Skip to content

Integer Truncation in h_token Allows Parser Bypass (/src/parsers/token.c) #3

@zwrh

Description

@zwrh

An integer truncation vulnerability exists in the Hammer parser library's h_token implementation located in:
/src/parsers/token.c

The function accepts a size_t length parameter but stores it in a uint8_t field inside the HToken structure. This truncates values larger than 255 bytes, creating a mismatch between the copied buffer size and the stored token length. This can allow an attacker to bypass parser token validation.

The vulnerable structures and functions:

typedef struct {
    uint8_t *str;
    uint8_t len;
} HToken;
...
HParser *h_token(const uint8_t *str, const size_t len) {
    return h_token__m(&system_allocator, str, len);
}

HParser *h_token__m(HAllocator *mm__, const uint8_t *str, const size_t len) {
    HToken *t = h_new(HToken, 1);
    uint8_t *str_cpy = h_new(uint8_t, len);
    memcpy(str_cpy, str, len);
    t->str = str_cpy, t->len = len; // truncated when assigned to uint8_t
    return h_new_parser(mm__, &token_vt, t);
}

The function accepts a size_t len parameter but stores it in a uint8_t:

  • size_t len → uint8_t len
  • If len > 255, the value is truncated: t->len = len % 256

However, the memcpy copies the full len bytes, creating inconsistent behavior between the stored token length and the actual allocated token buffer.

This mismatch can allow Token validation bypass, unexpected parser matches, incorrect parsing logic, and malformed inputs being accepted as valid tokens. If Hammer is used for protocol validation, input filtering, or security-sensitive parsing, this could allow invalid data to bypass parser rules.

Proof of Concept

#include <hammer/hammer.h>
#include <stdio.h>
#include <string.h>

int main(void) {
    uint8_t expected[256];

    memset(expected, 0x41, 256);

    HParser *parser = h_token(expected, 256);

    // Input clearly does not match expected token
    HParseResult *result = h_parse(parser, (uint8_t*)"Hello!", 0);

    if (result) {
        printf("bypassed!\n");
        h_parse_result_free(result);
    }

    return 0;
}

Expected Behavior:
The parser should reject "Hello!".

Actual Behavior:
The parser accepts the input due to the truncated token length.

Suggested Fix:
Use a larger integer type for the token length:

typedef struct {
    uint8_t *str;
    size_t len;
} HToken;

Researchers credited with discovering this issue:
Tyler Waddell
Ardian Peach
Muhammad Ali
Anthony Marrongelli

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions