Java entra en un loop infinito al parsear “2.2250738585072012e-308”

February 15, 2011
bug double java jvm oracle sun

Al igual que PHP lo hace con “2.2250738585072011e-308”, Java entra en un loop infinito al parsear el double “2.2250738585072012e-308”.

Esto ocurre en cualquier versión de la máquina virtual de sun por lo que afecta a todos los lenguajes basados en esta como JRuby, Scala, Groovy, Clojure, Jython, etc. El que quiera comprobarlo, no tiene que hacer más que compilar y ejecutar el siguiente programa:

class bug {
    public static void main(String[] args) {
        System.out.println("Test:");
        double d = Double.parseDouble("2.2250738585072012e-308");
        System.out.println("Value: " + d);
    }
}

El stack no se llena, no se lanza ninguna excepción. Simplemente entra en un loop infinito. Esto quiere decir que facilmente puede ser usado en ataques de negación de servicio (DoS) pues dicho loop mantendrá ocupado al thread que ejecute la llamada a Double#parseDouble(String) indefinidamente con lo que se vuelve fácil lograr que se ocupe todo el tiempo de procesador disponible.

¿Cómo se relaciona con el bug en PHP?

Aunque la máquina virtual está desarrollada con C/C++, el bug se encuentra dentro de código java. Específicamente en sun.misc.FloatingDecimal#doubleValue(). Sin embargo, este código parece estar basado en la función strtod de la biblioteca estándar de C en donde se encuentra el bug que provoca el loop en PHP.

¿Qué tan fácil es provocar un DoS?

Para empezar cualquier aplicación web que reciba parámetros en formato double muy probablemente en algún lugar llame Double#parseDouble(String). Y si creen que no es tan sencillo encontrar una aplicación web que reciba doubles como parámetros consideren JSON: JSON soporta números con punto flotante directamente en el lenguaje. Por lo tanto, es casi seguro que cualquier implementacion de JSON basada en la máquina virtual de sun entre en un loop infinito al evaluar algo como {“blah”: 2.2250738585072012e-308} incluso antes de ejecutar la lógica particular a la aplicación en cuestión! con lo que se vuelve vulnerable de manera automática cualquier servicio JSON basado en la máquina virtual. Por ejemplo, si tienen JRuby a la mano podrán comprobar que lo siguiente es afectado por el bug:

JSON.parse(‘{"blah": 2.2250738585072012e-308}’)

Asi pues, este bug es una vulnerabilidad seria de la máquina virtual. Lo peor, sin embargo, es que el bug es conocido desde hace 10 años! El bug fué registrado en el sistema de rastreo de errores de sun con el id 4421494, sin embargo, recientemente cuando volvió a salir a la luz este bug, Oracle, ahora propietario de java, lo eliminó pero aún se puede encontrar evidencia de el en google. Estos son los detalles del bug:

Bug ID: 4421494
Votes 1
Synopsis infinite loop while parsing double literal
Category java:classes_lang
Reported Against 1.3 , 1.4.1
Release Fixed
State 5-Cause Known, bug
Priority: 4-Low
Related Bugs 4396272 , 4749698 , 4887667 , 6876342
Submit Date 04-MAR-2001

De hecho existe un reporte relacionado desde el 2000 que Oracle aún no ha eliminado: 4396272.

Pues bién, Después de todo el revuelo que causó el redescubrimiento de este bug, Oracle finalmente publicó un fix que consiste en una aplicación java que actualiza la biblioteca rt.jar ejecutándo el siguiente comando:

java -jar fpupdater.jar -u -v

Via Exploring Binary

comments powered by Disqus