From 6895b40e47b2b63a48123241a5a5ef5008ba1cb7 Mon Sep 17 00:00:00 2001 From: Yukihiro Matsumoto Date: Sat, 1 Aug 2026 12:42:43 +0900 Subject: [PATCH] Bound the leading-zero skip in pm_integer_parse The PM_INTEGER_BASE_DEFAULT branch skips leading zeros without checking `end`, so it reads one byte past the range for an all-zero input. pm_float_node_rational_create() reaches it: it allocates `length` bytes for the mantissa, writes only `length - 1` of them because the decimal point is squeezed out, and passes end = digits + length - 1. Parsing `+0.0r` then walks the skip onto the byte that was never written. $ valgrind ./parse +0.0r Conditional jump or move depends on uninitialised value(s) at pm_integer_parse (integer.c:506) by pm_float_node_rational_create (prism.c:3963) by parse_expression_prefix (prism.c:17898) The value parsed is unaffected, since `start >= end` returns 0 either way. The other bases already guard with `(end - start) > 1`. Found by an mruby fuzzer testcase. --- src/integer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/integer.c b/src/integer.c index 1b69dbdceb..104052412d 100644 --- a/src/integer.c +++ b/src/integer.c @@ -503,7 +503,7 @@ pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *s uint32_t multiplier = 10; switch (base) { case PM_INTEGER_BASE_DEFAULT: - while (*start == '0') start++; // 01 -> 1 + while (start < end && *start == '0') start++; // 01 -> 1 break; case PM_INTEGER_BASE_BINARY: start += 2; // 0b