Skip to content

Heap buffer overflow READ in lre_exec_backtrack (libregexp.c:3068) via crafted bytecode #498

@Sebasteuo

Description

@Sebasteuo

Description

QuickJS (version 2025-09-13, commit d7ae12a) has a heap-buffer-overflow READ in lre_exec_backtrack() at libregexp.c:3068. The crash occurs in the REOP_loop handler when accessing capture[idx] with an out-of-bounds index derived from regex bytecode operands.

The issue was found by bytecode mutation fuzzing with AddressSanitizer.

ASAN output

ERROR: AddressSanitizer: heap-buffer-overflow on address 0x5030000064e8
READ of size 8 at 0x5030000064e8 thread T0
#0 in lre_exec_backtrack libregexp.c:3068
#1 in lre_exec libregexp.c:3359
#2 in js_regexp_exec quickjs.c:47467
0x5030000064e8 is located 8 bytes after 32-byte region

Reproduction

Build with ASAN:

# Patch Makefile: CFLAGS_OPT=-g -O0 -fsanitize=address,undefined ... and comment out -flto
make CC=gcc LDFLAGS="-fsanitize=address,undefined"

Compile harness:

#include <stdio.h>
#include <stdlib.h>
#include "quickjs.h"

int main(int argc, char **argv) {
    FILE *f = fopen(argv[1], "rb");
    fseek(f, 0, SEEK_END);
    size_t fsize = ftell(f);
    fseek(f, 0, SEEK_SET);
    uint8_t *buf = malloc(fsize);
    fread(buf, 1, fsize, f);
    fclose(f);
    JSRuntime *rt = JS_NewRuntime();
    JSContext *ctx = JS_NewContext(rt);
    JSValue obj = JS_ReadObject(ctx, buf, fsize, JS_READ_OBJ_BYTECODE);
    if (!JS_IsException(obj)) {
        JSValue ret = JS_EvalFunction(ctx, obj);
        JS_FreeValue(ctx, ret);
    } else { JS_FreeValue(ctx, obj); }
    JS_FreeContext(ctx);
    JS_FreeRuntime(rt);
    free(buf);
    return 0;
}
gcc -g -O0 -fsanitize=address,undefined -I. -o fuzz_bc fuzz_bc.c libquickjs.a -lm -lpthread -ldl
./fuzz_bc poc_regex_oob.bin

PoC binary attached.

Impact

Heap information disclosure and denial of service. The regex engine is reachable from normal JavaScript execution (RegExp.prototype.exec), though this specific crash was triggered via mutated bytecode containing crafted regex bytecode.

Severity

This is a heap-buffer-overflow (CWE-125: Out-of-bounds Read) that can lead to information disclosure and denial of service. I believe this warrants a CVE assignment.

Credit

Discovered by Sebastián Alba Vives (GitHub: @Sebasteuo)

I would appreciate being credited in any CVE or advisory issued for this vulnerability. I am available to assist with further analysis or patch review.

Environment

  • QuickJS version 2025-09-13, commit d7ae12a
  • Ubuntu 24.04 aarch64, GCC with ASAN/UBSan

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