From d0bc3c641d27c355ac8120721be308d7dde825a3 Mon Sep 17 00:00:00 2001
From: Petr Matyas
Date: Mon, 3 Aug 2026 17:19:09 +0200
Subject: [PATCH] pcre2_compile: zero-initialize code area before second-pass
compilation
When PCRE2 is used as a non-MSan-instrumented shared library inside an
MSan-instrumented program, bytes written to the compiled code via direct
assignment (e.g. literal character data for OP_CHAR opcodes) are not tracked
in MSan's shadow memory. The JIT compiler's detect_repeat() calls memcmp()
over compiled bytecode blocks, and MSan's memcmp interceptor reports a
use-of-uninitialized-value error for those character bytes.
Fix by zeroing the code area with memset() before the second compilation pass.
MSan's memset interceptor marks all code bytes as initialized in the shadow;
the compiler then overwrites them with the actual bytecode values. This
eliminates the spurious MSan error without any correctness impact.
Reproducer (requires clang + system PCRE2 without MSan instrumentation):
clang -fsanitize=memory -o test test.c -lpcre2-8
// test.c:
#define PCRE2_CODE_UNIT_WIDTH 8
#include
int main(void) {
int e; PCRE2_SIZE off;
pcre2_code *re = pcre2_compile(
(PCRE2_SPTR)"^(/foo/bar)(/foo/bar)$",
PCRE2_ZERO_TERMINATED, PCRE2_DOTALL, &e, &off, NULL);
pcre2_jit_compile(re, PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT);
}
// => MSan: use-of-uninitialized-value in memcmp inside pcre2_jit_compile_8
Tested on: aarch64 (PCRE2 10.44) and x86_64 (PCRE2 10.47).
Signed-off-by: Petr Matyas
---
src/pcre2_compile.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/pcre2_compile.c b/src/pcre2_compile.c
index c64fd2739..ed92d7cd1 100644
--- a/src/pcre2_compile.c
+++ b/src/pcre2_compile.c
@@ -10963,6 +10963,16 @@ if (cb.names_found > 0)
error, errorcode will be set non-zero, so we don't need to look at the result
of the function here. */
+/* Zero-initialize the code area before the second compilation pass.
+When PCRE2 is used as a non-MSan-instrumented shared library, bytes written to
+the compiled code via direct assignment (e.g. OP_CHAR character data) are not
+tracked in MSan's shadow memory. The JIT compiler's detect_repeat() then calls
+memcmp() over compiled bytecode blocks, and MSan's memcmp interceptor reports
+a use-of-uninitialized-value error for those char bytes. Zeroing the area here
+ensures all code bytes are initialized in the sanitizer shadow before the
+compiler overwrites them with the actual bytecode values. */
+memset((void *)codestart, 0, re_blocksize - re->code_start);
+
pptr = cb.parsed_pattern;
code = (PCRE2_UCHAR *)codestart;
*code = OP_BRA;