Los errores y su tratamiento representan una clase de API. Los errores relacionados con el tratamiento de errores son tan comunes que se merecen una sección por sí mismos. Tal como sucede con los "abusos de la API", hay dos formas de presentar una vulnerabilidad de seguridad relacionada con los errores: la más común es tratar los errores inadecuadamente (o no llegar a hacerlo). La segunda es producir errores que dan demasiada información (a posibles atacantes) o que son difíciles de tratar.
...
EXEC CICS
INGNORE CONDITION ERROR
END-EXEC.
...
doExchange()
.
try {
doExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
, el programa continuaría ejecutándose como si no hubiera ocurrido nada inusual. El programa no registra ninguna evidencia que aluda a la situación especial, lo que podría frustrar cualquier intento posterior de explicar el comportamiento del programa.DoExchange()
.
try {
DoExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
se fuese a iniciar en algún momento, el programa seguiría ejecutándose como si no hubiese ocurrido nada inusual. El programa no registrará ninguna prueba que indique la situación especial, evitando potencialmente cualquier intento posterior de explicar el comportamiento del programa.doExchange()
.
try {
doExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
se fuese a iniciar en algún momento, el programa seguiría ejecutándose como si no hubiese ocurrido nada inusual. El programa no registrará ninguna prueba que indique la situación especial, evitando potencialmente cualquier intento posterior de explicar el comportamiento del programa.doExchange()
.
try {
doExchange();
}
catch (exception $e) {
// this can never happen
}
RareException
se fuese a iniciar en algún momento, el programa seguiría ejecutándose como si no hubiese ocurrido nada inusual. El programa no registrará ninguna prueba que indique la situación especial, evitando potencialmente cualquier intento posterior de explicar el comportamiento del programa.open()
.
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except:
# This will never happen
pass
RareException
se fuese a iniciar en algún momento, el programa seguiría ejecutándose como si no hubiese ocurrido nada inusual. El programa no registrará ninguna prueba que indique la situación especial, evitando potencialmente cualquier intento posterior de explicar el comportamiento del programa.
PROCEDURE do_it_all
IS
BEGIN
BEGIN
INSERT INTO table1 VALUES(...);
COMMIT;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
END do_it_all;
Exception
, se pueden ocultar excepciones que requieran un tratamiento especial o que no se deberían obtener en este punto del programa. Si se obtiene una excepción demasiado amplia, básicamente hace fracasar el propósito de las excepciones tipificadas de .NET, y puede resultar particularmente peligroso si el programa se desarrolla y comienza a iniciar nuevos tipos de excepciones. Los nuevos tipos de excepciones quedarán desatendidas.
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()
para iniciar un nuevo tipo de excepción que debería tratarse de forma diferente, el amplio bloque catch evitará que el compilador señale la situación. Además, ahora el bloque catch nuevo tratará también excepciones de los tipos ApplicationException
y NullReferenceException
, lo cual no es el propósito del programador.Exception
, se pueden ocultar excepciones que requieran un tratamiento especial o que no se deberían obtener en este punto del programa. Si se obtiene una excepción demasiado amplia, básicamente hace fracasar el propósito de las excepciones tipificadas de Java, y puede resultar particularmente peligroso si el programa se desarrolla y comienza a iniciar nuevos tipos de excepciones. Los nuevos tipos de excepciones quedarán desatendidas.
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()
para iniciar un nuevo tipo de excepción que debería tratarse de forma diferente, el amplio bloque catch evitará que el compilador señale la situación. Es más, el nuevo bloque de filtrado ahora también administra las excepciones derivadas de RuntimeException
como ClassCastException
y NullPointerException
, que no es el propósito del programador.Exception
o Throwable
dificulta a los autores de llamada hacer un buen trabajo en cuanto al tratamiento y la recuperación de errores. El mecanismo de excepciones de Java se ha configurado para facilitar a los autores de llamada la anticipación de qué puede salir mal y escribir código para administrar cada circunstancia de excepción específica. Declarar que un método lance una forma genérica de excepción frustra este sistema.
public void doExchange()
throws IOException, InvocationTargetException,
SQLException {
...
}
public void doExchange()
throws Exception {
...
}
doExchange()
introduce un nuevo tipo de excepción que debería tratarse de forma diferente a las excepciones anteriores, no hay una forma fácil de exigir este requisito.NullPointerException
.NullPointerException
bajo tres circunstancias: NullPointerException
para señalar una condición de error.NullPointerException
.
try {
mysteryMethod();
}
catch (NullPointerException npe) {
}
NullReferenceException
.NullReferenceException
bajo tres circunstancias: NullReferenceException
para señalar una condición de error.NullReferenceException
.
try {
MysteryMethod();
}
catch (NullReferenceException npe) {
}
finally
provocará que las excepciones se pierdan.finally
provocará que todas las excepciones que se puedan lanzar en el bloque try se descarten.MagicException
lanzada por la segunda llamada para doMagic
con true
transferido a ella nunca se entregará al autor de llamada. La instrucción return dentro del bloque finally
provocará que la excepción se descarte.
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
provocará que las excepciones se pierdan.finally
provocará que todas las excepciones que se puedan lanzar en el bloque try se descarten.exception
lanzada por la segunda llamada para doMagic
con True
transferido a ella nunca se entregará al autor de llamada. La instrucción RETURN dentro del bloque finally
provocará que la excepción se descarte."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
no se vuelve a lanzar, el subproceso en cuestión podría no acabar.ThreadDeath
solo deben filtrarse si una aplicación tiene que limpiar después de finalizar de forma asíncrona. Si se filtra un error ThreadDeath
, es importante que se vuelva a lanzar para que el subproceso finalice realmente. El propósito de lanzar ThreadDeath
es detener un subproceso. Si ThreadDeath
es absorbido, puede impedir que un subproceso se detenga y dé lugar a un comportamiento inesperado, puesto que quien haya lanzado originalmente ThreadDeath
espera que el subproceso se detenga.ThreadDeath
, pero no lo vuelve a lanzar.
try
{
//some code
}
catch(ThreadDeath td)
{
//clean up code
}
throw
dentro de un bloque finally
rompe la progresión lógica de try-catch-finally
.finally
siempre se ejecutan después de su bloque try-catch
correspondiente y se utilizan frecuentemente para liberar recursos asignados, como controladores de archivos o cursores de base de datos. Lanzar una excepción en un bloque finally
puede derivar el código de limpieza crítico, puesto que la ejecución normal del programa se interrumpirá. stmt.close()
se deriva cuando se lanza la FileNotFoundException
.
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
y javax.net.ssl.SSLPeerUnverifiedException
transmiten errores importantes relacionados con una conexión SSL. Si estos errores no se administran explícitamente, la conexión puede dejarse en un estado inesperado y potencialmente inseguro.