bneradt commented on code in PR #13621:
URL: https://github.com/apache/trafficserver/pull/13621#discussion_r3919631351
##########
src/proxy/http3/QPACK.cc:
##########
@@ -1221,6 +1227,10 @@ QPACK::estimate_header_block_size(const HTTPHdr & /* hdr
ATS_UNUSED */)
const XpackLookupResult
QPACK::StaticTable::lookup(uint16_t index, const char **name, size_t
*name_len, const char **value, size_t *value_len)
{
+ if (index >= countof(STATIC_HEADER_FIELDS)) {
+ return {index, XpackLookupResult::MatchType::NONE};
+ }
+
Review Comment:
Fixed. `StaticTable::lookup()` now takes a `uint64_t` index, and
`_read_insert_with_name_ref()` reports the index as `uint64_t`, so the decoded
value reaches the bounds check at full width instead of wrapping into an
in-range slot first. The `> 0xFFFF` clamp in `_read_insert_with_name_ref()`
existed only to protect the `uint16_t` out-parameter, so it is gone; range
validation is the table lookup's job now. The encoder-stream dynamic branch is
bounded to `uint32_t` explicitly before calling into the dynamic table.
The decoder's dynamic-table branch still narrows through
`_calc_absolute_index_from_relative_index()`, which is `uint16_t` throughout
and wraps on underflow. That is a pre-existing problem in the relative-index
arithmetic rather than the static-table bounds check, so I left it for separate
work.
##########
src/proxy/http3/QPACK.cc:
##########
@@ -1155,7 +1155,13 @@ QPACK::_on_encoder_stream_read_ready(IOBufferReader
&reader)
}
QPACKDebug("Received Insert With Name Ref: is_static=%d, index=%d,
value=%.*s", is_static, index, static_cast<int>(value_len),
value);
- StaticTable::lookup(index, &name, &name_len, &dummy, &dummy_len);
+ auto result = is_static ? StaticTable::lookup(index, &name, &name_len,
&dummy, &dummy_len) :
+ this->_dynamic_table.lookup(index, &name,
&name_len, &dummy, &dummy_len);
+ if (result.match_type != XpackLookupResult::MatchType::EXACT) {
+ this->_arena.str_free(value);
+ this->_abort_decode();
+ return EVENT_DONE;
+ }
Review Comment:
Added "An out-of-range encoder stream name reference invalidates the
decoder", which feeds an Insert With Name Reference for static index 100 over
the encoder stream and asserts the decoder is left invalid. Verified it fails
without the new `match_type != EXACT` guard: the process aborts on the entry
built from the out-of-range lookup.
The stream has to be opened and written from an event thread.
`QUICStreamVCAdapter` schedules its read-ready event on `this_ethread()` and
will not schedule another until that one is handled, so doing either from the
test's own thread leaves the event queued on a thread that never runs an event
loop.
##########
src/proxy/http3/test/test_QPACK.cc:
##########
@@ -405,6 +405,31 @@ test_decode(const char *enc_file, const char *out_file,
int dts, int mbs)
return ret;
}
+TEST_CASE("Decoding out-of-range static table indexes fails", "[qpack-decode]")
+{
+ QUICApplicationDriver driver;
+ QPACK qpack(driver.get_connection(), UINT32_MAX, 0, 0,
MAX_FIELD_SIZE);
+ TestQPACKEventHandler event_handler;
+ HTTPHdr hdr;
+
+ hdr.create(HTTPType::REQUEST);
+
+ const uint8_t header_block[] = {
+ 0x00, // Required Insert Count.
+ 0x00, // Delta Base.
+ 0xff, // Indexed static field with an extended 6-bit index.
+ 0x25, // Index 100.
+ };
+
+ CHECK(qpack.decode(1, header_block, sizeof(header_block), hdr,
&event_handler, eventProcessor.all_ethreads[0]) == 0);
+
+ sleep(1);
+
+ CHECK(event_handler.last_event() == QPACK_EVENT_DECODE_FAILED);
Review Comment:
Replaced with a bounded poll. There is now a `wait_for_event()` helper that
polls at 10ms up to a 5s timeout and returns whether the expected event
arrived, so the test finishes as soon as the callback lands and still fails
deterministically if it never does. `test_qpack` went from ~1.0s to 0.04s.
I left the pre-existing `sleep(1)` in `test_decode()` alone since it waits
on a different condition and is outside this change.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]