зеркало из https://github.com/github/ruby.git
merge revision(s) d292a9b98ce03c76dbe13138d20b9fbf613cc02d: [Backport #20453]
[Bug #20453] segfault in Regexp timeout https://bugs.ruby-lang.org/issues/20228 started freeing `stk_base` to avoid a memory leak. But `stk_base` is sometimes stack allocated (using `xalloca`), so the free only works if the regex stack has grown enough to hit `stack_double` (which uses `xmalloc` and `xrealloc`). To reproduce the problem on master and 3.3.1: ```ruby Regexp.timeout = 0.001 /^(a*)x$/ =~ "a" * 1000000 + "x"' ``` Some details about this potential fix: `stk_base == stk_alloc` on [init](dde99215f2/regexec.c (L1153)
), so if `stk_base != stk_alloc` we can be sure we called [`stack_double`](dde99215f2/regexec.c (L1210)
) and it's safe to free. It's also safe to free if we've [saved](dde99215f2/regexec.c (L1187-L1189)
) the stack to `msa->stack_p`, since we do the `stk_base != stk_alloc` check before saving. This matches the check we do inside [`stack_double`](dde99215f2/regexec.c (L1221)
)
This commit is contained in:
Родитель
5c06e93074
Коммит
cf643fabd5
|
@ -4218,7 +4218,8 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
|
||||||
|
|
||||||
timeout:
|
timeout:
|
||||||
xfree(xmalloc_base);
|
xfree(xmalloc_base);
|
||||||
xfree(stk_base);
|
if (stk_base != stk_alloc || IS_NOT_NULL(msa->stack_p))
|
||||||
|
xfree(stk_base);
|
||||||
HANDLE_REG_TIMEOUT_IN_MATCH_AT;
|
HANDLE_REG_TIMEOUT_IN_MATCH_AT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1827,6 +1827,17 @@ class TestRegexp < Test::Unit::TestCase
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_bug_20453
|
||||||
|
assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
|
||||||
|
begin;
|
||||||
|
Regexp.timeout = 0.001
|
||||||
|
|
||||||
|
assert_raise(Regexp::TimeoutError) do
|
||||||
|
/^(a*)x$/ =~ "a" * 1000000 + "x"
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
def per_instance_redos_test(global_timeout, per_instance_timeout, expected_timeout)
|
def per_instance_redos_test(global_timeout, per_instance_timeout, expected_timeout)
|
||||||
assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
|
assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
|
||||||
global_timeout = #{ EnvUtil.apply_timeout_scale(global_timeout).inspect }
|
global_timeout = #{ EnvUtil.apply_timeout_scale(global_timeout).inspect }
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
|
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
|
||||||
#define RUBY_VERSION_TEENY 1
|
#define RUBY_VERSION_TEENY 1
|
||||||
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
|
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
|
||||||
#define RUBY_PATCHLEVEL 71
|
#define RUBY_PATCHLEVEL 72
|
||||||
|
|
||||||
#include "ruby/version.h"
|
#include "ruby/version.h"
|
||||||
#include "ruby/internal/abi.h"
|
#include "ruby/internal/abi.h"
|
||||||
|
|
Загрузка…
Ссылка в новой задаче