Yes I did, but it is so rare that it did go unnoticed for 20years 🙂
In short:
-headers have to be split in multiple packets
-break between packets have to be exacly on CRLF sequence (CR in first packet, LF in second)
-last header line data in first packet should be equal length to previous header line data
Observed conditions:
Headers were very long - 30+ lines. Some header lines were very long.
On first call of SocketDataAvailable, FReceiveBuffer did not receive whole header.
After
Len := FCtrlSocket.Receive(@FReceiveBuffer[FReceiveLen], I);
Len is 1369, FReceiveBuffer[1368] = #13, FReceiveBuffer[1369] = #0
so everything there is as expected, 20+ full header lines and last line in buffer ending with CR (LF will come in next packet/call to SocketDataAvailable + rest of the headers)
After processing all header lines that were terminated with CRLF we observe here:
while FReceiveLen > 0 do begin
I := 0; // FP 09/09/06
while (I <= FReceiveLen) and (Ord(FReceiveBuffer[I]) <> 10) do // FP 09/09/06
Inc(I); // FP 09/09/06
if I > FReceiveLen then
break;
FReceiveLen is 32 and first 33 bytes of FReveiveBuffer are:
X-Content-Type-Options: nosniff#$D#$A
You would expect that FReceiveBuffer[32] would be #0 but it isn't probably due to incorrect parameters of
MoveTBytes(FReceiveBuffer, I + 1, 0, FReceiveLen); // FP 09/09/06
and fact that last full header line was:
X-XSS-Protection: 1; mode=block#$D#$A
exacty 31 bytes(without CRLF) as our last unprocessed (and incomplete) header line.
It will increase I to 32, it will not break (but it should cause line is not terminated with LF - but state of buffer and errors in code says otherwise )
Rest of the code in while loop
while FReceiveLen > 0 do begin
will consider line complete and will add it to headers, FReceiveLen would go from -1 to 0 due to
FReceiveLen := FReceiveLen - I - 1; // FP 09/09/06
if FReceiveLen > 0 then begin
// Move(FReceiveBuffer[I], FReceiveBuffer[0], FReceiveLen + 1);
MoveTBytes(FReceiveBuffer, I + 1, 0, FReceiveLen); // FP 09/09/06
// Debugging purpose only
//FillChar(FReceiveBuffer[FReceiveLen], I + 1, '*');
end
else if FReceiveLen < 0 then // AG 03/19/07
FReceiveLen := 0; // AG 03/19/07
and we will go to another packet/SocketDataAvailable call
which starts with #10 and have rest of headers after that
FLastresponse would be empty and rest of headers will end up in body.