From: Vsevolod Stakhov Date: Wed, 8 Oct 2025 08:10:09 +0000 (+0100) Subject: [Fix] Fix TCP framing protocol endianness mismatch X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1e2a03e9661103576b5066dd7d7f2efb2523f8ad;p=thirdparty%2Frspamd.git [Fix] Fix TCP framing protocol endianness mismatch The TCP framing protocol had an endianness mismatch for the 2-byte frame size header. The client was sending and expecting frame lengths in little-endian, while the server was sending and expecting them in network byte order (big-endian). This inconsistency corrupted frame lengths, leading to protocol errors and communication failures. Changes: * Server now uses GUINT16_TO_LE() instead of htons() for frame length encoding * Server now uses GUINT16_FROM_LE() instead of ntohs() for frame length reading * Server frame length parsing now reconstructs little-endian format * Updated comment to reflect little-endian byte order consistency All TCP frame lengths are now consistently transferred as little-endian numbers. --- diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c index da2d920911..d0edcca81a 100644 --- a/src/fuzzy_storage.c +++ b/src/fuzzy_storage.c @@ -1052,7 +1052,7 @@ rspamd_fuzzy_tcp_enqueue_reply(struct fuzzy_session *session) /* Create reply queue element */ reply_elt = g_malloc0(sizeof(*reply_elt)); - reply_elt->rep.size_hdr = htons((uint16_t) len); + reply_elt->rep.size_hdr = GUINT16_TO_LE((uint16_t) len); memcpy(&reply_elt->rep.payload, data, len); reply_elt->written = 0; @@ -2572,7 +2572,7 @@ rspamd_fuzzy_tcp_write_reply(struct fuzzy_tcp_session *session, struct fuzzy_tcp_reply_queue_elt *reply) { gssize r; - gsize total_len = sizeof(reply->rep.size_hdr) + ntohs(reply->rep.size_hdr); + gsize total_len = sizeof(reply->rep.size_hdr) + GUINT16_FROM_LE(reply->rep.size_hdr); gsize remaining = total_len - reply->written; unsigned char *data = ((unsigned char *) &reply->rep) + reply->written; @@ -2664,7 +2664,8 @@ rspamd_fuzzy_tcp_io(EV_P_ ev_io *w, int revents) if (processed_offset < session->bytes_unprocessed) { uint16_t first_byte = session->cur_frame_state & 0xFF; uint16_t second_byte = session->input_buf[processed_offset]; - session->cur_frame_state = 0xC000 | ((first_byte << 8) | second_byte); + /* Reconstruct in little-endian byte order */ + session->cur_frame_state = 0xC000 | (first_byte | (second_byte << 8)); processed_offset++; } else { diff --git a/src/plugins/fuzzy_check.c b/src/plugins/fuzzy_check.c index ff9fc6dfbe..743fdd3750 100644 --- a/src/plugins/fuzzy_check.c +++ b/src/plugins/fuzzy_check.c @@ -209,7 +209,7 @@ struct fuzzy_tcp_pending_command { * TCP write queue element - contains framed command ready to send */ struct fuzzy_tcp_write_buf { - uint16_t size_hdr; /* Frame size in network byte order */ + uint16_t size_hdr; /* Frame size in little-endian byte order */ unsigned char *data; /* Command data (encrypted) */ gsize total_len; /* Total length: sizeof(size_hdr) + data_len */ gsize bytes_written; /* How many bytes already written */