From 78a7f126f3236765c14028ecaf82295c6dc1612c Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Sun, 25 Oct 2026 17:19:14 +0900 Subject: [PATCH] Check the result of compile_length_tree() at every call site (#19505) Two call sites added a negative error code into a jump offset instead of returning it. It was harmless since compilation fails later anyway. Reported-by: Owais Lone (thesecguy) Co-authored-by: Claude Opus 5.5 --- regcomp.c | 7 ++++++- test/ruby/test_regexp.rb | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/regcomp.c b/regcomp.c index f5776c08e4e..f85e912c8d5 100644 --- a/regcomp.c +++ b/regcomp.c @@ -1356,6 +1356,7 @@ compile_enclose_node(EncloseNode* node, regex_t* reg) r = add_abs_addr(reg, (int )node->call_addr); if (r) return r; len = compile_length_tree(node->target, reg); + if (len < 0) return len; len += (SIZE_OP_MEMORY_START_PUSH + SIZE_OP_RETURN); if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)) len += (IS_ENCLOSE_RECURSION(node) @@ -1604,6 +1605,7 @@ compile_anchor_node(AnchorNode* node, regex_t* reg) { int n; len = compile_length_tree(node->target, reg); + if (len < 0) return ONIGERR_PARSER_BUG; r = add_opcode_rel_addr(reg, OP_PUSH_LOOK_BEHIND_NOT, len + SIZE_OP_FAIL_LOOK_BEHIND_NOT); if (r) return r; @@ -1742,7 +1744,9 @@ compile_tree(Node* node, regex_t* reg) Node* x = node; len = 0; do { - len += compile_length_tree(NCAR(x), reg); + r = compile_length_tree(NCAR(x), reg); + if (r < 0) return r; + len += r; if (NCDR(x) != NULL) { len += SIZE_OP_PUSH + SIZE_OP_JUMP; } @@ -1751,6 +1755,7 @@ compile_tree(Node* node, regex_t* reg) do { len = compile_length_tree(NCAR(node), reg); + if (len < 0) return ONIGERR_PARSER_BUG; if (IS_NOT_NULL(NCDR(node))) { r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_JUMP); if (r) break; diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index 11a5d34b5e2..7196ad71c40 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -2035,6 +2035,15 @@ class TestRegexp < Test::Unit::TestCase end; end + def test_invalid_condition_in_alternation_and_call + assert_raise_with_message(RegexpError, /invalid conditional pattern/) do + Regexp.new("(x)|(?(1)x|x|)") + end + assert_raise_with_message(RegexpError, /invalid conditional pattern/) do + Regexp.new("(?x)(?(?()x|x|))\\g") + end + end + def test_too_big_number_for_repeat_range assert_raise_with_message(SyntaxError, /too big number for repeat range/) do eval(%[/|{1000000}/])