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

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 8 #ifndef DART_PRECOMPILED
9 9
10 #include "lib/invocation_mirror.h" 10 #include "lib/invocation_mirror.h"
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 ~BoolScope() { 118 ~BoolScope() {
119 *_addr = _saved_value; 119 *_addr = _saved_value;
120 } 120 }
121 121
122 private: 122 private:
123 bool* _addr; 123 bool* _addr;
124 bool _saved_value; 124 bool _saved_value;
125 }; 125 };
126 126
127 127
128 class RecursionChecker : public ValueObject {
129 public:
130 explicit RecursionChecker(Parser* p) : parser_(p) {
131 parser_->recursion_counter_++;
132 // No need to check the stack unless the parser is in an unusually deep
133 // recurive state. Thus, we omit the more expensive stack checks in
134 // the common case.
135 const int kMaxUncheckedDepth = 100; // Somewhat arbitrary.
136 if (parser_->recursion_counter_ > kMaxUncheckedDepth) {
137 parser_->CheckStack();
138 }
139 }
140 ~RecursionChecker() {
141 parser_->recursion_counter_--;
142 }
143
144 private:
145 Parser* parser_;
146 };
147
148
128 static RawTypeArguments* NewTypeArguments( 149 static RawTypeArguments* NewTypeArguments(
129 const GrowableArray<AbstractType*>& objs) { 150 const GrowableArray<AbstractType*>& objs) {
130 const TypeArguments& a = 151 const TypeArguments& a =
131 TypeArguments::Handle(TypeArguments::New(objs.length())); 152 TypeArguments::Handle(TypeArguments::New(objs.length()));
132 for (int i = 0; i < objs.length(); i++) { 153 for (int i = 0; i < objs.length(); i++) {
133 a.SetTypeAt(i, *objs.At(i)); 154 a.SetTypeAt(i, *objs.At(i));
134 } 155 }
135 // Cannot canonicalize TypeArgument yet as its types may not have been 156 // Cannot canonicalize TypeArgument yet as its types may not have been
136 // finalized yet. 157 // finalized yet.
137 return a.raw(); 158 return a.raw();
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 allow_function_literals_(true), 361 allow_function_literals_(true),
341 parsed_function_(NULL), 362 parsed_function_(NULL),
342 innermost_function_(Function::Handle(zone())), 363 innermost_function_(Function::Handle(zone())),
343 literal_token_(LiteralToken::Handle(zone())), 364 literal_token_(LiteralToken::Handle(zone())),
344 current_class_(Class::Handle(zone())), 365 current_class_(Class::Handle(zone())),
345 library_(Library::Handle(zone(), library.raw())), 366 library_(Library::Handle(zone(), library.raw())),
346 try_stack_(NULL), 367 try_stack_(NULL),
347 last_used_try_index_(0), 368 last_used_try_index_(0),
348 unregister_pending_function_(false), 369 unregister_pending_function_(false),
349 async_temp_scope_(NULL), 370 async_temp_scope_(NULL),
350 trace_indent_(0) { 371 trace_indent_(0),
372 recursion_counter_(0) {
351 ASSERT(tokens_iterator_.IsValid()); 373 ASSERT(tokens_iterator_.IsValid());
352 ASSERT(!library.IsNull()); 374 ASSERT(!library.IsNull());
353 } 375 }
354 376
355 377
356 // For parsing a function. 378 // For parsing a function.
357 Parser::Parser(const Script& script, 379 Parser::Parser(const Script& script,
358 ParsedFunction* parsed_function, 380 ParsedFunction* parsed_function,
359 intptr_t token_position) 381 intptr_t token_position)
360 : isolate_(Thread::Current()->isolate()), 382 : isolate_(Thread::Current()->isolate()),
(...skipping 13 matching lines...) Expand all
374 literal_token_(LiteralToken::Handle(zone())), 396 literal_token_(LiteralToken::Handle(zone())),
375 current_class_(Class::Handle(zone(), 397 current_class_(Class::Handle(zone(),
376 parsed_function->function().Owner())), 398 parsed_function->function().Owner())),
377 library_(Library::Handle(zone(), Class::Handle( 399 library_(Library::Handle(zone(), Class::Handle(
378 zone(), 400 zone(),
379 parsed_function->function().origin()).library())), 401 parsed_function->function().origin()).library())),
380 try_stack_(NULL), 402 try_stack_(NULL),
381 last_used_try_index_(0), 403 last_used_try_index_(0),
382 unregister_pending_function_(false), 404 unregister_pending_function_(false),
383 async_temp_scope_(NULL), 405 async_temp_scope_(NULL),
384 trace_indent_(0) { 406 trace_indent_(0),
407 recursion_counter_(0) {
385 ASSERT(tokens_iterator_.IsValid()); 408 ASSERT(tokens_iterator_.IsValid());
386 ASSERT(!current_function().IsNull()); 409 ASSERT(!current_function().IsNull());
387 EnsureExpressionTemp(); 410 EnsureExpressionTemp();
388 } 411 }
389 412
390 413
391 Parser::~Parser() { 414 Parser::~Parser() {
392 if (unregister_pending_function_) { 415 if (unregister_pending_function_) {
393 const GrowableObjectArray& pending_functions = 416 const GrowableObjectArray& pending_functions =
394 GrowableObjectArray::Handle(T->pending_functions()); 417 GrowableObjectArray::Handle(T->pending_functions());
(...skipping 5710 matching lines...) Expand 10 before | Expand all | Expand 10 after
6105 for (intptr_t i = 0; i < top_level.functions().length(); i++) { 6128 for (intptr_t i = 0; i < top_level.functions().length(); i++) {
6106 toplevel_class.AddFunction(*top_level.functions()[i]); 6129 toplevel_class.AddFunction(*top_level.functions()[i]);
6107 } 6130 }
6108 if (toplevel_class.is_finalized()) { 6131 if (toplevel_class.is_finalized()) {
6109 toplevel_class.ResetFinalization(); 6132 toplevel_class.ResetFinalization();
6110 } 6133 }
6111 pending_classes.Add(toplevel_class, Heap::kOld); 6134 pending_classes.Add(toplevel_class, Heap::kOld);
6112 } 6135 }
6113 6136
6114 6137
6138 void Parser::CheckStack() {
6139 volatile uword c_stack_pos = Isolate::GetCurrentStackPointer();
6140 volatile uword c_stack_base = OSThread::Current()->stack_base();
6141 volatile uword c_stack_limit =
6142 c_stack_base - OSThread::GetSpecifiedStackSize();
6143 if ((c_stack_base > 0) && (c_stack_pos < c_stack_limit)) {
rmacnak 2016/01/22 00:45:28 Add comment that c_stack_base > 0 handles the case
hausner 2016/01/22 18:38:14 Done.
6144 ReportError("stack overflow while parsing");
6145 }
6146 }
6147
6148
6115 void Parser::ChainNewBlock(LocalScope* outer_scope) { 6149 void Parser::ChainNewBlock(LocalScope* outer_scope) {
6116 Block* block = new(Z) Block( 6150 Block* block = new(Z) Block(
6117 current_block_, 6151 current_block_,
6118 outer_scope, 6152 outer_scope,
6119 new(Z) SequenceNode(TokenPos(), outer_scope)); 6153 new(Z) SequenceNode(TokenPos(), outer_scope));
6120 current_block_ = block; 6154 current_block_ = block;
6121 } 6155 }
6122 6156
6123 6157
6124 void Parser::OpenBlock() { 6158 void Parser::OpenBlock() {
(...skipping 1926 matching lines...) Expand 10 before | Expand all | Expand 10 after
8051 } 8085 }
8052 } 8086 }
8053 return false; 8087 return false;
8054 } 8088 }
8055 8089
8056 8090
8057 void Parser::ParseStatementSequence() { 8091 void Parser::ParseStatementSequence() {
8058 TRACE_PARSER("ParseStatementSequence"); 8092 TRACE_PARSER("ParseStatementSequence");
8059 const bool dead_code_allowed = true; 8093 const bool dead_code_allowed = true;
8060 bool abrupt_completing_seen = false; 8094 bool abrupt_completing_seen = false;
8095 RecursionChecker rc(this);
8061 while (CurrentToken() != Token::kRBRACE) { 8096 while (CurrentToken() != Token::kRBRACE) {
8062 const intptr_t statement_pos = TokenPos(); 8097 const intptr_t statement_pos = TokenPos();
8063 AstNode* statement = ParseStatement(); 8098 AstNode* statement = ParseStatement();
8064 // Do not add statements with no effect (e.g., LoadLocalNode). 8099 // Do not add statements with no effect (e.g., LoadLocalNode).
8065 if ((statement != NULL) && statement->IsLoadLocalNode()) { 8100 if ((statement != NULL) && statement->IsLoadLocalNode()) {
8066 // Skip load local. 8101 // Skip load local.
8067 continue; 8102 continue;
8068 } 8103 }
8069 if (statement != NULL) { 8104 if (statement != NULL) {
8070 if (!dead_code_allowed && abrupt_completing_seen) { 8105 if (!dead_code_allowed && abrupt_completing_seen) {
(...skipping 19 matching lines...) Expand all
8090 OpenBlock(); 8125 OpenBlock();
8091 } 8126 }
8092 if (label != NULL) { 8127 if (label != NULL) {
8093 current_block_->scope->AddLabel(label); 8128 current_block_->scope->AddLabel(label);
8094 } 8129 }
8095 if (CurrentToken() == Token::kLBRACE) { 8130 if (CurrentToken() == Token::kLBRACE) {
8096 ConsumeToken(); 8131 ConsumeToken();
8097 ParseStatementSequence(); 8132 ParseStatementSequence();
8098 ExpectToken(Token::kRBRACE); 8133 ExpectToken(Token::kRBRACE);
8099 } else { 8134 } else {
8135 RecursionChecker rc(this);
8100 AstNode* statement = ParseStatement(); 8136 AstNode* statement = ParseStatement();
8101 if (statement != NULL) { 8137 if (statement != NULL) {
8102 current_block_->statements->Add(statement); 8138 current_block_->statements->Add(statement);
8103 } 8139 }
8104 } 8140 }
8105 SequenceNode* sequence = CloseBlock(); 8141 SequenceNode* sequence = CloseBlock();
8106 return sequence; 8142 return sequence;
8107 } 8143 }
8108 8144
8109 8145
(...skipping 2718 matching lines...) Expand 10 before | Expand all | Expand 10 after
10828 } 10864 }
10829 10865
10830 10866
10831 AstNode* Parser::ParseExpr(bool require_compiletime_const, 10867 AstNode* Parser::ParseExpr(bool require_compiletime_const,
10832 bool consume_cascades) { 10868 bool consume_cascades) {
10833 TRACE_PARSER("ParseExpr"); 10869 TRACE_PARSER("ParseExpr");
10834 String* expr_ident = 10870 String* expr_ident =
10835 Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL; 10871 Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
10836 const intptr_t expr_pos = TokenPos(); 10872 const intptr_t expr_pos = TokenPos();
10837 10873
10874 RecursionChecker rc(this);
10875
10838 if (CurrentToken() == Token::kTHROW) { 10876 if (CurrentToken() == Token::kTHROW) {
10839 if (require_compiletime_const) { 10877 if (require_compiletime_const) {
10840 ReportError("'throw expr' is not a valid compile-time constant"); 10878 ReportError("'throw expr' is not a valid compile-time constant");
10841 } 10879 }
10842 ConsumeToken(); 10880 ConsumeToken();
10843 if (CurrentToken() == Token::kSEMICOLON) { 10881 if (CurrentToken() == Token::kSEMICOLON) {
10844 ReportError("expression expected after throw"); 10882 ReportError("expression expected after throw");
10845 } 10883 }
10846 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades); 10884 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades);
10847 return new(Z) ThrowNode(expr_pos, expr, NULL); 10885 return new(Z) ThrowNode(expr_pos, expr, NULL);
(...skipping 3569 matching lines...) Expand 10 before | Expand all | Expand 10 after
14417 const ArgumentListNode& function_args, 14455 const ArgumentListNode& function_args,
14418 const LocalVariable* temp_for_last_arg, 14456 const LocalVariable* temp_for_last_arg,
14419 bool is_super_invocation) { 14457 bool is_super_invocation) {
14420 UNREACHABLE(); 14458 UNREACHABLE();
14421 return NULL; 14459 return NULL;
14422 } 14460 }
14423 14461
14424 } // namespace dart 14462 } // namespace dart
14425 14463
14426 #endif // DART_PRECOMPILED 14464 #endif // DART_PRECOMPILED
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