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

Side by Side Diff: runtime/vm/parser.cc

Issue 1620493002: Parser recursion check (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 11 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
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/deep_nesting1_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 #include "vm/flags.h" 6 #include "vm/flags.h"
7 7
8 #ifndef DART_PRECOMPILED_RUNTIME 8 #ifndef DART_PRECOMPILED_RUNTIME
9 9
10 #include "lib/invocation_mirror.h" 10 #include "lib/invocation_mirror.h"
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 ~BoolScope() { 120 ~BoolScope() {
121 *_addr = _saved_value; 121 *_addr = _saved_value;
122 } 122 }
123 123
124 private: 124 private:
125 bool* _addr; 125 bool* _addr;
126 bool _saved_value; 126 bool _saved_value;
127 }; 127 };
128 128
129 129
130 class RecursionChecker : public ValueObject {
131 public:
132 explicit RecursionChecker(Parser* p) : parser_(p) {
133 parser_->recursion_counter_++;
134 // No need to check the stack unless the parser is in an unusually deep
135 // recurive state. Thus, we omit the more expensive stack checks in
136 // the common case.
137 const int kMaxUncheckedDepth = 100; // Somewhat arbitrary.
138 if (parser_->recursion_counter_ > kMaxUncheckedDepth) {
139 parser_->CheckStack();
140 }
141 }
142 ~RecursionChecker() {
143 parser_->recursion_counter_--;
144 }
145
146 private:
147 Parser* parser_;
148 };
149
150
130 static RawTypeArguments* NewTypeArguments( 151 static RawTypeArguments* NewTypeArguments(
131 const GrowableArray<AbstractType*>& objs) { 152 const GrowableArray<AbstractType*>& objs) {
132 const TypeArguments& a = 153 const TypeArguments& a =
133 TypeArguments::Handle(TypeArguments::New(objs.length())); 154 TypeArguments::Handle(TypeArguments::New(objs.length()));
134 for (int i = 0; i < objs.length(); i++) { 155 for (int i = 0; i < objs.length(); i++) {
135 a.SetTypeAt(i, *objs.At(i)); 156 a.SetTypeAt(i, *objs.At(i));
136 } 157 }
137 // Cannot canonicalize TypeArgument yet as its types may not have been 158 // Cannot canonicalize TypeArgument yet as its types may not have been
138 // finalized yet. 159 // finalized yet.
139 return a.raw(); 160 return a.raw();
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 allow_function_literals_(true), 363 allow_function_literals_(true),
343 parsed_function_(NULL), 364 parsed_function_(NULL),
344 innermost_function_(Function::Handle(zone())), 365 innermost_function_(Function::Handle(zone())),
345 literal_token_(LiteralToken::Handle(zone())), 366 literal_token_(LiteralToken::Handle(zone())),
346 current_class_(Class::Handle(zone())), 367 current_class_(Class::Handle(zone())),
347 library_(Library::Handle(zone(), library.raw())), 368 library_(Library::Handle(zone(), library.raw())),
348 try_stack_(NULL), 369 try_stack_(NULL),
349 last_used_try_index_(0), 370 last_used_try_index_(0),
350 unregister_pending_function_(false), 371 unregister_pending_function_(false),
351 async_temp_scope_(NULL), 372 async_temp_scope_(NULL),
352 trace_indent_(0) { 373 trace_indent_(0),
374 recursion_counter_(0) {
353 ASSERT(tokens_iterator_.IsValid()); 375 ASSERT(tokens_iterator_.IsValid());
354 ASSERT(!library.IsNull()); 376 ASSERT(!library.IsNull());
355 } 377 }
356 378
357 379
358 // For parsing a function. 380 // For parsing a function.
359 Parser::Parser(const Script& script, 381 Parser::Parser(const Script& script,
360 ParsedFunction* parsed_function, 382 ParsedFunction* parsed_function,
361 intptr_t token_position) 383 intptr_t token_position)
362 : isolate_(Thread::Current()->isolate()), 384 : isolate_(Thread::Current()->isolate()),
(...skipping 13 matching lines...) Expand all
376 literal_token_(LiteralToken::Handle(zone())), 398 literal_token_(LiteralToken::Handle(zone())),
377 current_class_(Class::Handle(zone(), 399 current_class_(Class::Handle(zone(),
378 parsed_function->function().Owner())), 400 parsed_function->function().Owner())),
379 library_(Library::Handle(zone(), Class::Handle( 401 library_(Library::Handle(zone(), Class::Handle(
380 zone(), 402 zone(),
381 parsed_function->function().origin()).library())), 403 parsed_function->function().origin()).library())),
382 try_stack_(NULL), 404 try_stack_(NULL),
383 last_used_try_index_(0), 405 last_used_try_index_(0),
384 unregister_pending_function_(false), 406 unregister_pending_function_(false),
385 async_temp_scope_(NULL), 407 async_temp_scope_(NULL),
386 trace_indent_(0) { 408 trace_indent_(0),
409 recursion_counter_(0) {
387 ASSERT(tokens_iterator_.IsValid()); 410 ASSERT(tokens_iterator_.IsValid());
388 ASSERT(!current_function().IsNull()); 411 ASSERT(!current_function().IsNull());
389 EnsureExpressionTemp(); 412 EnsureExpressionTemp();
390 } 413 }
391 414
392 415
393 Parser::~Parser() { 416 Parser::~Parser() {
394 if (unregister_pending_function_) { 417 if (unregister_pending_function_) {
395 const GrowableObjectArray& pending_functions = 418 const GrowableObjectArray& pending_functions =
396 GrowableObjectArray::Handle(T->pending_functions()); 419 GrowableObjectArray::Handle(T->pending_functions());
(...skipping 5643 matching lines...) Expand 10 before | Expand all | Expand 10 after
6040 for (intptr_t i = 0; i < top_level.functions().length(); i++) { 6063 for (intptr_t i = 0; i < top_level.functions().length(); i++) {
6041 toplevel_class.AddFunction(*top_level.functions()[i]); 6064 toplevel_class.AddFunction(*top_level.functions()[i]);
6042 } 6065 }
6043 if (toplevel_class.is_finalized()) { 6066 if (toplevel_class.is_finalized()) {
6044 toplevel_class.ResetFinalization(); 6067 toplevel_class.ResetFinalization();
6045 } 6068 }
6046 pending_classes.Add(toplevel_class, Heap::kOld); 6069 pending_classes.Add(toplevel_class, Heap::kOld);
6047 } 6070 }
6048 6071
6049 6072
6073 void Parser::CheckStack() {
6074 volatile uword c_stack_pos = Isolate::GetCurrentStackPointer();
6075 volatile uword c_stack_base = OSThread::Current()->stack_base();
6076 volatile uword c_stack_limit =
6077 c_stack_base - OSThread::GetSpecifiedStackSize();
6078 // Note: during early initialization the stack_base() can return 0.
6079 if ((c_stack_base > 0) && (c_stack_pos < c_stack_limit)) {
6080 ReportError("stack overflow while parsing");
6081 }
6082 }
6083
6084
6050 void Parser::ChainNewBlock(LocalScope* outer_scope) { 6085 void Parser::ChainNewBlock(LocalScope* outer_scope) {
6051 Block* block = new(Z) Block( 6086 Block* block = new(Z) Block(
6052 current_block_, 6087 current_block_,
6053 outer_scope, 6088 outer_scope,
6054 new(Z) SequenceNode(TokenPos(), outer_scope)); 6089 new(Z) SequenceNode(TokenPos(), outer_scope));
6055 current_block_ = block; 6090 current_block_ = block;
6056 } 6091 }
6057 6092
6058 6093
6059 void Parser::OpenBlock() { 6094 void Parser::OpenBlock() {
(...skipping 1883 matching lines...) Expand 10 before | Expand all | Expand 10 after
7943 } 7978 }
7944 } 7979 }
7945 return false; 7980 return false;
7946 } 7981 }
7947 7982
7948 7983
7949 void Parser::ParseStatementSequence() { 7984 void Parser::ParseStatementSequence() {
7950 TRACE_PARSER("ParseStatementSequence"); 7985 TRACE_PARSER("ParseStatementSequence");
7951 const bool dead_code_allowed = true; 7986 const bool dead_code_allowed = true;
7952 bool abrupt_completing_seen = false; 7987 bool abrupt_completing_seen = false;
7988 RecursionChecker rc(this);
7953 while (CurrentToken() != Token::kRBRACE) { 7989 while (CurrentToken() != Token::kRBRACE) {
7954 const intptr_t statement_pos = TokenPos(); 7990 const intptr_t statement_pos = TokenPos();
7955 AstNode* statement = ParseStatement(); 7991 AstNode* statement = ParseStatement();
7956 // Do not add statements with no effect (e.g., LoadLocalNode). 7992 // Do not add statements with no effect (e.g., LoadLocalNode).
7957 if ((statement != NULL) && statement->IsLoadLocalNode()) { 7993 if ((statement != NULL) && statement->IsLoadLocalNode()) {
7958 // Skip load local. 7994 // Skip load local.
7959 continue; 7995 continue;
7960 } 7996 }
7961 if (statement != NULL) { 7997 if (statement != NULL) {
7962 if (!dead_code_allowed && abrupt_completing_seen) { 7998 if (!dead_code_allowed && abrupt_completing_seen) {
(...skipping 19 matching lines...) Expand all
7982 OpenBlock(); 8018 OpenBlock();
7983 } 8019 }
7984 if (label != NULL) { 8020 if (label != NULL) {
7985 current_block_->scope->AddLabel(label); 8021 current_block_->scope->AddLabel(label);
7986 } 8022 }
7987 if (CurrentToken() == Token::kLBRACE) { 8023 if (CurrentToken() == Token::kLBRACE) {
7988 ConsumeToken(); 8024 ConsumeToken();
7989 ParseStatementSequence(); 8025 ParseStatementSequence();
7990 ExpectToken(Token::kRBRACE); 8026 ExpectToken(Token::kRBRACE);
7991 } else { 8027 } else {
8028 RecursionChecker rc(this);
7992 AstNode* statement = ParseStatement(); 8029 AstNode* statement = ParseStatement();
7993 if (statement != NULL) { 8030 if (statement != NULL) {
7994 current_block_->statements->Add(statement); 8031 current_block_->statements->Add(statement);
7995 } 8032 }
7996 } 8033 }
7997 SequenceNode* sequence = CloseBlock(); 8034 SequenceNode* sequence = CloseBlock();
7998 return sequence; 8035 return sequence;
7999 } 8036 }
8000 8037
8001 8038
(...skipping 2731 matching lines...) Expand 10 before | Expand all | Expand 10 after
10733 } 10770 }
10734 10771
10735 10772
10736 AstNode* Parser::ParseExpr(bool require_compiletime_const, 10773 AstNode* Parser::ParseExpr(bool require_compiletime_const,
10737 bool consume_cascades) { 10774 bool consume_cascades) {
10738 TRACE_PARSER("ParseExpr"); 10775 TRACE_PARSER("ParseExpr");
10739 String* expr_ident = 10776 String* expr_ident =
10740 Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL; 10777 Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
10741 const intptr_t expr_pos = TokenPos(); 10778 const intptr_t expr_pos = TokenPos();
10742 10779
10780 RecursionChecker rc(this);
10781
10743 if (CurrentToken() == Token::kTHROW) { 10782 if (CurrentToken() == Token::kTHROW) {
10744 if (require_compiletime_const) { 10783 if (require_compiletime_const) {
10745 ReportError("'throw expr' is not a valid compile-time constant"); 10784 ReportError("'throw expr' is not a valid compile-time constant");
10746 } 10785 }
10747 ConsumeToken(); 10786 ConsumeToken();
10748 if (CurrentToken() == Token::kSEMICOLON) { 10787 if (CurrentToken() == Token::kSEMICOLON) {
10749 ReportError("expression expected after throw"); 10788 ReportError("expression expected after throw");
10750 } 10789 }
10751 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades); 10790 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades);
10752 return new(Z) ThrowNode(expr_pos, expr, NULL); 10791 return new(Z) ThrowNode(expr_pos, expr, NULL);
(...skipping 3561 matching lines...) Expand 10 before | Expand all | Expand 10 after
14314 const ArgumentListNode& function_args, 14353 const ArgumentListNode& function_args,
14315 const LocalVariable* temp_for_last_arg, 14354 const LocalVariable* temp_for_last_arg,
14316 bool is_super_invocation) { 14355 bool is_super_invocation) {
14317 UNREACHABLE(); 14356 UNREACHABLE();
14318 return NULL; 14357 return NULL;
14319 } 14358 }
14320 14359
14321 } // namespace dart 14360 } // namespace dart
14322 14361
14323 #endif // DART_PRECOMPILED_RUNTIME 14362 #endif // DART_PRECOMPILED_RUNTIME
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/deep_nesting1_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698