fix infinite loop in WiFi frame skip when read fails

The frame-skip loops in checkRecvFrame subtract the return value of
client.read() from frame_length. On ESP32, WiFiClient::read() returns
-1 on error. Subtracting -1 increments frame_length instead of
decrementing it, turning the loop into an infinite hang.

A WiFi client can trigger this by sending a frame header with a large
length and then disconnecting (or sending fewer bytes than claimed).
The node locks up in the skip loop and stops processing all traffic.

Switch to single-byte client.read() which returns the byte value or -1,
and break out of the loop on error. Decrement frame_length by exactly 1
per successful read.
This commit is contained in:
Wessel Nieboer 2026-02-11 04:17:26 +01:00 committed by Wessel Nieboer
parent fb726e48c2
commit 1973d6134f
No known key found for this signature in database
GPG key ID: 27BB1C3D63DEEFFF

View file

@ -131,9 +131,9 @@ size_t SerialWifiInterface::checkRecvFrame(uint8_t dest[]) {
if(frame_length > MAX_FRAME_SIZE){
WIFI_DEBUG_PRINTLN("Skipping frame: length=%d is larger than MAX_FRAME_SIZE=%d", frame_length, MAX_FRAME_SIZE);
while(frame_length > 0){
uint8_t skip[1];
int skipped = client.read(skip, 1);
frame_length -= skipped;
int skipped = client.read();
if(skipped < 0) break; // read error, stop draining
frame_length--;
}
resetReceivedFrameHeader();
return 0;
@ -144,9 +144,9 @@ size_t SerialWifiInterface::checkRecvFrame(uint8_t dest[]) {
if(frame_type != '<'){
WIFI_DEBUG_PRINTLN("Skipping frame: type=0x%x is unexpected", frame_type);
while(frame_length > 0){
uint8_t skip[1];
int skipped = client.read(skip, 1);
frame_length -= skipped;
int skipped = client.read();
if(skipped < 0) break; // read error, stop draining
frame_length--;
}
resetReceivedFrameHeader();
return 0;