From e2b2db9f6615187b3793d19ede79a482f40e66a1 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 25 Aug 2026 07:45:34 +0900 Subject: [PATCH] Fix stack-use-after-return when the depth limit refuses a hash parse_assocs stores the address of its caller's stack-local pm_static_literals_t into parser->current_hash_keys so that a hash written directly into another with ** shares its keys, and the PM_TOKEN_BRACE_LEFT case in parse_expression_prefix is the only place that takes it back out and sets it to NULL. parse_expression returns before reaching parse_expression_prefix when depth has hit PRISM_DEPTH_MAXIMUM, so on input deep enough to reach the limit inside such a hash, nothing takes the pointer. The frame holding the static literals then returns, and the next hash to be parsed adds its keys to a dead stack frame. Clear the pointer where the expression it was handed over for is refused. Co-authored-by: Claude --- src/prism.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/prism.c b/src/prism.c index 51980155e4..b49b4a257b 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22526,6 +22526,15 @@ static pm_node_t * parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) { if (PRISM_UNLIKELY(depth >= PRISM_DEPTH_MAXIMUM)) { pm_parser_err_current(parser, PM_ERR_NESTING_TOO_DEEP); + + // A current_hash_keys handed over for the expression we are declining + // to parse points at a stack local of the frame waiting for it. Only + // the PM_TOKEN_BRACE_LEFT case in parse_expression_prefix takes it and + // sets it back to NULL, and returning here means that never runs, so + // the pointer would outlive the frame it points into and the next hash + // to be parsed would add its keys to a dead stack frame. + parser->current_hash_keys = NULL; + return UP(pm_error_recovery_node_create(parser, PM_TOKEN_START(parser, &parser->current), PM_TOKEN_LENGTH(&parser->current))); }