오류 및 오류 처리는 API 클래스를 나타냅니다. 오류 처리와 관련된 오류는 매우 흔하므로 따로 다룰 만한 내용입니다. "API 오용"과 마찬가지로 오류 관련 보안 취약성을 일으키는 두 가지 원인이 있습니다. 가장 흔한 것은 오류를 제대로(혹은 아예) 처리하지 못하는 것입니다. 두 번째는 (잠재적 공격자에게) 너무 많은 정보를 제공하거나 처리하기 어려운 오류를 발생시키는 것입니다.
+=
를 사용하여 변수에 숫자를 더하려고 했는데 코드를 =+
로 작성하더라도 작업은 정상적으로 실행되지만 덧셈이 수행되는 대신 변수가 다시 초기화됩니다.numberOne
변수에 숫자를 더하기 위해 작성한 것이지만 =+
연산자를 사용했으므로 실제로는 변수가 1로 다시 초기화됩니다.
uint numberOne = 1;
function alwaysOne() public {
numberOne =+ 1;
}
for
루프 문을 사용하여 send
외부 호출을 통해 모든 관련 주소에 대한 환불을 실행합니다.
function refundAll() public {
for(uint x; x < refundAddresses.length; x++) {
require(refundAddresses[x].send(refunds[refundAddresses[x]]));
}
}
...
EXEC CICS
INGNORE CONDITION ERROR
END-EXEC.
...
doExchange()
에서 드물게 발생하는 예외를 무시합니다.
try {
doExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
이 발생하더라도 프로그램은 아무 문제가 발생하지 않은 것처럼 계속 실행됩니다. 즉, 프로그램이 특수 상황을 나타내는 증거를 기록하지 않으므로 나중에 프로그램 동작을 파악하기가 어려워질 수도 있습니다.DoExchange()
에서 아주 드물게 발생하는 예외 사항을 무시합니다.
try {
DoExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
이 발생해도 프로그램은 아무 일도 없었던 것처럼 계속 실행됩니다. 프로그램은 특수한 상황을 나타내는 증거를 전혀 기록하지 않기 때문에 이후에 프로그램의 동작을 밝히려는 노력이 실패할 수 있습니다.doExchange()
에서 아주 드물게 발생하는 예외 사항을 무시합니다.
try {
doExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
이 발생해도 프로그램은 아무 일도 없었던 것처럼 계속 실행됩니다. 프로그램은 특수한 상황을 나타내는 증거를 전혀 기록하지 않기 때문에 이후에 프로그램의 동작을 밝히려는 노력이 실패할 수 있습니다.doExchange()
에서 아주 드물게 발생하는 예외 사항을 무시합니다.
try {
doExchange();
}
catch (exception $e) {
// this can never happen
}
RareException
이 발생해도 프로그램은 아무 일도 없었던 것처럼 계속 실행됩니다. 프로그램은 특수한 상황을 나타내는 증거를 전혀 기록하지 않기 때문에 이후에 프로그램의 동작을 밝히려는 노력이 실패할 수 있습니다.open()
에서 아주 드물게 발생하는 예외 사항을 무시합니다.
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except:
# This will never happen
pass
RareException
이 발생해도 프로그램은 아무 일도 없었던 것처럼 계속 실행됩니다. 프로그램은 특수한 상황을 나타내는 증거를 전혀 기록하지 않기 때문에 이후에 프로그램의 동작을 밝히려는 노력이 실패할 수 있습니다.
PROCEDURE do_it_all
IS
BEGIN
BEGIN
INSERT INTO table1 VALUES(...);
COMMIT;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
END do_it_all;
Exception
같은 높은 수준의 클래스를 catch하여 catch 블록을 "압축"하면 특수 처리가 필요하거나 프로그램의 이 시점에서 catch되지 않아야 하는 예외 사항을 숨길 수 있습니다. 지나치게 광범위한 예외 사항을 catch하면 .NET의 형식화된 예외 사항을 사용하는 의미가 사라지고 특히 프로그램이 커져서 새로운 형식의 예외 사항이 발생하기 시작하면 위험해질 수 있습니다. 새 예외 형식에는 주의를 기울이지 않기 때문입니다.
try {
DoExchange();
}
catch (IOException e) {
logger.Error("DoExchange failed", e);
}
catch (FormatException e) {
logger.Error("DoExchange failed", e);
}
catch (TimeoutException e) {
logger.Error("DoExchange failed", e);
}
try {
DoExchange();
}
catch (Exception e) {
logger.Error("DoExchange failed", e);
}
DoExchange()
가 수정되어 다른 방식으로 처리해야 하는 새로운 형식의 예외 사항이 발생하면 광범위한 catch 블록 때문에 컴파일러가 문제를 지적할 수 없습니다. 뿐만 아니라, 새 catch 블록은 ApplicationException
및 NullReferenceException
유형의 예외 사항도 처리하는데 이는 프로그래머의 의도와 반대되는 것입니다.Exception
같은 높은 수준의 클래스를 catch하여 catch 블록을 "압축"하면 특수 처리가 필요하거나 프로그램의 이 시점에서 catch되지 않아야 하는 예외 사항을 숨길 수 있습니다. 지나치게 광범위한 예외 사항을 catch하면 Java의 형식화된 예외 사항을 사용하는 의미가 사라지고 특히 프로그램이 커져서 새로운 형식의 예외 사항이 발생하기 시작하면 위험해질 수 있습니다. 새 예외 형식에는 주의를 기울이지 않기 때문입니다.
try {
doExchange();
}
catch (IOException e) {
logger.error("doExchange failed", e);
}
catch (InvocationTargetException e) {
logger.error("doExchange failed", e);
}
catch (SQLException e) {
logger.error("doExchange failed", e);
}
try {
doExchange();
}
catch (Exception e) {
logger.error("doExchange failed", e);
}
doExchange()
가 수정되어 다른 방식으로 처리해야 하는 새로운 형식의 예외 사항이 발생하면 광범위한 catch 블록 때문에 컴파일러가 문제를 지적할 수 없습니다. 뿐만 아니라, 새 catch 블록은 ClassCastException
및 NullPointerException
과 같이 RuntimeException
에서 파생된 예외 사항도 처리하는데 이는 프로그래머의 의도와 반대되는 것입니다.Exception
또는 Throwable
이 발생하도록 선언하면 호출자가 올바른 오류 처리 및 오류 복구 작업을 수행하기 어렵습니다. Java의 예외 메커니즘은 호출자가 손쉽게 잘못을 예상하고 각각의 고유한 예외 상황을 처리하기 위한 코드를 쓸 수 있도록 설계되어 있습니다. 일반적인 형태의 예외 사항이 발생하도록 메서드를 선언하면 이런 메커니즘이 아무 소용이 없습니다.
public void doExchange()
throws IOException, InvocationTargetException,
SQLException {
...
}
public void doExchange()
throws Exception {
...
}
doExchange()
의 이후 수정 버전에서 이전 예외 사항과 다르게 처리해야 하는 새 형식의 예외 사항을 도입하는 경우 이 요구 사항을 쉽게 적용할 수 없습니다.