I have a real old code from a service that uses named named pipes in message mode (PIPE_TYPE_MESSAGE) with overlapped i/o (FILE_FLAG_OVERLAPPED).
The code does the following:
ReadFilefor 4 bytes with overlapped i/o (header + message length). The Client wrote this command with one call toWriteFile.- After the 4 bytes are read, a
ReadFilecall is made to read the rest of the message (with the known length) without specifying anOVERLAPPEDstructure. - After the command is executed the routine continues at stage 1. and awaits the next command.
When I read the documentation
Overlapped operations require a file, named pipe, or communications device that was created with the FILE_FLAG_OVERLAPPED flag. When a thread calls a function (such as the ReadFile function) to perform an overlapped operation, the calling thread must specify a pointer to an OVERLAPPED structure. (If this pointer is NULL, the function return value may incorrectly indicate that the operation completed.)
I have to assume that this code will not work or is at least be called incorrect...
In fact this code is 15 years old and runs on hundreds of machines and it works without problems.
So do I have to tell my boss and colleagues that this code is buggy and it is just luck that it works and this code need to be corrected?
yes, this code is incorrect but can work without errors.
ReadFilecallZwReadFile. it 5th parameter - IoStatusBlock - Pointer to anIO_STATUS_BLOCKstructure - is mandatory and always must be not 0. for any file. for any I/O type. soReadFilemust pass pointer toIO_STATUS_BLOCKwhen it callZwReadFile. if you pass not 0 pointer toOVERLAPPED- it pass this pointer asIO_STATUS_BLOCKtoZwReadFile. the first 2 members ofOVERLAPPEDcorresponded toIO_STATUS_BLOCK. but if you pass 0 in place pointer ofOVERLAPPED-ReadFileallocate localIO_STATUS_BLOCK iosbvariable and pass it toZwReadFile. theIO_STATUS_BLOCKmemory must be valid until I/O not completed. because at the end of I/O kernel write final status to this memory. from another side - if you local variable forIO_STATUS_BLOCK- it became not valid (point to arbitrary memory in stack) afterReadFilereturn. in case synchronous I/O - no problem here, becauseReadFilenot return until I/O not completed. but in case asynchronous I/O - this was UB -ReadFilecan return while I/O still in progress. soIO_STATUS_BLOCKbecame not valid before I/O end. and when I/O actually ended - will be overwritten memory at arbitrary place in your thread stack. this can have no any effect or can corrupt your stack. undefinded. depend from where you be (which stack pointer value) at this time