Skip to content

Commit a9850e2

Browse files
authored
Merge pull request chakra-core#6857 from rhuanjl/FixCharTrieClone
Fix CharTrie::CloneFrom CharTrie::CloneFrom uses recursion to clone a CharTrie tree. Currently this can overflow the native stack producing an uncatchable hard crash. Fix by inserting a PROBE_STACK call that checks sufficient stack space is left and throws a catchable JS exception if not. Fix chakra-core#6835
2 parents 58639f9 + 9760c11 commit a9850e2

File tree

5 files changed

+67
-4
lines changed

5 files changed

+67
-4
lines changed

lib/Parser/CharTrie.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56
#include "ParserPch.h"
@@ -199,16 +200,17 @@ namespace UnifiedRegex
199200
#endif
200201
}
201202

202-
void RuntimeCharTrie::CloneFrom(ArenaAllocator* allocator, const CharTrie& other)
203+
void RuntimeCharTrie::CloneFrom(Js::ScriptContext* scriptContext, ArenaAllocator* allocator, const CharTrie& other)
203204
{
205+
PROBE_STACK_NO_DISPOSE(scriptContext, Js::Constants::MinStackRegex);
204206
count = other.count;
205207
if (count > 0)
206208
{
207209
children = AnewArray(allocator, RuntimeCharTrieEntry, count);
208210
for (int i = 0; i < count; i++)
209211
{
210212
children[i].c = other.children[i].c;
211-
children[i].node.CloneFrom(allocator, other.children[i].node);
213+
children[i].node.CloneFrom(scriptContext, allocator, other.children[i].node);
212214
}
213215
}
214216
else

lib/Parser/CharTrie.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56
#pragma once
@@ -65,7 +66,7 @@ namespace UnifiedRegex
6566
public:
6667
inline RuntimeCharTrie() : count(0), children(0) {}
6768
void FreeBody(ArenaAllocator* allocator);
68-
void CloneFrom(ArenaAllocator* allocator, const CharTrie& other);
69+
void CloneFrom(Js::ScriptContext* scriptContext, ArenaAllocator* allocator, const CharTrie& other);
6970

7071
bool Match
7172
( const Char* const input

lib/Parser/RegexCompileTime.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56
#include "ParserPch.h"
@@ -2538,7 +2539,7 @@ namespace UnifiedRegex
25382539
{
25392540
// Root of trie will live in compile-time allocator, but body will be in run-time allocator
25402541
runtimeTrie = Anew(compiler.ctAllocator, RuntimeCharTrie);
2541-
runtimeTrie->CloneFrom(compiler.rtAllocator, trie);
2542+
runtimeTrie->CloneFrom(compiler.scriptContext, compiler.rtAllocator, trie);
25422543
scheme = Trie;
25432544
}
25442545
return;

test/Regex/regexCharTrieStack.js

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
4+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
5+
//-------------------------------------------------------------------------------------------------------
6+
7+
var testString = "tacgattttatcgcgactagttaatcatcatagcaagtaaaatttgaattatgtcattat\
8+
catgctccattaacaggttatttaattgatactgacgaaattttttcacaatgggttttc\
9+
tagaatttaatatcagtaattgaagccttcataggggtcctactagtatcctacacgacg\
10+
caggtccgcagtatcctggagggacgtgttactgattaaaagggtcaaaggaatgaaggc\
11+
tcacaatgttacctgcttcaccatagtgagccgatgagttttacattagtactaaatccc\
12+
aaatcatactttacgatgaggcttgctagcgctaaagagaatacatacaccaccacatag\
13+
aattgttagcgatgatatcaaatagactcctggaagtgtcagggggaaactgttcaatat\
14+
ttcgtccacaggactgaccaggcatggaaaagactgacgttggaaactataccatctcac\
15+
gcccgacgcttcactaattgatgatccaaaaaatatagcccggattcctgattagcaaag\
16+
ggttcacagagaaagatattatcgacgtatatcccaaaaaacagacgtaatgtgcatctt\
17+
cgaatcgggatgaatacttgtatcataaaaatgtgacctctagtatacaggttaatgtta\
18+
ctcacccacgtatttggtctaattatgttttatttagtgacaatccaatagataaccggt\
19+
cctattaagggctatatttttagcgaccacgcgtttaaacaaaggattgtatgtagatgg\
20+
gcttgatataagatttcggatgtatgggttttataatcgttggagagctcaatcatgagc\
21+
taatacatggatttcgctacctcaccgagagaccttgcatgaagaattctaaccaaaagt\
22+
ttaataggccggattggattgagttaattaagaccttgttcagtcatagtaaaaaccctt\n\
23+
aaattttaccgattgacaaagtgagcagtcgcaataccctatgcgaaacgcctcgatagt\n\
24+
gactaggtatacaaggtttttgagttcctttgaaatagttaactaatttaaaattaatta\n\
25+
acgacatggaaatcacagaacctaatgctttgtaggagttatttatgctgtttactgcct\n\
26+
ctacaaccctaataaagcagtcctaagaatgaaacgcatcttttagttcagaaagtggta\n\
27+
tccagggtggtcaatttaataaattcaacatcgggtctcaggatattcggtcatataatt\n\
28+
tattaagggctcttcgagtcttactctgagtgaaattggaaacagtcatccttttcgttg\n\
29+
tgaggcatcttacaccgctatcgatatacaatgcattccaccgcggtgtcccgtacacaa\n\
30+
ggaaacttgttaccttggggatataagaaaactcacacgtctcattattaaactgagtac\n\
31+
tggaacgcacctcggatctgttgcactggattaaaatccgattatttttaaaaatattca\n\
32+
gtgctagagcatatcaggtctacttttttatctggtatgtaaagcccacggagcgatagt\n\
33+
gagatccttacgactcaacgaaaagttataacataactcccgttagccaaagcccaatcc\n\
34+
\n";
35+
testString = testString + testString + testString;
36+
testString = testString + testString + testString;
37+
testString = testString + testString + testString;
38+
testString = testString + testString + testString;
39+
var seqs = [/a|tttaccct/ig];
40+
41+
Array.prototype.push.call(seqs, false, Array.prototype.concat.call(seqs, seqs, testString));
42+
try {
43+
for (i in seqs) {
44+
testString.match(seqs[i]);
45+
}
46+
print ("Test should produce Stack over flow but didn't, case may need amending")
47+
}
48+
catch(e) {
49+
if (e == "Error: Out of stack space") {
50+
print ("pass")
51+
} else {
52+
print ("Wrong error thrown, expected \"Error: Out of stack space\" but recieved \"" + e + "\"");
53+
}
54+
}

test/Regex/rlexe.xml

+5
Original file line numberDiff line numberDiff line change
@@ -247,4 +247,9 @@
247247
<compile-flags>-args summary -endargs</compile-flags>
248248
</default>
249249
</test>
250+
<test>
251+
<default>
252+
<files>regexCharTrieStack.js</files>
253+
</default>
254+
</test>
250255
</regress-exe>

0 commit comments

Comments
 (0)