mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-20 11:36:10 +00:00
LibRegex: Fix crash when parse result exceeds max cache size
Before, If the cache was empty we would try and evict non-existant entries and crash. So the fix is to make sure that we don't saturate the cache with a single parse result.
This commit is contained in:
parent
99df80f81e
commit
83e46b3728
Notes:
github-actions[bot]
2025-04-04 14:11:28 +00:00
Author: https://github.com/ttrssreal Commit: https://github.com/LadybirdBrowser/ladybird/commit/83e46b37281 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4221 Reviewed-by: https://github.com/alimpfard ✅
2 changed files with 21 additions and 6 deletions
|
@ -77,3 +77,7 @@ test("v flag should enable unicode mode", () => {
|
|||
const re = new RegExp("a\\u{10FFFF}", "v");
|
||||
expect(re.test("a\u{10FFFF}")).toBe(true);
|
||||
});
|
||||
|
||||
test("parsing a large bytestring shouldn't crash", () => {
|
||||
RegExp(new Uint8Array(0x40000));
|
||||
});
|
||||
|
|
|
@ -48,6 +48,20 @@ static size_t s_cached_bytecode_size = 0;
|
|||
|
||||
static constexpr auto MaxRegexCachedBytecodeSize = 1 * MiB;
|
||||
|
||||
template<class Parser>
|
||||
static void cache_parse_result(regex::Parser::Result const& result, CacheKey<Parser> const& key)
|
||||
{
|
||||
auto bytecode_size = result.bytecode.size() * sizeof(ByteCodeValueType);
|
||||
if (bytecode_size > MaxRegexCachedBytecodeSize)
|
||||
return;
|
||||
|
||||
while (bytecode_size + s_cached_bytecode_size<Parser> > MaxRegexCachedBytecodeSize)
|
||||
s_cached_bytecode_size<Parser> -= s_parser_cache<Parser>.take_first().bytecode.size() * sizeof(ByteCodeValueType);
|
||||
|
||||
s_parser_cache<Parser>.set(key, result);
|
||||
s_cached_bytecode_size<Parser> += bytecode_size;
|
||||
}
|
||||
|
||||
template<class Parser>
|
||||
Regex<Parser>::Regex(ByteString pattern, typename ParserTraits<Parser>::OptionsType regex_options)
|
||||
: pattern_value(move(pattern))
|
||||
|
@ -61,12 +75,9 @@ Regex<Parser>::Regex(ByteString pattern, typename ParserTraits<Parser>::OptionsT
|
|||
parser_result = parser.parse();
|
||||
|
||||
run_optimization_passes();
|
||||
if (parser_result.error == regex::Error::NoError) {
|
||||
while (parser_result.bytecode.size() * sizeof(ByteCodeValueType) + s_cached_bytecode_size<Parser> > MaxRegexCachedBytecodeSize)
|
||||
s_cached_bytecode_size<Parser> -= s_parser_cache<Parser>.take_first().bytecode.size() * sizeof(ByteCodeValueType);
|
||||
s_parser_cache<Parser>.set({ pattern_value, regex_options }, parser_result);
|
||||
s_cached_bytecode_size<Parser> += parser_result.bytecode.size() * sizeof(ByteCodeValueType);
|
||||
}
|
||||
|
||||
if (parser_result.error == regex::Error::NoError)
|
||||
cache_parse_result<Parser>(parser_result, { pattern_value, regex_options });
|
||||
}
|
||||
|
||||
if (parser_result.error == regex::Error::NoError)
|
||||
|
|
Loading…
Add table
Reference in a new issue