Yesterday, I came across a case in a piece of software which was really hard for me to understand perfectly. Not only the code is well written (which is always worse for finding bugs) but the structure is also well thought (this is the implementation of an associated array in C in the lighttpd application).
The problem I had was to state whether a tool report was a true-positive/false-positive. So, as in many case I've seen in this software a problem may occur only in the limit cases. This one may occur after INT_MAX insertion in the structure. I don't know if one of you ever tried to do such a thing, but only INT_MAX (\~2 billions on typical PC) allocations is a lot, so inserting elements in a structure that needs at least 5 (re)allocations is too much. But well, I did it. Also, I ran this test with valgrind using the memory leak check (full check and high definition).
I then ran a simple test program to fill this structure in a real
condition: a typical x86/32-bit architecture. As I knew it was stupid
and didn't even think this could end before 2 days I started looking in
other direction in order to reduce the INT_MAX
size for having a
reasonable time execution of the test.
My first attempt is to shift all the types that are used, I knew this
was not perfect because even if I can force my program to use
unsigned short
instead of size_t
, I wouldn't change the size of the
pointers, a char *
would still b 32-bit (there may be some options in
gcc to control the size of the pointers — which I doubt — but I didn't
find any).Using this methodology, I was able to make the program crash
in the way that would have been a real true-positive.
But as I knew it was not good since the size of the pointers are not modified and I had the feeling that in that particular structure, the case of the possible crash is handled by itself (due to pointer and type limits), I started looking in other direction for running that program in 16-bit, a pseudo-real-16-bit-mode. I then started looking into emulators and how to compile code for 16-bits and running it on my linux (x86/32-bit).After having issues compiling and running the test program with the gnu-m68hc11 ELF package, I found the bcc/elksemu stuff. After compiling and running with ELKS utilities, the test program didn't crash, it only failed in an assertion test after an allocation...
Different behavior, with different methods, okay... which is the correct one? Is it a problem of pointer size that made the test running differently than the real program on a 32-bit or maybe a limitation of the elksemu machine?As this morning I checked the state of the 32-bit run I launched yesterday, and this was finished... ended by a failed assertion.
As expected, pointer size matters when you wanna test on intrinsic limitations of a structure and its behavior using limit cases.