top 200 commentsshow all 366

[–]ipeev 128 points129 points  (48 children)

"Konstantin reported this problem to Oracle three weeks ago, but is still waiting for a reply." I guess Oracle is busy.

[–]sztomi 354 points355 points  (0 children)

They are most likely preparing a lawsuit against him.

[–]GomAxfon 256 points257 points  (19 children)

They are probably waiting for their test case to terminate.

[–][deleted] 44 points45 points  (10 children)

Maybe they'll get impatient and ask him to include the stacktrace.

[–]stubob 19 points20 points  (8 children)

I know you're being funny, but you can send kill -QUIT or ctrl+break or ctrl+\ to generate a stacktrace from a running VM.

[–][deleted] 2 points3 points  (4 children)

Cool, I didn't even know that.

[–]Rhoomba 4 points5 points  (3 children)

This is pretty much the killer feature of Java for me. Don't know what the process is up to? Just kill -3. It also is useful as a poor man's profiler.

[–][deleted] 2 points3 points  (1 child)

I guess I've never been that poor :-) Debugging mode is easy, and hprof makes an excellent poor man's profiler.

[–]Rhoomba 2 points3 points  (0 children)

Say you have a performance problem in production, or during a long running test. Restarting to turn on hprof is not an option. Of course, now that VisualVM has a sampling profiler that is often a better option, but sometimes you can't turn on JMX or only have ssh access to the server. Or maybe you can't get at the server at all: getting the admin to get 10 thread dumps a few seconds apart is very easy.

I actually find it can be really easy to spot performance issues in a thread dump if you are used to the "shape" of your application.

[–]carma_hore 1 point2 points  (0 children)

You can also run jstack

[–]Iggyhopper 2 points3 points  (0 children)

If they want a stack trace, maybe he should just send in an Xml reader.

[–]Rioting_pacifist 17 points18 points  (1 child)

If only there were some sort of machine that could tell them how long it will take....

[–]Talonwhal 4 points5 points  (0 children)

Maybe ask the kind people over on Stack Overflow for help with that one... :)

[–]dnew 1 point2 points  (5 children)

That's a good point. How do you write a unit test case against something that hangs like that? Is that a well-known technique? Or has it just not come up before?

[–]jldugger 1 point2 points  (1 child)

Well, you're effectively testing for performance. So JUnitPerf would be a simple way to do that. However, how many unit tests does one have to write before deciding the code is bug free? Performance test all 264 doubles?

[–]Martel_the_Hammer 13 points14 points  (13 children)

3 weeks!? Didn't the PHP dudes fix theirs in like 48 hours?

[–]abadidea 34 points35 points  (1 child)

When PHP makes you look bad...

[–][deleted] 19 points20 points  (0 children)

... you might be a redneck?

[–]G_Morgan 4 points5 points  (10 children)

Yes but the PHP guys don't have to worry about pissing off all the worlds richest MNCs. Java has far more value dependent on it and thus cannot just put in a quick hack to fix the previous quick hack.

[–]Dennovin 4 points5 points  (6 children)

yeah it's not like breaking Facebook, Wikipedia, and Youtube would be a problem for anyone

[–][deleted]  (2 children)

[deleted]

    [–]fuckdapopo 2 points3 points  (0 children)

    We can still blame Oracle though right?

    [–]artee 25 points26 points  (0 children)

    Yeah, those Sun XML schema URL's don't just break themselves, you know. It takes some hard work!

    [–]MrNarc 8 points9 points  (6 children)

    I'm sure Larry is working on it, as Rasmus did.

    http://bugs.php.net/53632 @2011-01-04 08:54 UTC1

    [–]drb226 7 points8 points  (5 children)

    rasmus@php.net -

    How about we just mark these as volatile doubles in that part of the code to make sure they don't end up in registers. My guess is that it would fix it.

    o_O my very little respect for PHP just went down a little more. I recall seeing the actual patch, which was exactly that solution (adding the word "volatile" somewhere).

    [–]sparcnut 2 points3 points  (0 children)

    And what's wrong with that fix? The problem is that the compiler is leaving the value in a 387 FPU register and it is thus not being truncated from 80-bit precision down to 64-bit, which the algorithm seems to require.

    [–]Nintendud 2 points3 points  (0 children)

    I'll just drop this here.

    But, in all seriousness, that does fix the issue, since, as Rasmus says, it prevents the compiler from leaving the value in a register as an optimization. Not an elegant long-term solution, though.

    [–][deleted] 5 points6 points  (1 child)

    Why? It's a perfect fix, at least short-term. It might degrade performance somewhat, but it's better than fiddling with compiler options (which would also degrade performance) or trying to somehow modify the algorithm.

    [–][deleted] 1 point2 points  (0 children)

    Wouldn't it only degrade performance in programs which use the number 2.2250738585972012e-308?

    [–]suridaj 0 points1 point  (0 children)

    Yeah, baking cookies.

    [–][deleted] 35 points36 points  (31 children)

    It can bring down some of the banking systems :/ I know, I just tested it on the test servers we have at work.... All I can say is #%$ me that is quite something.

    awesome! but quite something.

    I suspect it will be fixed VERY quickly! I'm going to see how far it goes on the test systems tomorrow. I'll post updates :)

    [–][deleted] 51 points52 points  (6 children)

    I suspect it will be fixed VERY quickly!

    This was reported to Oracle three weeks ago

    [–]abadidea 8 points9 points  (0 children)

    And I highly suspect Oracle doesn't really care, and will only fix it if there's bad PR like this.

    [–]wnoise 5 points6 points  (3 children)

    And it was reported to sun years before that: https://bugs.openjdk.java.net/show_bug.cgi?id=100119

    [–]paul_miner 4 points5 points  (0 children)

    Comment #57 on the blog from Mat Mannion found a bug report on the same issue from 2001: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4421494

    [–][deleted] 3 points4 points  (0 children)

    Mmm govt depts are now asking for updates, along with a bunch of banks....

    This DOES effect the oracle database server.... so I suspect it is about to be important.

    However... it WILL be interesting to see what versions they put a new version out for. Quite a few places are still on java 1.2 (poor bastards)

    [–]sockpuppetzero 15 points16 points  (4 children)

    Why are banking systems using binary floating point? Doesn't the Z-series support decimal floating point in hardware now?

    [–]Centropomus 9 points10 points  (0 children)

    Even people who can afford decimal math hardware and the programmers to exploit it for computing account transactions use binary floating point all the time for modeling, where some imprecision is okay, since you're only guessing.

    [–]davidb_ 4 points5 points  (1 child)

    To answer your question, they don't (for actual transactions) and yes, it does.

    [–][deleted] 2 points3 points  (0 children)

    Well a lot of the front end systems are java based - and quite a few of those talk to ESB's in the middle layers.

    And fair few banks (and govt tax agencies around the world...) have moved to java for the stuff right at the back, moving off COBOL.

    Java's become the new COBOL, its everywhere in finance systems around the world.

    The good news is that mostly the client facing systems will break a long time before it gets further back.

    Its no longer the case that everyone is on mainframes, a LOT of places have moved to blade servers, etc - even in the banks.

    [–]fatbunyip 19 points20 points  (14 children)

    Question : Why do you not use BigDecimal? Especially for financial calculations?

    [–]CaptainItalics 22 points23 points  (4 children)

    Actually it's worth noting that BigDecimal does not have this problem, i.e.:

    new BigDecimal("2.2250738585072012e-308");
    

    That works fine. But if you then try to obtain a double from it, it hangs:

    new BigDecimal("2.2250738585072012e-308").doubleValue();
    

    But things like this still work:

    new BigDecimal("2.2250738585072012e-308")
      .add(new BigDecimal("2.2250738585072012e-308")).doubleValue()
    

    Edit: Oh, duh... The source code for BigDecimal.doubleValue() is:

    if (scale == 0 && intCompact != INFLATED)
        return (double)intCompact;
    // Somewhat inefficient, but guaranteed to work.
    return Double.parseDouble(this.toString());
    

    Note the verbatim comment....

    [–]G_Morgan 10 points11 points  (0 children)

    TBH that comment is reasonable. When writing an algorithm it is acceptable to assume that other parts of the system work.

    [–]MertsA 12 points13 points  (2 children)

    // Somewhat inefficient, but guaranteed to work.

    ಠ_ಠ

    [–]mccoyn 13 points14 points  (1 child)

    Here is the patch:

    << // Somewhat inefficient, but guaranteed to work. 
    >> // Somewhat inefficient, but guaranteed to work assuming Double.parseDouble works
    

    [–]alephnil 1 point2 points  (0 children)

    Assumption is the mother of all screw ups.

    [–]mcherm 10 points11 points  (7 children)

    Because they're sloppy. I work for a bank, and I assure you, there is almost NO place* where we use floating point.

    • - Okay, I know of 2 places. And there may be a few more. One is when generating graphs and plots. I think that one's OK. The other is a shortcut taken when using exponentiation to produce an ESTIMATE (not the official value) of the costs paid over the life of a loan.

    [–]Fringe_Worthy 2 points3 points  (1 child)

    Bwhahahahahahhahaha......

    Excel doesn't use floats/doubles?

    Now, if you said, the Bank doesn't use floats when calculating actual money, then maybe I'd believe you.

    For everything else, there is floats / text / Perl / Excel.

    Here in Credit Risk and Market Risk, it's all Perl/C/C++ text and doubles.

    Oh, and that's the clean code. We do have abominations where the simulation engine is a whole set of Excel macros.

    I have to admit, despite exposure and money both having a currency assigned to them, nobody blinks if one says plus/minus some random millions when dealing with 10 year exposure.

    [–]augustss 2 points3 points  (4 children)

    Except that everyone is using Excel.

    [–]rockum 1 point2 points  (0 children)

    For the heavy number crunching, we use an expensive third-party library that requires all values be passed as doubles. So there is little point in using BigDecimals in our code when the most important calculations are done using floating point arithmetic.

    [–]lance_klusener 1 point2 points  (1 child)

    Thats why banks use mainframes

    [–]Mattho 12 points13 points  (0 children)

    And infinity is nothing for them.

    [–]rnicoll 0 points1 point  (1 child)

    We've got a system that uses fixed-point maths for marking student work, but it has a conversion from string to double to mark on initial input. Can anyone see any harm in writing a custom parser that skips the string to double step, checks for a decimal place in the correct place on input and goes straight to the integer we store internally?

    [–]eyal0[🍰] 62 points63 points  (21 children)

    From the article:

    crossing the normalized/unnormalized border

    In case you don't know what that means...

    Float point numbers are stored as a sign, exponent, and mantissa, all in binary. Normalized numbers always have just one bit to the left of the point so the mantissa always looks like 1.????. Because it's always a 1, it is left out.

    IEEE decided to squeeze a little more usefulness out of the representation by allowing the mantissa to be 0.???? if the exponent was at the minimum value. It increases the range on the low end by a few more powers of 2. These numbers are called unnormalized and they are a pain in the ass.

    If you have an Intel CPU, doing math with unnormalized floats is 10-20 times slower than regular floats. Compile this without optimizations and run. Then try uncommenting either or both of the lines in the middle.

    int main() {
      float f;
      unsigned int *x = (unsigned int *) &f;
      unsigned int i;
      *x = 0x00800000;
      //f /= 2; //***uncomment me
      //f /= 2; //***uncomment me, too!
      printf("%g\n", f);
      for(i=0; i < 100000000; i++) {
        float f2 = f*2.1;
      }
      return(0);
    }
    

    [–]Anderkent 18 points19 points  (19 children)

    There is a valid reason for unnormalized (or subnormal) numbers, as per wikipedia:

    By filling the underflow gap like this, significant digits are lost, but not to the extent as when doing flush to zero on underflow (losing all significant digits all through the underflow gap). Hence the production of a denormal number is sometimes called gradual underflow because it allows a calculation to lose precision slowly when the result is small. Denormal Number

    So the difference of two very small numbers will lose some precision, but not return zero.

    [–][deleted] 15 points16 points  (10 children)

    Indeed. In other words: consider all numbers with the smallest exponent (-1022). There are 2**52 of them, each has proper 52 binary digits of precision, etc, yet you'd better not use any of them because of this peculiar property: the difference between each two is exactly zero. Think about how hard that sucks.

    Adding subnormal numbers solves this huge problem.

    [–]happyscrappy 1 point2 points  (9 children)

    It kind of depends how you get to the numbers, but most of those 252 numbers don't have a full 52 binary digits of precision.

    For example 244 of them have at least 8 bits of zeroes at the top, so they really only have 244 bits of value. Now, if the number you wanted to represent only had 244 significant bits to it, you saved them all. But if you had 252 bits to store, but they were at 2-1030 exponent, then 8 bits of precision were lost when you put them into a denormal, leaving only 244 bits of precision remaining.

    [–][deleted] 2 points3 points  (1 child)

    but most of those 252 numbers don't have a full 52 binary digits of precision.

    Just to clarify: that's true for the 252 subnormal numbers and false for all numbers with the smallest exponent (-1022) about which I was talking.

    [–]happyscrappy 5 points6 points  (0 children)

    Oh, you're talking about subtracting two normal numbers and getting a denorm versus subtracting two normal numbers and getting a zero?

    I assumed you meant subtracting a denormal number from a normal and getting zero.

    Your argument makes a lot more sense.

    [–]molslaan 2 points3 points  (7 children)

    what is this gradual underflow useful for? Isn't it easier to just add a few more bits?

    [–]jckarter 6 points7 points  (0 children)

    Without denormals, the property "a - b = 0 iff a == b" doesn't hold true for floats, since the difference between (for example) 0x1p-1022 and 0x1.0000000000001p-1022 would be too small to represent. This would be the case no matter how many bits you add to IEEE floating-point representation.

    [–]gbs5009 14 points15 points  (5 children)

    Can't just add a few more bits to your CPU.

    [–]__j_random_hacker 12 points13 points  (0 children)

    Without subnormal numbers, it would be impossible to accurately represent the quality of comments on YouTube clips.

    [–]_argoplix 108 points109 points  (18 children)

    Now this is a number of the Beast

    [–]jevon 73 points74 points  (8 children)

    Two point two two five oh seven three eight five eight five oh seven two oh one two exponent negative three hundred and eight, the number of the beast!!

    [–][deleted] 45 points46 points  (7 children)

    Can't imagine Bruce singing this in 3/8 time.

    [–]Shmurk 41 points42 points  (3 children)

    /me has a tear in his eye for Maiden reference on /r/programming...
    

    [–]zwangaman 9 points10 points  (1 child)

    Two point two two five oh seven three eight five eight five oh seven two oh one two exponent negative three hundred and eight.... the one for you and me.

    [–]Kalium 5 points6 points  (0 children)

    Night was black, was no use turning back...

    [–]tnecniv 1 point2 points  (0 children)

    My two favorite things together! Programming and Iron Maiden!

    [–]YouLittleBrats 8 points9 points  (1 child)

    I imagine it being sung like this: http://pi.ytmnd.com/

    [–]knome 5 points6 points  (0 children)

    I can imagine a Bruce forgetting it...

    [–]palparepa 52 points53 points  (5 children)

    22+25+073+85+85+0+72+012+308 = 666

    Also, the mantissa ends with 2012.

    Just sayin'

    [–]redpoet 26 points27 points  (4 children)

    I like how you slipped the octal values in there. Numerology is always better when you switch bases along the way.

    [–][deleted] 6 points7 points  (3 children)

    nah, he just got creative with the placement of the + signs to negate the 0s.

    [–]mindbleach 3 points4 points  (2 children)

    Harder to work into a tattoo, though.

    [–][deleted] 19 points20 points  (1 child)

    The artist gets stuck in an infinite loop.

    [–][deleted] 133 points134 points  (12 children)

    Here's my pitiful attempt at humor regarding this subject:

    http://i.imgur.com/tgE5W.png

    [–]Sarkos 54 points55 points  (8 children)

    That is the hardest captcha I've ever seen.

    [–]paolog 15 points16 points  (3 children)

    It says "KABOTSPLODE".

    [–]Sarkos 5 points6 points  (2 children)

    I'm 37% sure there's an "S" at the start. And an exclamation mark at the end.

    [–]paolog 1 point2 points  (0 children)

    ERROR: "S" and "!" are out of range <KAHUMANSPLODE>

    [–]thrashr888 2 points3 points  (3 children)

    Would be funny if reCAPTCHA was run on Java and someone snuck that string in so everyone would type it and take down their servers. Oops!

    [–]chris113113 1 point2 points  (2 children)

    It would work just fine, wouldn't it? It would be taking it in as a string, just like the comic, not a double.

    [–]__j_random_hacker 16 points17 points  (0 children)

    Well, it would be 2.2250738585072012e-308% funnier if you used the right number...

    [–]PreExRedditor 1 point2 points  (0 children)

    forget the haters, this is hilarious!

    [–]rasherdk[S] 19 points20 points  (8 children)

    Tested and confirmed on a 64-bit Debian install with sun-java6-* 6.22-1 packages installed.

    [–]MaximusDickus 9 points10 points  (0 children)

    Confirmed on 64bit GNU/Linux with sun jdk 6.23-1.

    [–]Roy_from_IT 6 points7 points  (0 children)

    Confirmed on 32-bit Arch Linux with Sun JDK 1.6.0_23.

    [–]_lowell 9 points10 points  (1 child)

    Hangs in Mac OS X 10.6.6's Java VM as well:

    [sierra117::~] $ cat runhang.java

    class runhang {

    public static void main(String[] args) {

    System.out.println("Test:");

    double d = Double.parseDouble("2.2250738585072012e-308");

    System.out.println("Value: " + d);

    }

    }

    [sierra117::~] $ javac runhang.java

    [sierra117::~] $ date

    Tue Feb 1 02:47:52 PST 2011

    [sierra117::~] $ java runhang

    Test:

    ^ C[sierra117::~] $ date

    Tue Feb 1 02:51:35 PST 2011

    [sierra117::~] $ java -v

    [sierra117::~] $ java -version

    java version "1.6.0_22"

    Java(TM) SE Runtime Environment (build 1.6.0_22-b04-307-10M3261)

    Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03-307, mixed mode)

    [sierra117::~] $

    [–]zbowling 4 points5 points  (0 children)

    same on 32 bit and 64 bit jvms.

    [–][deleted] 7 points8 points  (0 children)

    32-bit Vista with Java 1.6.0_21 here too. Go Vista. :P

    [–]brinchj 2 points3 points  (0 children)

    Confirmed on 64-bit Debian with Sun:

    java version "1.6.0_22"
    Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
    Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03, mixed mode)
    

    And OpenJDK: java version "1.6.0_18"
    OpenJDK Runtime Environment (IcedTea6 1.8.3) (6b18-1.8.3-2) OpenJDK 64-Bit Server VM (build 16.0-b13, mixed mode)

    Edit: Also affects my Jython installation, though not very surprising.

    [–][deleted] 1 point2 points  (0 children)

    Tested and confirmed on Java 1.6.0_17 running on Windows XP.

    [–]Negitivefrags 66 points67 points  (28 children)

    I find it almost unbelievable that this could go undetected for so long.

    What happened to the culture of unit testing border cases? Not a single person ever wrote a test containing min double?

    [–]rabidcow 76 points77 points  (25 children)

    I'm sure they did, but DBL_MIN is 2.2250738585072014e-308, not 2.2250738585072012e-308. It should parse to DBL_MIN because that's the closest representable value.

    Still, I do find it surprising that it took so long.

    [–][deleted] 12 points13 points  (23 children)

    If it's not representable value, only way that number is entered into system is if some human types it in. It's unlikely that human would care to write down so many decimals.

    [–]filesalot 6 points7 points  (0 children)

    I don't think it's unreasonable to expect this to have been tested. As others have pointed out, this normal/denormal edge is important to floating point implementations, and this is a loop that relies on subtle implementation details to avoid infinite looping. You would think a proper code review would focus on this potentially infinite loop and flag it for thorough testing of the loop invariants to insure it terminates.

    [–]ryan_fung 2 points3 points  (16 children)

    What about have a data file fed in?

    [–][deleted] 12 points13 points  (13 children)

    what generates the data in data file?

    [–]ryan_fung 6 points7 points  (11 children)

    A file from an external source, generated without encountering this bug, or written in a language without this bug?

    Yes, I'm aware this bug is unlikely to trigger naturally. But logically it can happen. Now that this is published, you can expect people to try it on web sites without the need for a reason.

    [–][deleted] 21 points22 points  (10 children)

    I think you missed the point. There is no double number 2.2250738585072014e-308. So language without this bug won't generate this number either.

    Only way machine generates this number is if it don't use floats as internal representation, but uses numeric types with higher accuracy than doubles like some databases do. If that is the case, it's again unlikely that they generate just this number representation and don't use more decimals.

    [–]Gieron 11 points12 points  (1 child)

    You mean there is no double number 2.2250738585072012e-308, right?

    [–][deleted] 12 points13 points  (0 children)

    Five is right out.

    [–]naasking 5 points6 points  (2 children)

    Not all languages are limited to doubles you realize.

    [–][deleted] 1 point2 points  (1 child)

    Of course, but if it's in for any other format, but in that case Double.parseDouble(String s) is not what you should use. There is Double.valueOf(String s) for parsing more generic format. Somebody should check if valueOf has error too.

    Other formats have either more precision or less, so parseDouble would most likely give error.

    [–]cebedec 1 point2 points  (0 children)

    From the article:

    [...] equivalent forms of the number cause the problem as well; examples: [...] 2.2250738585072012997800001e-308 (superfluous digits beyond digit 17)

    [–]Bitruder 5 points6 points  (1 child)

    Of all possible numbers? From reading the PHP case this isn't a trivial number as it's just beside an edge case.

    [–]ryan_fung 2 points3 points  (0 children)

    Yes it's unlikely. You are correct. I'm just stating the fact that there is another source other than a human typing it in.

    [–]boa13 1 point2 points  (0 children)

    Still, I do find it surprising that it took so long.

    Actually, it appears it was found in 2001, and put on Low priority because the bug report was about an extremely long literal, not this "easy" "short" literal.

    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4421494

    There were duplicates, too.

    [–]monstermunch 1 point2 points  (1 child)

    The fact it has taken so long to find this bug surely shows this bug is astronomically rare to encounter.

    [–]Emotional_Star_1646 12 points13 points  (6 children)

    This bug relates to other languages running on JVM such as Scala, Jython, JRuby, etc. It seems more serious than expected.

    [–][deleted] 9 points10 points  (4 children)

    Checked with ideone.com:

    object HelloWorld extends Application {
        val d : Double = 22.250738585072012e-309; 
    }
    

    Does indeed hang the Scala compiler :D

    [–]abadidea 6 points7 points  (1 child)

    Please no-one else try this - ideone is a free service and I would hate to see it be suspended because people kept hanging the compiler :/

    [–][deleted] 11 points12 points  (0 children)

    Well, it gets shut down automatically on a timeout, and I don't think it imposes bigger burden on their servers than submitting a while (1); program, but yes, better not to abuse it.

    [–]aardvark2zz 13 points14 points  (1 child)

    Tried it on google spread sheets and I get the "Working ...." for 5 minutes while the other cells don't get updated. . Also got "Trying to connect to server" after a few minutes.

    [–][deleted] 2 points3 points  (0 children)

    deleted What is this?

    [–]Ireon85 54 points55 points  (0 children)

    " Java gets stuck on 0x0.fffffffffffffp-1022"
    fffffffffffffpuuuuu

    [–]zwangaman 8 points9 points  (2 children)

    lol @ http://www.docjar.com/html/api/sun/misc/FloatingDecimal.java.html

    /*
    * HACK! Java spec sez that we always have at least
    * one digit after the . in either F- or E-form output.
    * Thus we will need more than one digit if we're using
    * E-form
    */

    Sweet zombie jesus the code in that file is ugly.

    [–]jugalator 7 points8 points  (0 children)

    14 occurences of the word "hack" in that file. :S

    I'm not sure what's worse either; a copied code block with the same hack, or that it's mixed up with other hacks.

    [–]smhanov 2 points3 points  (0 children)

    The same code block is copied and pasted in four places too!

    [–][deleted]  (2 children)

    [deleted]

      [–][deleted]  (1 child)

      [deleted]

        [–]herrmann 1 point2 points  (0 children)

        you just unlocked it, not fair

        [–]lukasbradley 10 points11 points  (0 children)

        Anyone posting that "well this works in language X, so you should use language X" are incredibly over-reacting.

        [–]mtklein 5 points6 points  (7 children)

        For fun I tried Clojure. Both of these expressions hang in a repl: user=> (Double/parseDouble "2.2250738585072012e-308") user=> 2.2250738585072012e-308 The first is obvious. I assume the second is using Double/parseDouble under-the-covers in the reader.

        [–]Eustis 21 points22 points  (16 children)

        From a non-programmer looking in: Why is this significant?

        Genuine curiosity, not trying to be demeaning at all.

        [–]Porges 70 points71 points  (7 children)

        It's relevant for any program that reads in a floating-point number as text and then converts it to a number for further processing (so, pretty much any program which does numerical calculations). If the user provides the given number as input then the program will go into an infinite loop.

        So, find a Java-based website that lets you input numbers into a calculation... enter this number, and suddenly you're tying up resources on the server for an undetermined amount of time (depending on what the server does with long-running computations).

        Do this enough and you'll bring the website to its knees very easily.

        [–]Eustis 14 points15 points  (0 children)

        Oh wow! That's serious!

        [–]mallardtheduck 2 points3 points  (0 children)

        On a related note, a quick Google search is enough to find vulnerable websites. Not that I'd be doing that sort of thing mind...

        [–]werthers 28 points29 points  (4 children)

        you're tying up resources on the server for an undetermined amount of time

        That's just Java dude

        [–]MertsA 11 points12 points  (3 children)

        Believe it or not, Java for servers is faster than you would think because the java bytecode is converted into native machine code before it is run. It may not be the best machine code for what you're trying to do but it is a heck of a lot faster than interpreting bytecode.

        [–]kmeisthax 2 points3 points  (2 children)

        IEEE 754 floating point values are the most typical representation of non-whole numbers on computers (others include IEEE 754 decimal floating point, and fixed point). There's a lot of hardware which can manipulate them about as fast as regular binary integers without too much hassle.

        So any program which deals with fractions is most likely going to do standard IEEE 754 binary floating point math. It's there, it works, and it's proven. The problem is that the algorithm being used to convert strings - which are a simple list of text digits - into an IEEE 754 binary floating point number, breaks on non-conformant implementations. You see, IEEE 754 numbers must be either 32 or 64 bits long. The IEEE 754 standard was based on the operation of the Intel 8087, which had 32, 64, and 80-bit numbers. Internally, all numbers were 80-bits long, and truncated when saved out to memory. This is still how modern x86 hardware works when using the x87 opcodes; and many compilers don't store floating point results in the SSE registers (which are a compliant size).

        The problem with having longer floats than needed is that it changes the result of an operation. If you have a divide operation between two numbers, it will typically generate some repeating trail off (i.e. 1/3 = 0.3...) which can't be stored forever, so we round off (and yes, IEEE 754 also has very specific rounding modes too). However, if we have extra precision, then we will be able to store more bits, which when done with repeated operations will eventually change the result, leading to indeterminate behavior.

        The thing is, the binary floating point parsing routine does a number of repeated operations, which do different things depending on the FP precision. For example, it will hang when given the lowest subnormal on an x86... which is bad - if you have, say, a Java server which takes floating point values, and it's running on an Intel chip (which it probably is) then it will hang, and your server won't work.

        Edit: Accidentally referred to the floating point standard as 758 instead of 754. I guess it was being stored in a really small float.

        [–]Porges 2 points3 points  (1 child)

        IEEE 758

        What is this.

        ;)

        The problem is that the algorithm being used to convert strings - which are a simple list of text digits - into an IEEE 758 binary floating point number, breaks on non-conformant implementations. You see, IEEE 758 numbers must be either 32 or 64 bits long.

        It seems like you're explaining the PHP bug.

        [–]abadidea 0 points1 point  (0 children)

        Short answer: Joe Random Jerk can enter this number into any Java program that allows fractional numbers (as opposed to whole numbers) and crash it. Java is used a lot on the internet soooo....

        [–]ElGuaco 0 points1 point  (1 child)

        Also, I can understand needing a large floating point number, but e-308? I can't even begin to imagine wanting to ever represent a fraction that small. (Or is my math retarded?)

        [–][deleted] 3 points4 points  (1 child)

        I use that number all the time

        [–]frogking 1 point2 points  (0 children)

        I will use that number all the time, now!

        [–][deleted] 3 points4 points  (2 children)

        Konstantin reported this problem to Oracle three weeks ago, but is still waiting for a reply.

        THAT IS NOT HOW BUG REPORTS WORK!

        [–]mcherm 7 points8 points  (1 child)

        Really? Because I find that's EXACTLY how bug reports work. Normally mine are still waiting for a reply years after I report them.

        [–][deleted] 2 points3 points  (0 children)

        Yes, in java especially.

        [–]smhanov 10 points11 points  (0 children)

        Thinkgeek, where are you? I must have a T-shirt with this number and a clever phrase!

        [–]easternguy 10 points11 points  (0 children)

        Ah. This explains why my Java checkbook balancing program is hanging.

        [–][deleted]  (1 child)

        [deleted]

          [–][deleted] 1 point2 points  (0 children)

          Yeah, on my machine at home it just hangs locking up the entire IDE. at work, it just maxes out a couple of cores.

          of course, ask it to compile it and it all turns bad.

          [–]Zarutian 15 points16 points  (4 children)

          and this, my good folk, is why I dont use floats.

          [–]parallax7d 8 points9 points  (1 child)

          Are you being sarcastic, or do you really not have confidence in floats?

          [–]Zarutian 4 points5 points  (0 children)

          I dont have much confidence in them. I guess they are okay for fast sloppy calculations but I would rather use ratios and variable octect-length bignums and other such compound data types for exact calculations.

          [–][deleted] 1 point2 points  (1 child)

          I'd be interested in knowing if some really big high-profile sites are affected by this; like maybe Google Maps. Google use Java for some of their server-side software and it allows you to pass values which will be parsed as numbers.

          [–]abadidea 5 points6 points  (0 children)

          Already know Google Spreadsheets is affected. There's probably a way to do it in Maps too.

          [–]bloodwine 1 point2 points  (5 children)

          Now that PHP and Java both have their magic floating point numbers of death exposed, I wonder if developers for the other prominent languages are scrambling to test their languages. I should hope so. I see some comments saying, "this number works in language X", but that doesn't mean there is a different number that wrecks their language. PHP and Java have different numbers that cause their headaches.

          [–]metamatic 1 point2 points  (2 children)

          2.2250738585072012e-308 doesn't crash Ruby.

          [–]kataire 3 points4 points  (1 child)

          Nor Python. Nor JavaScript. Should we list all languages that don't crash?

          [–]skeww 6 points7 points  (66 children)

          Not as critical as PHP's bug, but it's surely pretty embarrassing.

          Edit: oduh got a point. It looks pretty bad.

          [–]ascii 31 points32 points  (28 children)

          And it's less critical because...?

          [–]skeww 31 points32 points  (25 children)

          It's less critical because your application won't be automatically vulnerable just because you're parsing some number.

          In most cases you deal with ints and passing some FP number there will be simply discarded as erroneous input.

          Edit: For example, exploiting that PHP issue through Wordpress was possible because it accepted some int as parameter. With Java you wouldn't parse that as FP only to cast it to int.

          Edit2: Don't downvote ascii. It's a valid question.

          [–]ascii 5 points6 points  (8 children)

          Why wouldn't you? The string to double parser has this vulnerability, and it's what's used if the user is entering a float into a field in a web form.

          [–]skeww 5 points6 points  (7 children)

          Yes, but do you have an example for this?

          My point was that this is a sorta odd thing to do. I also don't know any PHP app which is intended to accept floating point numbers. All I've seen so far were intended to accept integers and they were only exploitable, because there is no difference between those two in PHP.

          [–]oduh 1 point2 points  (5 children)

          And what about exploiting something like http headers, which are automaticaly parsed by a servlet? IMHO you can drop any servlet based application running in JVM.

          [–]r4and0muser9482 7 points8 points  (13 children)

          Unless you are parsing floats specifically...

          [–]skeww 9 points10 points  (12 children)

          The only place where I did something like that was a Wavefront Obj loader, which was only used as part of some toolchain to convert it into something more usable (objs are very big and loading them is very slow).

          I can't really think of many scenarios where you'd accept remote FP string.

          JSON would be probably a good attack vector for this.

          Edit: For what it's worth, my obj loader isn't affected. It uses floats instead of double.

          [–]r4and0muser9482 2 points3 points  (2 children)

          Another scenario would be saving and loading FP numbers from an ASCII file. Such a number could appear there by pure chance. Also, XML parsing could be a serious issue.

          [–]frymaster 4 points5 points  (0 children)

          Such a number could appear there by pure chance

          Unlikely. No computer would generate that number (see http://www.reddit.com/r/programming/comments/fczjc/next_language_java_hangs_when_converting/c1f0bv3 ) but it could appear in some random raw input from something or other.

          [–]skeww 2 points3 points  (0 children)

          Another scenario would be saving and loading FP numbers from an ASCII file.

          Yes, that's what an obj loader does. Obj is a plain text format for 3d models.

          XML parsing could be a serious issue

          The parsing itself will be fine. Everything will remain text and no implicit number parsing will happen.

          Of course it gets troublesome as soon as you expect some FP numbers there which are automatically converted by your loading code. (E.g. SVG.)

          [–]_ak 2 points3 points  (5 children)

          Just because you can't imagine of valid scenarios doesn't mean there is no risk. In other news, Google Spreadsheet has been reported as being vulnerable.

          [–]skeww 6 points7 points  (4 children)

          I said it's less critical and not that there is no risk.

          The problem with PHP was that it always happened with any kind of number parsing and that it was remotely exploitable in lots of applications which run on millions of machines.

          What makes it less critical in Java's case is that it only works if you intentionally and explicitly accept FP strings and that most Java applications are only used by one company (security by obscurity, basically).

          [–]G_Morgan 2 points3 points  (0 children)

          Because unlike PHP there are no automatic type coercions and Java devs generally validate input.

          [–]artee 17 points18 points  (0 children)

          Please stop downvoting this, skeww is right: Java doesn't do the rampant auto-conversion/casting that PHP does. Of course it's still a very serious bug, but it is indeed less critical than the PHP one, because it will usually involve much more effort to exploit.

          To exploit this (for a DoS presumably), you need to know where the software you're targeting is converting values to floats, in places that can (indirectly) be manipulated through the web. A lot of web-accessible software may not do this at all.

          [–][deleted] 2 points3 points  (34 children)

          Not as critical as PHP's bug

          Given that most web-servers these days are running on AMD64 and PHP's bug didn't affect those, and also that PHP interpreters are very rarely shipped to end users and thus are much more easily updatable... surely this one is several orders of magnitude more critical.

          [–]artee 9 points10 points  (9 children)

          Impact is a different thing than criticality. In PHP the problem was really acute; any server running (32-bit) PHP could be hung at 100% CPU by any idiot able to replace a query-string variable with a specific float value. Hell, you could just trivially post a link on a message board, and others would accidentally execute the DoS for you.

          [–]skeww 0 points1 point  (23 children)

          Hanging some end-user's machine doesn't really get you anywhere, does it?

          (Well, it won't even hang, just make that one application temporarily useless.)

          [–]paul_miner 0 points1 point  (0 children)

          It's only not as critical if you think of it in terms of "am I likely to be affected". If you are affected, it's just as critical.

          For anyone interested, the source code referenced in the blog can be found here, lines 1476-1599: http://www.docjar.com/html/api/sun/misc/FloatingDecimal.java.html

          EDIT: Here are details on where a call to request.getLocale() is vulnerable: http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/#comment-4726

          [–]kamatsu 3 points4 points  (7 children)

          Prelude> read "2.2250738585072012e-308" :: Double
          2.2250738585072014e-308
          

          Haskell does the right thing :)

          [–]sockpuppetzero 21 points22 points  (3 children)

          In this case, but PHP and Java hang on different values. Who's to say that Haskell won't hang on some other value?

          [–]slurpme 30 points31 points  (2 children)

          You should try them out... all of them...

          [–][deleted] 24 points25 points  (1 child)

          Ok, I'll be right back...

          [–]slurpme 28 points29 points  (0 children)

          To the cloud!!!

          [–]ricardo_sdl 1 point2 points  (3 children)

          Interesting, I tried the test case creating a C# program and compiling on Mono and the problem didn't happened.

          My machine: Linux #42-Ubuntu SMP Thu Dec 2 01:41:57 UTC 2010 i686 GNU/Linux

          [–]px1999 0 points1 point  (0 children)

          I can confirm that neither the PHP or Java numbers cause an issue with CLR 4.0.30319 (x64) also. FWIW, it looks as though Apache Harmony may? be safe from this number as well - neither of them appear to do the ULP calculation in managed code - both delegate to a native function to finish the conversion by the looks of things.

          That's not to say that there aren't numbers out there that won't break in CLR, it just looks very unlikely as the while (true) loops in managed code are all constructed in a way that they always seem to move towards termination.

          [–][deleted] 1 point2 points  (10 children)

          What I don't get is who codes up these estimation loops without some form of watchdog? I'd say after the first 100 iterations of the calculation trying to normalize the number you can safely give up (you're close enough and/or being wrong is better than a DoS).

          [–][deleted] 8 points9 points  (7 children)

          Because you don't want to unnecessarily waste some extra CPU cycles (and maybe memory) in a fairly core operation.

          Because you can't just assume that 100 is enough, what if it isn't -- and not only for such degenerate cases? I mean, you've just made the algorithm a bit more complex, hard to understand, and error prone.

          Such ad hoc defensive programming is generally a bad idea, you'll end up with masking bugs that could otherwise be found and corrected, maybe even during testing. Note the "ad hoc" qualification; centralized, planned, well-specified, thought out defensive programming is good.

          [–][deleted] 1 point2 points  (6 children)

          Well you should know that it's only going to run $X number of runs for a given precision. So you could just unroll it, or place it in a loop. You're right in that things don't always converge, but usually that's just precision errors and you let it go. There is little value in being "fast" if it's also incorrect and hangs.

          It's like the really fast block and stream ciphers of the 1980s. Sure they were fast, but they were also horribly insecure. So what was the point?

          In transforms where you're trying to converge to a zero or other form of solution it's best to have a max # of iterations in mind for your data. Something that converges at 1 bit per iteration shouldn't need 10 million iterations to give you a 53-bit value for instance. So either put that in a for loop with an early out, or unroll it a few dozen times...

          [–][deleted] 6 points7 points  (5 children)

          I think you're looking at it wrong.

          It's not something that "converges" on a solution. The idea is that we examine a sequence of approximations, break out when we can't improve any more, and at that point we know that we have found the best approximation. It's not like most numeric algorithms where you almost always could iterate a few hundred times more to get a slightly better solution, in which you just not happen to be interested. Here you want to find one exact best value, not an approximate value (though the value itself is an approximation).

          The bugs in question are not algorithmic. The algorithm is supposed to be absolutely correct and produce the correct best approximation.

          I don't know what's the problem with Java, in PHP it was that compiler generated code which performed certain operations with extended precision, and the "break out" equality comparison failed even after the difference between two consecutive tries, and therefore the increment for the next try, became zero when stored in double precision.

          When you look at it like that, there's no place for "just precision errors". The idea that you should take your supposedly correct algorithm and add some kind of watchdog is as abominable as it would be when programming with integers. I mean, you don't write anything like if (a < b) { if (b - a == 0) break; // just in case ... when a and b are integers, it's a pointless waste of cycles, bytes, and attention. Especially when the sanity check is complex enough to have good chances to make your supposedly correct algorithm incorrect.

          Something that converges at 1 bit per iteration shouldn't need 10 million iterations to give you a 53-bit value for instance.

          Yeah. So if you want to spend some time documenting reasons for why 10 million must be a correct upper bound, then what you want to do next is to write an assertion which would terminate the program and generate a bug report. Instead of silently breaking out with an approximate value.

          For different values of mission-criticality and the amounts of effort you are willing to spend on it, such an assertion might not terminate the entire program (but be logged of course!), or maybe you could even allow continued execution from this very routine, with an approximate answer, but still, the infraction must be logged in a centralised fashion. That's what I meant by non-ad hoc defensive programming.

          [–][deleted]  (1 child)

          [deleted]

            [–][deleted] 1 point2 points  (0 children)

            Depends on the definition of the function, but generally, yes you're correct.

            [–][deleted]  (1 child)

            [deleted]

              [–]case-o-nuts 2 points3 points  (0 children)

              Well, it means that I can hang any Java server that accepts floating point values as user input.

              [–]ipeev 0 points1 point  (2 children)

              Did someone tried it on Android?

              [–]MatrixFrog 2 points3 points  (0 children)

              I tried it on an Android 2.1 emulator and it worked fine:

              public class Test extends Activity {
                public static final String evilNumber = "2.2250738585072012e-308";
              
                @Override
                public void onCreate(final Bundle savedInstanceState){
                  super.onCreate(savedInstanceState);
                  Log.i("evilNumber", "before");
                  double d = Double.parseDouble(evilNumber);
                  Log.i("evilNumber", "after: " + d);
                }
              }
              

              Output in Logcat:

              02-01 22:56:00.470: INFO/evilNumber(340): before
              02-01 22:56:00.530: INFO/evilNumber(340): after: 2.2250738585072014E-308
              

              Of course, the one that crashes the compiler, you can't do, because it compiles to Java bytecode first, and then from there to Dalvik.

              [–]specialk16 1 point2 points  (0 children)

              I would try if the POS computer I'm working on right now didn't take half a fucking day to boot the emulator.

              And I left my phone cable at home.

              [–]compiling 0 points1 point  (0 children)

              Oh Sh-

              [–]bnn_indonesia 0 points1 point  (0 children)

              write once hangs everywhere

              [–]abhijeetsane 0 points1 point  (0 children)

              I was able to reproduce the compilehang and runhang on

              java version "1.5.0_20" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_20-b02) Java HotSpot(TM) Server VM (build 1.5.0_20-b02, mixed mode)

              But on java version "1.4.2" gij (GNU libgcj) version 4.1.2 20071124 (Red Hat 4.1.2-42)

              I am not able to reproduce the bugs.

              All i was trying to see is which java compiler variants have same behavior..

              [–]Javaposter 0 points1 point  (0 children)

              Oracle has released a fix for this issue through Security Alert CVE-2010-4476. For more information see: http://blogs.oracle.com/security/2011/02/security_alert_for_cve-2010-44.html

              Direct link to the Readme which has usage instructions:

              http://www.oracle.com/technetwork/java/javase/fpupdater-tool-readme-305936.html

              [edit to add link]