Loading changes/ticket41245 0 → 100644 +4 −0 Original line number Diff line number Diff line o Major bugfixes (relay, onion service): - Fix off-by-one out-of-bounds read if a malformed BEGIN cell is received. TROVE-2026-007. Found by Flanagan. Fixes bug 41245; bugfix on 0.2.4.7-alpha. src/core/or/connection_edge.c +1 −1 Original line number Diff line number Diff line Loading @@ -3865,7 +3865,7 @@ begin_cell_parse(const cell_t *cell, begin_cell_t *bcell, *end_reason_out = END_STREAM_REASON_TORPROTOCOL; return -1; } if (body + rh.length >= nul + 4) if (body + rh.length > nul + 4) bcell->flags = ntohl(get_uint32(nul+1)); return 0; Loading src/test/test_cell_formats.c +17 −0 Original line number Diff line number Diff line Loading @@ -233,6 +233,23 @@ test_cfmt_begin_cells(void *arg) make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:80", 6); tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); /* bad begin cell: this makes sure we never read out of bound (#41245). * * We set 10 bytes in the payload (address + 3 bytes of flags). Omitting the * last flag byte triggers an off-by-one: the buggy condition (>=) would read * out of ound. The fixed condition (>) does not set flags at all. */ memset(&bcell, 0x7f, sizeof(bcell)); const char payload[] = "a.b:80\x00\x42\x43\x44"; make_relay_cell(&cell, RELAY_COMMAND_BEGIN, payload, sizeof(payload) - 1); tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); tt_int_op(5, OP_EQ, bcell.stream_id); tt_str_op("a.b", OP_EQ, bcell.address); tt_int_op(80, OP_EQ, bcell.port); /* With the bug it would be 0x424344<junk> */ tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(0, OP_EQ, bcell.is_begindir); tor_free(bcell.address); done: tor_free(bcell.address); } Loading Loading
changes/ticket41245 0 → 100644 +4 −0 Original line number Diff line number Diff line o Major bugfixes (relay, onion service): - Fix off-by-one out-of-bounds read if a malformed BEGIN cell is received. TROVE-2026-007. Found by Flanagan. Fixes bug 41245; bugfix on 0.2.4.7-alpha.
src/core/or/connection_edge.c +1 −1 Original line number Diff line number Diff line Loading @@ -3865,7 +3865,7 @@ begin_cell_parse(const cell_t *cell, begin_cell_t *bcell, *end_reason_out = END_STREAM_REASON_TORPROTOCOL; return -1; } if (body + rh.length >= nul + 4) if (body + rh.length > nul + 4) bcell->flags = ntohl(get_uint32(nul+1)); return 0; Loading
src/test/test_cell_formats.c +17 −0 Original line number Diff line number Diff line Loading @@ -233,6 +233,23 @@ test_cfmt_begin_cells(void *arg) make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:80", 6); tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); /* bad begin cell: this makes sure we never read out of bound (#41245). * * We set 10 bytes in the payload (address + 3 bytes of flags). Omitting the * last flag byte triggers an off-by-one: the buggy condition (>=) would read * out of ound. The fixed condition (>) does not set flags at all. */ memset(&bcell, 0x7f, sizeof(bcell)); const char payload[] = "a.b:80\x00\x42\x43\x44"; make_relay_cell(&cell, RELAY_COMMAND_BEGIN, payload, sizeof(payload) - 1); tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); tt_int_op(5, OP_EQ, bcell.stream_id); tt_str_op("a.b", OP_EQ, bcell.address); tt_int_op(80, OP_EQ, bcell.port); /* With the bug it would be 0x424344<junk> */ tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(0, OP_EQ, bcell.is_begindir); tor_free(bcell.address); done: tor_free(bcell.address); } Loading