What was the most dangerous programming mistake you have made in C?

前端 未结 26 1172
南方客
南方客 2021-02-03 12:46

I am an intermediate C programmer. If you have made any coding mistake that you came to know later that it was the most hazardous / harmful to the total application please share

相关标签:
26条回答
  • 2021-02-03 13:23

    I remember two blunders:

    1. returning address of an auto variable from within a function in which it was created;
    2. copying string to an uninitialised and unallocated pointer to char.
    0 讨论(0)
  • 2021-02-03 13:24
    if (c = 1) // insert code here
    
    0 讨论(0)
  • 2021-02-03 13:25

    I'm in agreement with Pat Mac here (despite his downvoting). The most dangerous thing you can do in C is simply to use it for something important.

    For example, a sensible language would by default check array bounds and stop your program immediately (raise an exception or something) if you try to wander outside of it. Ada does this. Java does this. Tons of other languages do this. Not C. There are entire hacking industries built around this flaw in the language.

    One personal experience with this. I worked with a company that ran a network of flight simulators, tied together with reflective (shared) memory hardware. They were having a nasty crash bug they couldn't track down, so our two best engineers got sent up there to track it down. It took them 2 months.

    It turned out that there was an off-by-one error in a C loop on one of the machines. A competent language would have stopped things right there of course, but C let it go ahead and write a piece of data in the next location past the end of the array. This memory location happened to be used by another machine on the network which passed it to a third machine, which used the (garbage) value as an array index. Since this system was also coded in C, it didn't care either that it was indexing way outside of its array, and trashing semi-random memory locations in its program.

    So, due to a lack of array bounds checking, a simple easy to make off-by-one bug caused random crashes in a computer two entire hops away from the source of the bug! Cost to the company: 4 man-months of their best engineers' time, plus however much was spent by other engineers and support personnel, plus all the downtime from the simulators in question not working right.

    0 讨论(0)
  • 2021-02-03 13:26

    Few years ago I've got a call from my ex-colleague telling me about the problem he had to fix with my code, which was a router for credit card transactions.

    Card number prefix consists of 6-digit BIN (Bank Identification Number) and extra few digits that banks use at own discretion, e.g. bank has BIN for Visa Classic card 456789, and reserve 2 extra digits to indicate sub-product, like 01 for student's card, 02 for co-branded card with local department store and so on. In this case card prefix, which is basically product identifier, becomes 8 digits long. When I coded this part, I decided that 9 digits "ought to be enough for everyone". I was running ok for 2 years until one day bank make a new card products with 10-digit-long prefix (have no idea why they needed it). Not too hard to imagine what has happened - router segfaulted, the whole system halted because it cannot function without transaction router, all ATMs of that bank (one of biggest in the country) became non-operational for few hours, until problem was found and fixed.

    I cannot post the code here firstly because I don't have it and secondly it is copyrighted by the company, but it is not hard to imagine the strcpy() without checking size of target buffer.

    Just like man strcpy says:

    If the destination string of a strcpy() is not large enough (that is, if the programmer was stupid or lazy, and failed to check the size before copying) then anything might happen. Overflowing fixed length strings is a favorite cracker technique.

    I was very embarrassed. It was a good time to commit seppuku :)

    But I learned the lesson well and do not forget (usually :) ) to check size of target buffer. I wouldn't recommend you to learn it the hard way - just develop a habit to check target buffer before strcpy() and strcat().

    Edit: good suggestion from Healthcarel - use strncpy() rather than strcpy(). It doesn't add trailing 0 but I usually use following macro to get around it:

    #define STRNCPY(A,B,C) do {strncpy(A,B,C); A[C] = 0; } while (0)

    0 讨论(0)
  • 2021-02-03 13:27

    When a pointer is first allocated, it does not have a pointee.

    The pointer is "uninitialized"

    A dereference operation on a bad pointer is a serious runtime error.

    If you are lucky, the dereference operation will crash or halt immediately (Java behaves this way).

    If you are unlucky, the bad pointer dereference will corrupt a random area of memory, slightly altering the operation of the program so that it goes wrong some indefinite time later. Each pointer must be assigned a pointee before it can support dereference operations.

    0 讨论(0)
  • 2021-02-03 13:28

    system() with some user-supplied string in the argument. Same goes for popen().

    Use exec*() instead.

    Of course, this is not unique to C.

    0 讨论(0)
提交回复
热议问题