错误和错误处理代表一类 API。与错误处理相关的错误非常普遍,因此它们应该拥有自己的专属章节。与“API 滥用”一样,有两种情况可以引入与错误相关的安全漏洞:最常见的一种是错误处理不当(或者根本不处理)。第二种是产生错误,这些错误要么(向潜在的攻击者)泄露过多信息,要么难以处理。
NullPointerException
并不是一个好方法。NullPointerException
: NullPointerException
异常来标记错误状况。NullPointerException
异常。
try {
mysteryMethod();
}
catch (NullPointerException npe) {
}
NullReferenceException
并不是一个好方法。NullReferenceException
: NullReferenceException
异常来标记错误状况。NullReferenceException
。
try {
MysteryMethod();
}
catch (NullReferenceException npe) {
}
finally
块中返回会导致异常的丢失。finally
块中的返回指令会导致从 try 块中抛出的异常丢失。doMagic
方法,同时将参数 true
传递给该方法会导致抛出 MagicException
异常,该异常将不会传递给调用者。finally
块中的返回指令会导致异常的丢弃。
public class MagicTrick {
public static class MagicException extends Exception { }
public static void main(String[] args) {
System.out.println("Watch as this magical code makes an " +
"exception disappear before your very eyes!");
System.out.println("First, the kind of exception handling " +
"you're used to:");
try {
doMagic(false);
} catch (MagicException e) {
// An exception will be caught here
e.printStackTrace();
}
System.out.println("Now, the magic:");
try {
doMagic(true);
} catch (MagicException e) {
// No exception caught here, the finally block ate it
e.printStackTrace();
}
System.out.println("tada!");
}
public static void doMagic(boolean returnFromFinally)
throws MagicException {
try {
throw new MagicException();
}
finally {
if (returnFromFinally) {
return;
}
}
}
}
finally
块中返回会导致异常的丢失。finally
块中的返回指令会导致从 try 块中抛出的异常丢失。doMagic
方法,同时将参数 True
传递给该方法会导致抛出 exception
异常,该异常将不会传递给调用者。finally
块中的返回指令会导致异常的丢弃。"disappear before your very eyes!" . PHP_EOL;
echo "First, the kind of exception handling " .
"you're used to:" . PHP_EOL;
try {
doMagic(False);
} catch (exception $e) {
// An exception will be caught here
echo $e->getMessage();
}
echo "Now, the magic:" . PHP_EOL;
try {
doMagic(True);
} catch (exception $e) {
// No exception caught here, the finally block ate it
echo $e->getMessage();
}
echo "Tada!" . PHP_EOL;
function doMagic($returnFromFinally) {
try {
throw new Exception("Magic Exception" . PHP_EOL);
}
finally {
if ($returnFromFinally) {
return;
}
}
}
?>
ThreadDeath
错误,则出现问题的线程可能实际上并未终止。ThreadDeath
错误。如果捕获了 ThreadDeath
错误,则将其重新抛出非常重要,因为这样该线程才真正地终止。抛出 ThreadDeath
的目的是终止线程。如果 ThreadDeath
被抑制,则它可以阻止线程停止并导致意外行为,因为代码最初抛出 ThreadDeath
的目的是希望停止该线程。ThreadDeath
但未将其重新抛出。
try
{
//some code
}
catch(ThreadDeath td)
{
//clean up code
}
finally
块中的 throw
语句会通过 try-catch-finally
破坏逻辑进度。finally
块通常在其相应的 try-catch
块之后执行,该块通常用于自由分配的资源,例如文件句柄或数据库指针。由于破坏了正常的程序执行,在 finally
块中抛出异常会绕过关键的清除代码。 FileNotFoundException
时,将绕过对 stmt.close()
的调用。
public void processTransaction(Connection conn) throws FileNotFoundException
{
FileInputStream fis = null;
Statement stmt = null;
try
{
stmt = conn.createStatement();
fis = new FileInputStream("badFile.txt");
...
}
catch (FileNotFoundException fe)
{
log("File not found.");
}
catch (SQLException se)
{
//handle error
}
finally
{
if (fis == null)
{
throw new FileNotFoundException();
}
if (stmt != null)
{
try
{
stmt.close();
}
catch (SQLException e)
{
log(e);
}
}
}
}
javax.net.ssl.SSLHandshakeException
、javax.net.ssl.SSLKeyException
和 javax.net.ssl.SSLPeerUnverifiedException
都可以传达与 SSL 连接相关的重要错误。如果没有显式地处理这些错误,连接会被处于一种意想不到的、潜在不安全的状态。