]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: peers: fix byte order of last_get on updates without identifier
authorFrederic Lecaille <flecaille@haproxy.com>
Tue, 20 Oct 2026 14:12:36 +0000 (16:12 +0200)
committerFrederic Lecaille <flecaille@haproxy.com>
Mon, 26 Oct 2026 10:39:41 +0000 (11:39 +0100)
Since commit f12252c7a ("BUG/MEDIUM: peers: Fix update message parsing
during a full resync"), peer_treat_updatemsg() computes the update ID
in a local variable whose byte order depends on the message type.
Explicit identifiers are read in network byte order, while implicit
identifiers are computed in host byte order as st->last_get + 1.

Outside full resynchronization, htonl() is then applied to this variable
in both cases before storing it in st->last_get. This correctly converts
explicit identifiers, since htonl() and ntohl() perform the same
transformation, but incorrectly byte-swaps implicit identifiers on
little-endian machines.

The incorrect identifier is sent in ACK messages and stored by the
sender as st->update. This value initializes the transmission cursors
after a reconnection, so its corruption may cause updates to be skipped
or unnecessarily resent. A subsequent update carrying an explicit
identifier restores the correct last_get value, which can hide the
issue when inspecting the final state after a burst of updates.

This can be reproduced by completing the initial resynchronization,
then sending an UPDATE with identifier 199 followed by an INCUPDATE.
On a little-endian receiver, last_get and the acknowledged identifier
become 3355443200 (0xc8000000) instead of 200. A regression test exercising
this sequence fails without the fix and passes with it.

Convert explicit identifiers to host byte order immediately after
reading them, then store the resulting identifier without conversion.
Leave the full-resynchronization guard unchanged.

This must be backported as far as 3.3.

src/peers.c

index 37dae2771a35afd23b88902dd4e63ec12ec9dce9..c09e585533e06fc4f03fe3ff0079321185902aa8 100644 (file)
@@ -1840,12 +1840,13 @@ int peer_treat_updatemsg(struct appctx *appctx, struct peer *p, int updt, int ex
 
                memcpy(&update, *msg_cur, sizeof(update));
                *msg_cur += sizeof(update);
+               update = ntohl(update);
        }
        else
                update = st->last_get + 1;
 
        if (p->learnstate != PEER_LR_ST_PROCESSING)
-               st->last_get = htonl(update);
+               st->last_get = update;
 
        if (exp) {
                size_t expire_sz = sizeof expire;