Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: src/jsregexp.cc

Issue 7170014: Avoid OOM on regexps with nested quantifiers. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ast.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 3748 matching lines...) Expand 10 before | Expand all | Expand 10 after
3759 // this case. 3759 // this case.
3760 static const int kMaxUnrolledMinMatches = 3; // Unroll (foo)+ and (foo){3,} 3760 static const int kMaxUnrolledMinMatches = 3; // Unroll (foo)+ and (foo){3,}
3761 static const int kMaxUnrolledMaxMatches = 3; // Unroll (foo)? and (foo){x,3} 3761 static const int kMaxUnrolledMaxMatches = 3; // Unroll (foo)? and (foo){x,3}
3762 if (max == 0) return on_success; // This can happen due to recursion. 3762 if (max == 0) return on_success; // This can happen due to recursion.
3763 bool body_can_be_empty = (body->min_match() == 0); 3763 bool body_can_be_empty = (body->min_match() == 0);
3764 int body_start_reg = RegExpCompiler::kNoRegister; 3764 int body_start_reg = RegExpCompiler::kNoRegister;
3765 Interval capture_registers = body->CaptureRegisters(); 3765 Interval capture_registers = body->CaptureRegisters();
3766 bool needs_capture_clearing = !capture_registers.is_empty(); 3766 bool needs_capture_clearing = !capture_registers.is_empty();
3767 if (body_can_be_empty) { 3767 if (body_can_be_empty) {
3768 body_start_reg = compiler->AllocateRegister(); 3768 body_start_reg = compiler->AllocateRegister();
3769 } else if (FLAG_regexp_optimization && !needs_capture_clearing) { 3769 } else if (FLAG_regexp_optimization &&
3770 !body->ContainsExpandedQuantifier() &&
3771 !needs_capture_clearing) {
3770 // Only unroll if there are no captures and the body can't be 3772 // Only unroll if there are no captures and the body can't be
3771 // empty. 3773 // empty.
3772 if (min > 0 && min <= kMaxUnrolledMinMatches) { 3774 if (min > 0 && min <= kMaxUnrolledMinMatches) {
3773 int new_max = (max == kInfinity) ? max : max - min; 3775 int new_max = (max == kInfinity) ? max : max - min;
3774 // Recurse once to get the loop or optional matches after the fixed ones. 3776 // Recurse once to get the loop or optional matches after the fixed ones.
3775 RegExpNode* answer = ToNode( 3777 RegExpNode* answer = ToNode(
3776 0, new_max, is_greedy, body, compiler, on_success, true); 3778 0, new_max, is_greedy, body, compiler, on_success, true);
3777 // Unroll the forced matches from 0 to min. This can cause chains of 3779 // Unroll the forced matches from 0 to min. This can cause chains of
3778 // TextNodes (which the parser does not generate). These should be 3780 // TextNodes (which the parser does not generate). These should be
3779 // combined if it turns out they hinder good code generation. 3781 // combined if it turns out they hinder good code generation.
3780 for (int i = 0; i < min; i++) { 3782 for (int i = 0; i < min; i++) {
3781 answer = body->ToNode(compiler, answer); 3783 answer = body->ToNode(compiler, answer);
3782 } 3784 }
3785 if (min > 1) body->set_contains_expanded_quantifier(true);
3783 return answer; 3786 return answer;
3784 } 3787 }
3785 if (max <= kMaxUnrolledMaxMatches) { 3788 if (max <= kMaxUnrolledMaxMatches) {
3786 ASSERT(min == 0); 3789 ASSERT(min == 0);
3787 // Unroll the optional matches up to max. 3790 // Unroll the optional matches up to max.
3788 RegExpNode* answer = on_success; 3791 RegExpNode* answer = on_success;
3789 for (int i = 0; i < max; i++) { 3792 for (int i = 0; i < max; i++) {
3790 ChoiceNode* alternation = new ChoiceNode(2); 3793 ChoiceNode* alternation = new ChoiceNode(2);
3791 if (is_greedy) { 3794 if (is_greedy) {
3792 alternation->AddAlternative(GuardedAlternative(body->ToNode(compiler, 3795 alternation->AddAlternative(GuardedAlternative(body->ToNode(compiler,
3793 answer))); 3796 answer)));
3794 alternation->AddAlternative(GuardedAlternative(on_success)); 3797 alternation->AddAlternative(GuardedAlternative(on_success));
3795 } else { 3798 } else {
3796 alternation->AddAlternative(GuardedAlternative(on_success)); 3799 alternation->AddAlternative(GuardedAlternative(on_success));
3797 alternation->AddAlternative(GuardedAlternative(body->ToNode(compiler, 3800 alternation->AddAlternative(GuardedAlternative(body->ToNode(compiler,
3798 answer))); 3801 answer)));
3799 } 3802 }
3800 answer = alternation; 3803 answer = alternation;
3801 if (not_at_start) alternation->set_not_at_start(); 3804 if (not_at_start) alternation->set_not_at_start();
3802 } 3805 }
3806 if (max > 1) body->set_contains_expanded_quantifier(true);
3803 return answer; 3807 return answer;
3804 } 3808 }
3805 } 3809 }
3806 bool has_min = min > 0; 3810 bool has_min = min > 0;
3807 bool has_max = max < RegExpTree::kInfinity; 3811 bool has_max = max < RegExpTree::kInfinity;
3808 bool needs_counter = has_min || has_max; 3812 bool needs_counter = has_min || has_max;
3809 int reg_ctr = needs_counter 3813 int reg_ctr = needs_counter
3810 ? compiler->AllocateRegister() 3814 ? compiler->AllocateRegister()
3811 : RegExpCompiler::kNoRegister; 3815 : RegExpCompiler::kNoRegister;
3812 LoopChoiceNode* center = new LoopChoiceNode(body->min_match() == 0); 3816 LoopChoiceNode* center = new LoopChoiceNode(body->min_match() == 0);
(...skipping 1566 matching lines...) Expand 10 before | Expand all | Expand 10 after
5379 } 5383 }
5380 5384
5381 return compiler.Assemble(&macro_assembler, 5385 return compiler.Assemble(&macro_assembler,
5382 node, 5386 node,
5383 data->capture_count, 5387 data->capture_count,
5384 pattern); 5388 pattern);
5385 } 5389 }
5386 5390
5387 5391
5388 }} // namespace v8::internal 5392 }} // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ast.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698