Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index c778c32231f7cc87710727a40d974e1edc460134..39e8ca3fafbaf40381bdab12d8a4de2d24f1123e 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -3237,26 +3237,34 @@ Handle<String> Runtime::StringReplaceOneCharWithString(Isolate* isolate, |
Handle<String> subject, |
Handle<String> search, |
Handle<String> replace, |
- bool* found) { |
+ bool* found, |
+ int recursion_limit) { |
+ if (recursion_limit == 0) return Handle<String>::null(); |
if (subject->IsConsString()) { |
ConsString* cons = ConsString::cast(*subject); |
Handle<String> first = Handle<String>(cons->first()); |
Handle<String> second = Handle<String>(cons->second()); |
- Handle<String> new_first = StringReplaceOneCharWithString(isolate, |
- first, |
- search, |
- replace, |
- found); |
- if (*found) { |
- return isolate->factory()->NewConsString(new_first, second); |
- } else { |
- Handle<String> new_second = StringReplaceOneCharWithString(isolate, |
- second, |
- search, |
- replace, |
- found); |
- return isolate->factory()->NewConsString(first, new_second); |
- } |
+ Handle<String> new_first = |
+ StringReplaceOneCharWithString(isolate, |
+ first, |
+ search, |
+ replace, |
+ found, |
+ recursion_limit - 1); |
+ if (*found) return isolate->factory()->NewConsString(new_first, second); |
+ if (new_first.is_null()) return new_first; |
+ |
+ Handle<String> new_second = |
+ StringReplaceOneCharWithString(isolate, |
+ second, |
+ search, |
+ replace, |
+ found, |
+ recursion_limit - 1); |
+ if (*found) return isolate->factory()->NewConsString(first, new_second); |
+ if (new_second.is_null()) return new_second; |
+ |
+ return subject; |
} else { |
int index = StringMatch(isolate, subject, search, 0); |
if (index == -1) return subject; |
@@ -3276,13 +3284,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) { |
CONVERT_ARG_CHECKED(String, subject, 0); |
CONVERT_ARG_CHECKED(String, search, 1); |
CONVERT_ARG_CHECKED(String, replace, 2); |
- bool found = false; |
- return *(Runtime::StringReplaceOneCharWithString(isolate, |
- subject, |
- search, |
- replace, |
- &found)); |
+ // If the cons string tree is too deep, we simply abort the recursion and |
+ // retry with a flattened subject string. |
+ const int kRecursionLimit = 0x1000; |
Yang
2012/01/17 13:07:34
Recursion limit is chosen so that regexpdna still
|
+ bool found = false; |
+ for (int i = 0; i < 2; i++) { |
Erik Corry
2012/01/17 13:50:24
I think this would be clearer without the loop, ju
Yang
2012/01/17 14:29:04
Done.
|
+ Handle<String> result = |
+ Runtime::StringReplaceOneCharWithString(isolate, |
+ subject, |
+ search, |
+ replace, |
+ &found, |
+ kRecursionLimit); |
+ if (!result.is_null()) return *result; |
Erik Corry
2012/01/17 13:51:21
Should you have a test for found == false here and
Yang
2012/01/17 14:29:04
Allocation is only ever done if found==true. In al
|
+ subject = FlattenGetString(subject); |
+ } |
+ UNREACHABLE(); |
+ return NULL; |
} |