Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions include/wabt/wast-parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,11 +315,35 @@ class WastParser {
bool HasError() const;
bool CheckRefType(Type::Enum type);
void VarToType(const Var& var, Type* type);
Result CheckNestingDepth();

// Unlike the binary reader, which tracks nesting with an explicit label
// stack, this parser is recursive descent: every level of nested
// instructions costs several stack frames. The limit is therefore much
// lower than BinaryReaderIR's kMaxNestingDepth, and is chosen to stay
// within the smallest default stack we build against (1MB on MSVC).
Comment thread
Nishuuzz marked this conversation as resolved.
Outdated
static constexpr int kMaxNestingDepth = 1000;

// Increments the parser's nesting depth for as long as it is in scope.
class NestingGuard {
Comment thread
Nishuuzz marked this conversation as resolved.
Outdated
public:
explicit NestingGuard(WastParser* parser) : parser_(parser) {
Comment thread
Nishuuzz marked this conversation as resolved.
Outdated
++parser_->nesting_depth_;
}
~NestingGuard() { --parser_->nesting_depth_; }
NestingGuard(const NestingGuard&) = delete;
NestingGuard& operator=(const NestingGuard&) = delete;

private:
WastParser* parser_;
};

WastLexer* lexer_;
Index last_module_index_ = kInvalidIndex;
Errors* errors_;
WastParseOptions* options_;
int nesting_depth_ = 0;
bool nesting_limit_hit_ = false;

// Reference types can have names or indicies. For example (ref $foo)
// represents a type which name is $foo, and (ref 5) represents
Expand Down
25 changes: 25 additions & 0 deletions src/wast-parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2280,15 +2280,35 @@ Result WastParser::ParseResultList(TypeVector* result_types,
return ParseUnboundValueTypeList(TokenType::Result, result_types, type_vars);
}

Result WastParser::CheckNestingDepth() {
if (nesting_depth_ > kMaxNestingDepth) {
// Exceeding the limit is not recoverable: the error is reported once and
// the flag stops the callers below from resynchronizing and walking back
// into the same too-deep input, which would report it once per level.
if (!nesting_limit_hit_) {
nesting_limit_hit_ = true;
Error(GetLocation(), "instruction nesting depth exceeds max of %d",
kMaxNestingDepth);
}
return Result::Error;
}
return Result::Ok;
}

Result WastParser::ParseInstrList(ExprList* exprs) {
WABT_TRACE(ParseInstrList);
NestingGuard nesting_guard(this);
CHECK_RESULT(CheckNestingDepth());
ExprList new_exprs;
while (true) {
auto pair = PeekPair();
if (IsInstr(pair)) {
if (Succeeded(ParseInstr(&new_exprs))) {
exprs->splice(exprs->end(), new_exprs);
} else {
if (nesting_limit_hit_) {
return Result::Error;
}
CHECK_RESULT(Synchronize(IsInstr));
}
} else if (IsLparAnn(pair)) {
Expand Down Expand Up @@ -3432,11 +3452,16 @@ Result WastParser::ParseBlock(Block* block) {

Result WastParser::ParseExprList(ExprList* exprs) {
WABT_TRACE(ParseExprList);
NestingGuard nesting_guard(this);
CHECK_RESULT(CheckNestingDepth());
ExprList new_exprs;
while (PeekMatchExpr()) {
if (Succeeded(ParseExpr(&new_exprs))) {
exprs->splice(exprs->end(), new_exprs);
} else {
if (nesting_limit_hit_) {
return Result::Error;
}
CHECK_RESULT(Synchronize(IsExpr));
}
}
Expand Down
112 changes: 112 additions & 0 deletions test/parse/expr/bad-nesting-depth.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
;;; TOOL: wat2wasm
;;; ERROR: 1
;; Deeply nested blocks used to overflow the stack while parsing;
;; the parser now reports the nesting limit instead. See #2377.
(module (func
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
(block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block
nop
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))))))))))))))))))))
))
(;; STDERR ;;;
out/test/parse/expr/bad-nesting-depth.txt:56:1: error: instruction nesting depth exceeds max of 1000
nop
^^^
;;; STDERR ;;)
Loading