Skip to content

Commit 35000ac

Browse files
authored
Prevent double free for too big repetition quantifiers (ruby#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.
1 parent 6b10d40 commit 35000ac

2 files changed

Lines changed: 16 additions & 7 deletions

File tree

regparse.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6721,7 +6721,7 @@ parse_subexp(Node** top, OnigToken* tok, int term,
67216721
UChar** src, UChar* end, ScanEnv* env)
67226722
{
67236723
int r;
6724-
Node *node, **headp;
6724+
Node *node, *topnode, **headp;
67256725

67266726
*top = NULL;
67276727
env->parse_depth++;
@@ -6737,26 +6737,29 @@ parse_subexp(Node** top, OnigToken* tok, int term,
67376737
*top = node;
67386738
}
67396739
else if (r == TK_ALT) {
6740-
*top = onig_node_new_alt(node, NULL);
6741-
headp = &(NCDR(*top));
6740+
topnode = onig_node_new_alt(node, NULL);
6741+
headp = &(NCDR(topnode));
67426742
while (r == TK_ALT) {
67436743
r = fetch_token(tok, src, end, env);
67446744
if (r < 0) {
6745-
onig_node_free(node);
6745+
onig_node_free(topnode);
67466746
return r;
67476747
}
67486748
r = parse_branch(&node, tok, term, src, end, env);
67496749
if (r < 0) {
6750-
onig_node_free(node);
6750+
onig_node_free(topnode);
67516751
return r;
67526752
}
67536753

67546754
*headp = onig_node_new_alt(node, NULL);
6755-
headp = &(NCDR(*headp));
6755+
headp = &(NCDR(*headp));
67566756
}
67576757

6758-
if (tok->type != (enum TokenSyms )term)
6758+
if (tok->type != (enum TokenSyms )term) {
6759+
onig_node_free(topnode);
67596760
goto err;
6761+
}
6762+
*top = topnode;
67606763
}
67616764
else {
67626765
onig_node_free(node);

test/ruby/test_regexp.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,6 +1875,12 @@ def test_invalid_group
18751875
end;
18761876
end
18771877

1878+
def test_too_big_number_for_repeat_range
1879+
assert_raise_with_message(SyntaxError, /too big number for repeat range/) do
1880+
eval(%[/|{1000000}/])
1881+
end
1882+
end
1883+
18781884
# This assertion is for porting x2() tests in testpy.py of Onigmo.
18791885
def assert_match_at(re, str, positions, msg = nil)
18801886
re = Regexp.new(re) unless re.is_a?(Regexp)

0 commit comments

Comments
 (0)