• just me (unregistered) in reply to DrYak

    No, I think the programmer didn't figure out the problem it self. He only figured out that sometimes, the value started to suddenly change without explanation, thus the hacked test.

    Probably they had a nasty encounter with the tax man.

    I vote ***** for this wtf.

  • (cs) in reply to Alan Moore
    Alan Moore:
    No - there was an actual bug in the Visual Studio "unmanaged code to managed code" compilation. You would return true from an unmanaged c++ method and it would magically change to false when being tested by the .NET (say c#) code. Fixed with a service pack...

    ... which made it return File_Not_Found.

    ;-)scnr

  • MedO (unregistered)

    Problems like this still exist. I'm currently using C to program an ATmega microcontroller with a proud 1kb of RAM, and 8kb of seperate program memory. It's very easy to smash the stack right into the heap, especially when you are inexperienced enough to use normal string literals - these are copied into RAM before they are used, so you can get a normal pointer to an adress in RAM space.

    To prevent this, you have to define the strings to be in program memory (there is a handy macro for this), giving you pointers which are syntactically just the same as the ones into RAM, so you have to use special functions which interpret these pointers correctly. There is a convention that these functions are suffixed with "_P", an example would be "printf_P(PSTR("Hello World!\n"));". Not too inconvenient, but you have to know it first...

    In fact, there might even be a third type of pointer, for access to the eeprom memory, but I didn't work with this yet.

  • Mania (unregistered) in reply to Chris Kelley

    I can't for the life of me figure out the point of the if statement. Doesn't this do the same thing, with less clock cycles:

    vtaxrate = 0.06;

  • Mania (unregistered) in reply to Chris Kelley
    Chris Kelley:
    wow... if (vtaxrate != 0.06) vtaxrate = 0.06;
    Oops meant to quote.
  • TheM (unregistered) in reply to DrYak
    DrYak:
    @ Doubts > I think it's impressive that the submitter figured out the real problem rather than the "obvious" brute force fix.

    No, I think the programmer didn't figure out the problem it self. He only figured out that sometimes, the value started to suddenly change without explanation, thus the hacked test.

    What Doubts meant was that the programmer who reported this WTF figured out what was going on, not the clueless person who added tax test.

    DrYak:
    @ Joce : > Isn't this what C's "volatile" keyword is for - variables which can change due to external factors.

    No. Not at all. Volatile, is for variables that are shared between different task. It force the compiler to always read the variable from memory instead of caching it into a register, because some background process (say, a hardware interrupt) may have changed it meanwhile.

    In this situation, it's a variable that should change. But that gets overwritten when the heap and stack collide.

    Actually, volatile is meant for memory mapped hardware registers. Volatile is used to tell compiler not to get excited about code using seemingly non-initialized variable because it really isn't a variable at all but hardware register. Using it to share memory between processes is dangerous -- there are better ways to do that.

  • Anonymous (unregistered) in reply to NiceWTF
    NiceWTF:
    Now *that* is what I call a real WTF.

    Doesn't the compiler detect potential stack overflows,

    No, it shouldn't. It can't. For the same reason that a program (such as a compiler) cannot detect if another program (or itself) loops infinitely or not.

    If your compiler can detect potential stack overflows and still allows recursion, then your compiler can detect whether your program has infinite loops -- a problem that has been proven to be unsolvable.

    NiceWTF:
    or at least give runtime errors when they occur? Apparently not, I guess, because it would impact runtime performance.
    Right. The generated code could check the remaining space on the stack segment (between bottom of stack and top of heap) at the entrance of each function. But there is a high per-function-call performance impact.
    NiceWTF:
    This application very likely runs in the old 8086-style "real mode" which uses segmentation
    Segmentation is used in both real mode and 16-bit protected mode (introduced in the 286). Indeed segmentation is still in effect in 32-bit, paged protected mode (introduced in the 386), but with 32-bit addresses, people simply prefer to use a flat memory mode and set all segments registers to map to the same logical addresses (but with different segment descriptors for code/data/stack).
    NiceWTF:
    such that you can address >64KB of memory using 16-bit pointers.
    This statement is tricky. Indeed, you can only address 64kB with 16-bit pointers. If you want to address beyond that, you need to pick different segment registers. There are 4 segment registers on the 286 (and 186 and 8086/8088). That effectively adds 2 extra "hidden" bits. So, the 286 can access only at most 256kB concurrently. Beyond that, you have to set segment registers to different values. That's very inefficient. Furthermore, you can't do much with the code segment and stack segment, because they have their specific uses.
    NiceWTF:
    In this mode you have segments of 64KB starting every 16 bytes, overlapping each other. Hence, you can address 1 MB in total.
    "Hence"? I can't see how the last statement logically follows from what you have said.

    The fact is that there are only 20 lines on the address bus of a 8086/8088/80186. This is the very reason WHY you can only address 1MB in total. (There is one more line you can exploit: the I/O address bit, which has to be accessed using the IN/OUT instructions, which limits its use.)

    NiceWTF:
    A 16-bit pointer is always relative to a particular segment. So, I would assume the counter (pointer) within the segment to overflow,
    More accurately, it's "to wrap around" rather than "to overflow".
    NiceWTF:
    and hence start overwriting values at the very bottom of the stack, not the heap.
    The choice to make DS==SS is to make ALL data pointers to be near pointers.
    NiceWTF:
    If the "tax" percentage was on the stack somewhere, it could obviously become mangled by this. I doubt it was on the heap though.
    The original article says that "most variables are global". So, they should be allocated on the data region (I use "region" here instead of "segment" to avoid the confusion with 8086's "64k segments"). Oh! Normally, the data region is allocated below the BSS region, which is below the heap. So, if their program's stack region has grown to a point to have overwritten the data segment, that means all of the heap and BSS regions have been ruined already. That's a pretty severe problem!
    NiceWTF:
    If the program wouldn't crash this way, it would likely crash later upon returning from a few function calls. (wait...who am I kidding...did they even use functions?)
    If you mix near/far pointers in a program and do not handle them with care, it'll easily crash.
    NiceWTF:
    I may be wrong though, it's been 12 years or so since I last wrote x86 assembler code (speaking of WTF's, I know, I know).
    Me too.
  • Anonymous (unregistered) in reply to whatTheFunk
    whatTheFunk:
    Never change a "running" system...
    I won't fix something that ain't broken.

    But it's stupid not to change a running system that is BROKEN!

  • Anonymous (unregistered) in reply to Andrew
    Andrew:
    These PACKED DECIMALs match base-10 money. This is a major reason why banking still uses COBOL.
    You've got the fact right, but the reason wrong.

    Nothing prevents packed decimals to be used with other languages such as C, C++, Java, Perl, Python. You can easily write a library to handle packed decimals, much like libraries implementing complex numbers for these languages. (Fortran has built-in support for complex numbers. Has that driven everyone who needs to compute complex numbers to use Fortran and give up C++/Java? Common LISP has not only complex numbers, but also rational numbers. Has this caused people to stop developing ration-number classes in C++/Java and switch to writing programs in LISP?) With some languages (e.g. C++), you can even overload the operators to make using the library more convenient.

    The real reason that many banks still keep COBOL-based systems around is: legacy systems.

  • dkf (unregistered) in reply to Anonymous
    Anonymous:
    But it's stupid not to change a running system that *is* BROKEN!
    That is, as long as you're not just adding more new sorts of brokenness.
  • Tepid Perl User (unregistered) in reply to Mania
    Mania:
    I can't for the life of me figure out the point of the if statement. Doesn't this do the same thing, with less clock cycles:

    vtaxrate = 0.06;

    It shouldn't be allowed to reply without reading the previous comments first... Of course you have to avoid a WTF for the first posts :-)

  • Tepid Perl User (unregistered) in reply to TheM

    [quote user="TheM"][quote user="DrYak"]@ Doubts

    Actually, volatile is meant for memory mapped hardware registers. Volatile is used to tell compiler not to get excited about code using seemingly non-initialized variable because it really isn't a variable at all but hardware register. [/quote]

    And not to optimize it away!

    volatile int x=0 ; while (x=0) { whatever ; }

    Captcha: craaazy

  • Malloc (unregistered) in reply to just me
    vtaxrate = valf(buf); vtaxrate /= 100.00000;
    Why are people talking about the heap when there is no malloc involved?

Leave a comment on “Unconfigurables Configurables”

Log In or post as a guest

Replying to comment #:

« Return to Article