mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-25 07:41:36 +02:00
BUG/MEDIUM: peers: fix buffer overflow control in intdecode.
A buffer overflow could happen if an integer is badly encoded in the data part of a msg received from a peer. It should not happen with authenticated peers (the handshake do not use this function). This patch makes the code of the 'intdecode' function more robust. It also adds some comments about the intencode function. This bug affects versions >= 1.6.
This commit is contained in:
parent
acd4827eca
commit
18928af3a3
45
src/peers.c
45
src/peers.c
@ -174,6 +174,12 @@ enum {
|
|||||||
struct peers *peers = NULL;
|
struct peers *peers = NULL;
|
||||||
static void peer_session_forceshutdown(struct appctx *appctx);
|
static void peer_session_forceshutdown(struct appctx *appctx);
|
||||||
|
|
||||||
|
/* This function encode an uint64 to 'dynamic' length format.
|
||||||
|
The encoded value is written at address *str, and the
|
||||||
|
caller must assure that size after *str is large enought.
|
||||||
|
At return, the *str is set at the next Byte after then
|
||||||
|
encoded integer. The function returns then length of the
|
||||||
|
encoded integer in Bytes */
|
||||||
int intencode(uint64_t i, char **str) {
|
int intencode(uint64_t i, char **str) {
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
unsigned char *msg;
|
unsigned char *msg;
|
||||||
@ -205,36 +211,35 @@ int intencode(uint64_t i, char **str) {
|
|||||||
*str point on the beginning of the integer to decode
|
*str point on the beginning of the integer to decode
|
||||||
at the end of decoding *str point on the end of the
|
at the end of decoding *str point on the end of the
|
||||||
encoded integer or to null if end is reached */
|
encoded integer or to null if end is reached */
|
||||||
uint64_t intdecode(char **str, char *end) {
|
uint64_t intdecode(char **str, char *end)
|
||||||
uint64_t i;
|
{
|
||||||
int idx = 0;
|
|
||||||
unsigned char *msg;
|
unsigned char *msg;
|
||||||
|
uint64_t i;
|
||||||
|
int shift;
|
||||||
|
|
||||||
if (!*str)
|
if (!*str)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
msg = (unsigned char *)*str;
|
msg = (unsigned char *)*str;
|
||||||
if (msg >= (unsigned char *)end) {
|
if (msg >= (unsigned char *)end)
|
||||||
*str = NULL;
|
goto fail;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg[idx] < 240) {
|
i = *(msg++);
|
||||||
*str = (char *)&msg[idx+1];
|
if (i >= 240) {
|
||||||
return msg[idx];
|
shift = 4;
|
||||||
}
|
|
||||||
i = msg[idx];
|
|
||||||
do {
|
do {
|
||||||
idx++;
|
if (msg >= (unsigned char *)end)
|
||||||
if (msg >= (unsigned char *)end) {
|
goto fail;
|
||||||
|
i += (uint64_t)*msg << shift;
|
||||||
|
shift += 7;
|
||||||
|
} while (*(msg++) >= 128);
|
||||||
|
}
|
||||||
|
*str = (char *)msg;
|
||||||
|
return i;
|
||||||
|
|
||||||
|
fail:
|
||||||
*str = NULL;
|
*str = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
i += (uint64_t)msg[idx] << (4 + 7*(idx-1));
|
|
||||||
}
|
|
||||||
while (msg[idx] >= 128);
|
|
||||||
*str = (char *)&msg[idx+1];
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the stick-table UPDATE message type byte at <msg_type> address,
|
/* Set the stick-table UPDATE message type byte at <msg_type> address,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user