From e26bcf6e5e4f4f62b4e2f89cdb6480d24dba2aa3 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 17 May 2026 08:50:30 +0000 Subject: [PATCH] fix(libc): avoid undefined memcpy in js_worker_postMessage with len==0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit memcpy(dst, src, 0) is UB per C11 7.21.1 when either pointer is NULL, even if no bytes are copied — UBSan with -fsanitize=nonnull-attribute flags it and a strict optimiser may exploit the implied non-NULL attribute to elide subsequent NULL checks. In practice JS_WriteObject2 always emits a non-empty buffer, but make the call site safe by hand so the worker pipe is robust to any future serializer change. No test: triggering the UB requires data_len == 0 and malloc(0) returning non-NULL, which doesn't happen on the current writer. UBSan in CI would catch a regression. --- quickjs-libc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/quickjs-libc.c b/quickjs-libc.c index 1fe3cf5c1..f6b10a909 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -4254,7 +4254,10 @@ static JSValue js_worker_postMessage(JSContext *ctx, JSValueConst this_val, msg->data = malloc(data_len); if (!msg->data) goto fail; - memcpy(msg->data, data, data_len); + /* memcpy with NULL src/dst is UB even when n == 0; the writer side + can produce zero-length payloads (e.g. JSON.stringify(undefined)). */ + if (data_len > 0) + memcpy(msg->data, data, data_len); msg->data_len = data_len; if (sab_tab.len > 0) {