Skip to content

Decoder accepts a Sign bit of 1 when Required Insert Count is 0 (RFC 9204 §4.5.1.2 MUST) #90

Description

@vcarus

Decoder accepts a Sign bit of 1 when Required Insert Count is 0 (RFC 9204 §4.5.1.2 MUST)

Version: 2.7.0 (9156770); the relevant code is unchanged back through at least 2.6.x.

Summary

lsqpack_dec_read_header accepts an encoded field section whose prefix has the Delta Base Sign bit set to 1 while the Required Insert Count is 0. RFC 9204 §4.5.1.2 requires:

An endpoint MUST treat a field block with a Sign bit of 1 as invalid if the value of Required Insert Count is less than or equal to the value of Delta Base.

When Required Insert Count is 0, every non-negative Delta Base satisfies RIC <= Delta Base, so a Sign bit of 1 is always invalid. The decoder returns success instead.

Mechanism

In the prefix state machine (lsqpack.c, PREFIX_STATE_READ_DELTA_BASE_IDX), the Sign bit is only consulted when a dynamic-table reference was signalled (HBRC_LARGEST_REF_SET). With Required Insert Count 0 the else branch runs and sets the base unconditionally, discarding DELB.sign:

case PREFIX_STATE_READ_DELTA_BASE_IDX:
    r = lsqpack_dec_int(&buf, end, prefix_bits, &DELB.value, &DELB.dec_int_state);
    if (r == 0)
    {
        if (read_ctx->hbrc_flags & HBRC_LARGEST_REF_SET)
        {
            if (DELB.sign)
                read_ctx->hbrc_base_index =
                    ID_MINUS(read_ctx->hbrc_largest_ref, DELB.value + 1);
            else
                read_ctx->hbrc_base_index =
                        ID_PLUS(read_ctx->hbrc_largest_ref, DELB.value);
        }
        else    /* Sign bit is never checked here */
            read_ctx->hbrc_base_index = 0;
        ...

Reproduction

Each of these field sections is accepted (verified with the decoder returning :scheme: https); RFC 9204 §4.5.1.2 requires each to be rejected. Byte 1 is Required Insert Count = 0; byte 2 has the Sign bit (0x80) set with the low 7 bits carrying Delta Base; the remainder is a well-formed representation (0xd7 = Indexed Field Line, static table entry 23, :scheme: https).

00 80 d7
00 81 d7
00 87 d7
00 fe d7
00 ff 00 d7   (Delta Base spelled with a continuation octet)
00 ff 49 d7

Note

Found by a differential decoding oracle run against a third-party HTTP/3 implementation; every other divergence it surfaced adjudicated in ls-qpack's favor or was a deliberate layering choice on our side. This is the one that came out the other way. Reporting it upstream as a courtesy — we do not depend on ls-qpack directly.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions