I know that it seems absurd, and it probably is.
Short version:
FindInvalidUTF8Character could access the string beyond its length since it uses p[1], p[2] and p[3] without properly checking that those aren't beyond the end of the string.
In the worst case this should cause nothing more than a sigsev, however here, under circumstances that I cannot determine exactly (i.e. random), it seems to hang linux hard.
Long version:
I have a (relatively simple) program that has been running flawlessly 24x7 the last 4 years.
All it does is detect the presence of a piece in a production line (using the control lines of a serial port as an input), read some data via another serial port and display the data.
The main loop (triggered by a timer on the main form) checks the input and signals the reading thread. Everything is using the correct (I hope) synchronization primitives.
The class implementing the reading protocol and the related logging is a class that I'm using in a lot of programs, and when I update it, all programs compiled after the update obviously inherit the update. Last summer I had to do a trivial modification to this program and I switched it to gtk2 from the original gtk1, since it's now mature enough. After a while they told me that the program is hanging every two to three weeks, so I prepared a test rig (same hardware, same version of the os, same everything) to simulate the operation and see where the program was hanging.
After a week and around a million cycles, it hanged, but it wasn't the application, the whole os was completely frozen.
This is scary, since if it's a problem with the application I can hunt it down, but the os hanging is beyond my control, besides, an app should never freeze the os, unless there's a bug in the kernel or in the X server. Since the biggest change was the switch to gtk2, I thought to switch back the program to gtk1.
Well, with gtk1 it reliably hanged after less than some hundreds cycles. I tried everything (using a different X driver, vesa instead of the hardware specific one, using a newer version of linux, testing on a different machine, etc.) and it still hanged, so I checked my mercurial repository to see what I changed.
I excluded lazarus and the widgetset (without using the serial port, i.e. simulating the data reading it from files, it never hanged, so the display part of the program was fine), and the only "big" difference is that now, in the logging part of the serial port routine, I call FindInvalidUTF8Character to check that there are no printable characters. I removed the call (actually I removed the whole logging routine, that, as I said earlier, has been working fine for the last 4 years and in a number of programs) and now, crossing fingers, it's done 12000 cycles without hanging.
The most intriguing part is that, under the test conditions, FindInvalidUTF8Character is only given pure ASCII strings, so it should never enter the branches where it checks p[1], p[2] or p[3], so I'm really puzzled.
Bye
