Prevent double free for too big repetition quantifiers (#13332)

Prevent double free for too big repetition quantifiers

The previous implementation calls `free(node)` twice (on parsing and compiling a
regexp) when it has an error, so it leads to a double-free issue. This
commit enforces `free(node)` once by introducing a temporal pointer to hold
parsing nodes.
This commit is contained in:
Hiroya Fujinami 2025-05-16 10:14:26 +09:00 committed by GitHub
parent 6b10d40157
commit 35000ac2ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2025-05-16 01:14:39 +00:00
Merged-By: makenowjust <make.just.on@gmail.com>
2 changed files with 16 additions and 7 deletions

View File

@ -6721,7 +6721,7 @@ parse_subexp(Node** top, OnigToken* tok, int term,
UChar** src, UChar* end, ScanEnv* env)
{
int r;
Node *node, **headp;
Node *node, *topnode, **headp;
*top = NULL;
env->parse_depth++;
@ -6737,17 +6737,17 @@ parse_subexp(Node** top, OnigToken* tok, int term,
*top = node;
}
else if (r == TK_ALT) {
*top = onig_node_new_alt(node, NULL);
headp = &(NCDR(*top));
topnode = onig_node_new_alt(node, NULL);
headp = &(NCDR(topnode));
while (r == TK_ALT) {
r = fetch_token(tok, src, end, env);
if (r < 0) {
onig_node_free(node);
onig_node_free(topnode);
return r;
}
r = parse_branch(&node, tok, term, src, end, env);
if (r < 0) {
onig_node_free(node);
onig_node_free(topnode);
return r;
}
@ -6755,9 +6755,12 @@ parse_subexp(Node** top, OnigToken* tok, int term,
headp = &(NCDR(*headp));
}
if (tok->type != (enum TokenSyms )term)
if (tok->type != (enum TokenSyms )term) {
onig_node_free(topnode);
goto err;
}
*top = topnode;
}
else {
onig_node_free(node);
err:

View File

@ -1875,6 +1875,12 @@ class TestRegexp < Test::Unit::TestCase
end;
end
def test_too_big_number_for_repeat_range
assert_raise_with_message(SyntaxError, /too big number for repeat range/) do
eval(%[/|{1000000}/])
end
end
# This assertion is for porting x2() tests in testpy.py of Onigmo.
def assert_match_at(re, str, positions, msg = nil)
re = Regexp.new(re) unless re.is_a?(Regexp)