Grave bug encontrado em conversão de String->Double em PHP aparece na JVM
41 respostas
P
Paulo_Silveira
Um simples e novo bug foi recém descoberto em todas as versões do Java. Um double d = Double.parseDouble(“2.2250738585072012e-308”); (o menor double possível) entra em loop infinito, assim como no PHP.
Ou mesmo se você escrever um código java com double d = 2.2250738585072012e-308; o compilador vai utilizar o Double.parseDouble internamente, fazendo o compilador travar em loop infinito.
Isso obviamente afeta JRuby, Scala, Clojure, etc. Pode ser também um ataque a formuários web que recebem parâmetros e convertem diretamente para Double, o que sempre pareceu ser uma operação segura.
O bug é só no parseDouble. Se você usa a constante diretamente não há chamada ao parseDouble.
Z
zoren
Sergio Lopes:
O bug é só no parseDouble. Se você usa a constante diretamente não há chamada ao parseDouble.
Mas os valores não são os mesmos.
Só próximos.
P
Paulo_Silveira
é um antes do Double.MIN_NORMAL, algo assim.
Faça algo como System.out.printf("%.20e", Double.MIN_NORMAL);
Mas qual valor ele representa exatamente não é relevante para o bug. A fragilidade é qualquer um que converta diretamente de uma String da web para double, esta sucetivel a isso. Exemplo Double.parseDouble(req.getParameter(“valor”));
D
danilomunoz
O meu eclipse tbm deu deadlock, mas é só dar stop nos processos de compilação.
M
Marky.Vasconcelos
Travou o eclipse também.
D
danilomunoz
Ops … melhor não fazerem no eclipse não …
tive que editar o código por fora (notepad) e remover a linha … pq não conseguia mais salvar pelo eclipse …
encheu um pouco o saco aqui … travou bem feio … rs.
Até mais,
J
Jose111
Aqui o eclipse travou também… mas acredito que foi porque eu usei esta forma:
drigo cuidado para não validar com parseDouble() kkkkk…
B
bobmoe
Paulo Silveira:
Um simples e novo bug foi recém descoberto em todas as versões do Java. Um double d = Double.parseDouble(“2.2250738585072012e-308”); (o menor double possível) entra em loop infinito, assim como no PHP.
impressionante, mas pelo jeito esse bug já tinha sido reportado desde o final de 2009:
No entanto, se você clicar neste link aí em cima, verá que ele não funciona. Quando a Oracle comprou a Sun, vários bugs cadastrados “misteriosamente” sumiram.
Bem, que eu saiba ele não foi consertado até hoje (na época a sun recusou o bug como sendo algo “não importante”). Trata-se do seguinte:
No entanto, se você clicar neste link aí em cima, verá que ele não funciona. Quando a Oracle comprou a Sun, vários bugs cadastrados “misteriosamente” sumiram.
Bem, que eu saiba ele não foi consertado até hoje (na época a sun recusou o bug como sendo algo “não importante”). Trata-se do seguinte:
No entanto, se você clicar neste link aí em cima, verá que ele não funciona. Quando a Oracle comprou a Sun, vários bugs cadastrados “misteriosamente” sumiram.
Bem, que eu saiba ele não foi consertado até hoje (na época a sun recusou o bug como sendo algo “não importante”). Trata-se do seguinte:
Imagina o que acontece se um hacker serializa a exceção para o servidor e o servidor faz o log dela?
Se o cadastro sumiu quer dizer que foi corrigido :twisted:
Bem, acabei de testar aqui (Java Hotspot Client VM, versão 1.6.0_22) para ver o que acontecia. Deu um StackOverflowError após ele gerar centenas de linhas de stacktrace repetido. Menos pior do que um loop infinito, mas ainda assim uma ferramenta muito útil para alguém atacar um servidor. :twisted:
A
Adelar
victorwss:
Bem, acabei de testar aqui (Java Hotspot Client VM, versão 1.6.0_22) para ver o que acontecia. Deu um StackOverflowError após ele gerar centenas de linhas de stacktrace repetido. Menos pior do que um loop infinito, mas ainda assim uma ferramenta muito útil para alguém atacar um servidor. :twisted:
Aí sim heim… bem melhor kkkkkk
Nem me impressiono tanto… quando mexia com C tinha coisa bem pior
N
namor
Deve ficar melhor ainda assim:
while(true){
double d = 2.2250738585072012e-308;
System.out.println("Value: " + d);
}
hahahahaha
A
Adelar
namor:
Deve ficar melhor ainda assim:
while(true){
double d = 2.2250738585072012e-308;
System.out.println("Value: " + d);
}
hahahahaha
Uma versão customizada… daí caso corrijam o problema lançando uma exceção ainda vai entrar em loop infinito :twisted:
public void bug(){
try{
while(true){
double d = Double.parseDouble("2.2250738585072012e-308");
}
}
catch(Exception e){
bug();
}
}
P
peczenyj
Não acontece com Ruby \o/
mas e o jruby?
P
peerless
No minimo a Sun não utilizava testes de cobertura :twisted:
A
Alexandre_Saudate
BigDecimal é seu amigo.
[]´s
D
dmitsuo
Pessoal, só a título de aprendizado com relação a esse bug, se houvessem testes unitários automatizados utilizando as condições de fronteira (valores mínimos, máximos e imediatamente anteriores e posteriores) isso não poderia ter sido evitado? Esse bug pode ser considerado uma prova de que a Sun não utiliza/utilizou testes unitários automatizados em sua base de código?
D
Diabo_Loiro
Se eu fosse malvado eu diria.
"Mandem este codigo por email para os amigos mais queridos testarem.
Comitem um metodo com esse codigo so para ver se cai o servidor "
Mais como sou bonzinho eu digo.
Use bigdecimal, para evitar problemas.
rs kkk
A
andreiribas
dmitsuo:
Pessoal, só a título de aprendizado com relação a esse bug, se houvessem testes unitários automatizados utilizando as condições de fronteira (valores mínimos, máximos e imediatamente anteriores e posteriores) isso não poderia ter sido evitado? Esse bug pode ser considerado uma prova de que a Sun não utiliza/utilizou testes unitários automatizados em sua base de código?
Teoricamente esse tipo de erro deveria ter sido capturado no TCK, que é o teste de compatibilidade da plataforma Java, mas aparentemente os caras não testavam o código mesmo.
Imagina só, um erro tão bobo demorou mais de 15 anos para ser descoberto (desconsiderando o bugtraq da sun claro :).
E
eduveks
Affff!!!
Passei um calafrio danado agora… só de ver isto passou pela minha cabeça todos os sites q fiz, mas ainda bem que pelo q eu recordo não há nenhum parametro do tipo double, integers/ids há as pancadas como é óbvio, só falta algum ID estar sendo validado com o parseDouble… ai eu corto os pulsos!!!
Bem, se os servidores começarem a dar problemas já sei q poderá ser disto…
Aqui no guj esta tudo seguro? :twisted:
O q vai ter de neguinho tentando travar os sites em Java por ai…
Espero q os meus queridos colegas fanáticos em .Net não venham me encher o sako com isto! Se bem que o .Net tb tem bugs arcáicos não resolvidos, mas não imaginava q o Java estivesse assim tb, eu pelo menos acho que nunca encontrei um bug, é q na verdade até posso ter encontrado um ou outro e pensado q o problema era do código…
M
max_rego
Um bug realmente existe, mas existe também um problema de interpretação matemática. O código abaixo roda normalmente e o parser também funciona, observer o comentário que coloquei no código.
Eu recomendo relamente validar e usar o BigDecimal para tratar formularios web, pois o caso acima realmente não evita um ataque ao server se vc estiver usando o parse double para valores científicos.
Testei no Netbean 6.9.1 e funciona normalmente como a saida abaixo. RECOMENDO NAO TENTAR DEPURAR O CODIGO ABAIXO, POIS VAI TRAVAR O IDE.
/** * Atencao nas casas decimais a direita do ponto, * a declaracao abaixo, 22250738585072014E-324, equivale extamente * ao numero 2.225073858507201E-308, mas observe que * 2.2250738585072012 eh diferente de 22250738585072012. * O motivo eh a limitacao do expoente -308, sendo que com * 2.2250738585072012 temos 16 casas apos o ponto, logo extrapola * o limite do double. * Exemplo para 2.50e-5 e 250e-7 que sao o mesmo numero * 0.0000250 */doublex=22250738585072014E-324;System.out.println("X: "+x);Stringv=String.valueOf(x);// o parser ocorre sem problemas, pois a representacao esta no limite// do couble.doubley=Double.parseDouble(v);System.out.println("Y1: "+y);// aqui tambem ocorre normalmente pois ainda esta no limite do doubley=Double.parseDouble("22250738585072014E-324");System.out.println("Y2: "+y);doublez=Double.MIN_NORMAL;System.out.println("Z: double MIN_NORMAL: "+z);// operacao ocorre normalmentedoublew=x-y;/** * convesrao sem problema feita pelo BigDecimal */BigDecimalb=newBigDecimal("2.2250738585072012e-308");System.out.println("B: "+b);/** * A T E N C A O * a chamada abaixo vai dar problema pois nao ha como * representar o numero acima em double. *///System.out.println("B: " + b.doubleValue());System.out.println("W: "+w);
A Oracle também já lançou updates pro JDK deles e um patch manual pra quem quiser aplicar. Fizeram um post dando umas desculpinhas pra não terem corrigido antes, já que o bug existe desde 2001:
No entanto, se você clicar neste link aí em cima, verá que ele não funciona. Quando a Oracle comprou a Sun, vários bugs cadastrados “misteriosamente” sumiram.
Bem, que eu saiba ele não foi consertado até hoje (na época a sun recusou o bug como sendo algo “não importante”). Trata-se do seguinte:
No entanto, se você clicar neste link aí em cima, verá que ele não funciona. Quando a Oracle comprou a Sun, vários bugs cadastrados “misteriosamente” sumiram.
Bem, que eu saiba ele não foi consertado até hoje (na época a sun recusou o bug como sendo algo “não importante”). Trata-se do seguinte:
Imagina o que acontece se um hacker serializa a exceção para o servidor e o servidor faz o log dela?
O que vc estava tentando fazer para descobrir isto? :shock: :shock: :shock:
Ele estava tentando descobrir o que a JVM faz quando uma exceção culpa a outra!
L
luistiagos
peerless:
Ele estava tentando descobrir o que a JVM faz quando uma exceção culpa a outra!
então estava só brincando… agora ta explicado o porque a sun recusou… pela própria natureza do negocio isto iria estourar a pilha,
é a mesma coisa que vc colocar 2 espelhos um refletindo o outro e querer que só um deles reflita e o outro não…
V
victorwss
Cara, tem alguns anos desde que achei este bug, não lembro o que eu estava fazendo.
Eu acho que eu estava usando o initCause em exceções que não recebiam a causa pelo construtor. Mas troquei alguma variável sem querer e saiu isso.
E embora este problema possa parecer ser supérfluo e sem importância, na verdade constitui-se em uma falha de segurança, pois um usuário mal-intencionado pode serializar estas exceções para um servidor. Assim como o bug do Double.parseFloat poderia parecer supérfluo porque nenhum usuário inocente digitaria um valor daquele, há o problema de que alguém mal-intencionado com certeza faria.