Skip to content

Commit bad4637

Browse files
authored
Tighten varint reads
2 parents a0bf1cd + 4a49173 commit bad4637

2 files changed

Lines changed: 26 additions & 18 deletions

File tree

c/common.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@
5050
ptr += (n); \
5151
} while (0)
5252

53+
// Returns how many bytes a value occupies when encoded as a varint (compile-time).
54+
// 7 bits per byte: 0-127 → 1, 128-16383 → 2, ... up to 5 bytes max.
55+
#define VARINT_SIZE(n) \
56+
(((__u32)(n) <= 0x7F) ? 1 : \
57+
((__u32)(n) <= 0x3FFF) ? 2 : \
58+
((__u32)(n) <= 0x1FFFFF) ? 3 : \
59+
((__u32)(n) <= 0xFFFFFFF) ? 4 : 5)
60+
5361
// reads a value into 'dest' and increments 'ptr', or returns 0 if OOB
5462
#define READ_VAL_OR_RETURN(dest, ptr, pend, dend) \
5563
do \
@@ -91,17 +99,17 @@
9199
barrier_var(ptr); \
92100
} while (0)
93101

94-
// minecraft has a 21bit varint framedecoder so for packet length by protocol difinition only 3 bytes are allowed
95-
#define PACKET_LEN_OR_DIE(dest_struct, ptr, pend, dend) \
102+
#define MAX_VARINT_OR_DIE(dest_struct, ptr, pend, dend, max) \
96103
do \
97104
{ \
98-
dest_struct = read_varint_sized(ptr, pend, 3, dend); \
105+
dest_struct = read_varint_sized(ptr, pend, max, dend); \
99106
if (!(dest_struct).bytes) \
100107
return 0; \
101108
(ptr) += (dest_struct).bytes; \
102109
barrier_var(ptr); \
103110
} while (0)
104111

112+
105113
struct ipv4_flow_key
106114
{
107115
const __u32 src_ip;

c/minecraft_networking.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ static __always_inline __u8 inspect_ping_request(__u8 *start, const __u8 *payloa
1111
{
1212
struct varint_value varint;
1313

14-
// len 3 bytes varint max
15-
PACKET_LEN_OR_DIE(varint, start, payload_end, data_end);
14+
// max 9 bytes
15+
MAX_VARINT_OR_DIE(varint, start, payload_end, data_end, VARINT_SIZE(0x09));
1616
ASSERT_OR_RETURN(varint.value == 0x09);
1717

1818
// packet id
19-
VARINT_OR_DIE(varint, start, payload_end, data_end);
19+
MAX_VARINT_OR_DIE(varint, start, payload_end, data_end, VARINT_SIZE(0x01));
2020
ASSERT_OR_RETURN(varint.value == 0x01);
2121

2222
__u64 timestamp;
@@ -29,12 +29,12 @@ static __always_inline __u8 inspect_status_request(__u8 *start, const __u8 *payl
2929
{
3030
struct varint_value varint;
3131

32-
// len 3 bytes varint max
33-
PACKET_LEN_OR_DIE(varint, start, payload_end, data_end);
32+
// max 1 byte
33+
MAX_VARINT_OR_DIE(varint, start, payload_end, data_end, VARINT_SIZE(0x01));
3434
ASSERT_OR_RETURN(varint.value == 0x01);
3535

3636
// packet id
37-
VARINT_OR_DIE(varint, start, payload_end, data_end);
37+
MAX_VARINT_OR_DIE(varint, start, payload_end, data_end, VARINT_SIZE(0x00));
3838
ASSERT_OR_RETURN(varint.value == 0x00);
3939

4040
return start == payload_end;
@@ -48,15 +48,15 @@ static __always_inline __u8 inspect_login_packet(__u8 *reader_index, const __u8
4848
struct varint_value varint;
4949

5050
// len 3 bytes varint max
51-
PACKET_LEN_OR_DIE(varint, reader_index, payload_end, data_end);
51+
MAX_VARINT_OR_DIE(varint, reader_index, payload_end, data_end, VARINT_SIZE((PACKET_ID_MAX + LOGIN_DATA_MAX)));
5252
ASSERT_IN_RANGE(varint.value, PACKET_ID_MIN + LOGIN_DATA_MIN, PACKET_ID_MAX + LOGIN_DATA_MAX);
5353

5454
// packet id
55-
VARINT_OR_DIE(varint, reader_index, payload_end, data_end);
55+
MAX_VARINT_OR_DIE(varint, reader_index, payload_end, data_end, VARINT_SIZE(0x00));
5656
ASSERT_OR_RETURN(varint.value == 0x00);
5757

5858
// username length
59-
VARINT_OR_DIE(varint, reader_index, payload_end, data_end);
59+
MAX_VARINT_OR_DIE(varint, reader_index, payload_end, data_end, VARINT_SIZE(LOGIN_NAME_DATA_MAX));
6060
// bounce check, invalid username
6161
ASSERT_IN_RANGE(varint.value, LOGIN_NAME_DATA_MIN, LOGIN_NAME_DATA_MAX);
6262
// skip the username data
@@ -73,14 +73,14 @@ static __always_inline __u8 inspect_login_packet(__u8 *reader_index, const __u8
7373
READ_OR_RETURN(reader_index, 8, payload_end, data_end);
7474

7575
// login key
76-
VARINT_OR_DIE(varint, reader_index, payload_end, data_end);
76+
MAX_VARINT_OR_DIE(varint, reader_index, payload_end, data_end, VARINT_SIZE(LOGIN_KEY_MAX));
7777
// assert reasonable size
7878
ASSERT_IN_RANGE(varint.value, LOGIN_KEY_MIN, LOGIN_KEY_MAX);
7979
// skip login key
8080
READ_OR_RETURN(reader_index, varint.value, payload_end, data_end);
8181

8282
// signaturey length
83-
VARINT_OR_DIE(varint, reader_index, payload_end, data_end);
83+
MAX_VARINT_OR_DIE(varint, reader_index, payload_end, data_end, VARINT_SIZE(LOGIN_SIGNATURE_MAX));
8484
// assert reasonable size
8585
ASSERT_IN_RANGE(varint.value, LOGIN_SIGNATURE_MIN, LOGIN_SIGNATURE_MAX);
8686
// skip signature
@@ -125,23 +125,23 @@ static __always_inline __s32 inspect_handshake(__u8 *reader_index, const __u8 *p
125125

126126
struct varint_value varint;
127127
// len 3 bytes varint max
128-
PACKET_LEN_OR_DIE(varint, reader_index, payload_end, data_end);
128+
MAX_VARINT_OR_DIE(varint, reader_index, payload_end, data_end, VARINT_SIZE((PACKET_ID_MAX + HANDSHAKE_DATA_MAX)));
129129
ASSERT_IN_RANGE(varint.value, (PACKET_ID_MIN + HANDSHAKE_DATA_MIN), (PACKET_ID_MAX + HANDSHAKE_DATA_MAX));
130130
// packet id
131-
VARINT_OR_DIE(varint, reader_index, payload_end, data_end);
131+
MAX_VARINT_OR_DIE(varint, reader_index, payload_end, data_end, VARINT_SIZE(0x00));
132132
ASSERT_OR_RETURN(varint.value == 0x00); // packet id needs to be 0
133133
// protocol version
134134
VARINT_OR_DIE(varint, reader_index, payload_end, data_end);
135135
*protocol_version = varint.value;
136136
// host len
137-
VARINT_OR_DIE(varint, reader_index, payload_end, data_end);
137+
MAX_VARINT_OR_DIE(varint, reader_index, payload_end, data_end, VARINT_SIZE(HANDSHAKE_HOST_DATA_MAX));
138138
ASSERT_IN_RANGE(varint.value, HANDSHAKE_HOST_DATA_MIN, HANDSHAKE_HOST_DATA_MAX);
139139
// read host
140140
READ_OR_RETURN(reader_index, varint.value, payload_end, data_end);
141141
// read port
142142
READ_OR_RETURN(reader_index, 2, payload_end, data_end);
143143
// intention
144-
VARINT_OR_DIE(varint, reader_index, payload_end, data_end);
144+
MAX_VARINT_OR_DIE(varint, reader_index, payload_end, data_end, VARINT_SIZE(3));
145145
__s32 intention = varint.value;
146146
__u8 support_transfer = *protocol_version >= 766;
147147

0 commit comments

Comments
 (0)