Skip to content

Commit 2f731a7

Browse files
authored
Add declaration limit checks to parser (#2736)
1 parent 41db004 commit 2f731a7

2 files changed

Lines changed: 35 additions & 1 deletion

File tree

include/wabt/wast-parser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ class WastParser {
170170
// synchronized.
171171
Result Synchronize(SynchronizeFunc);
172172

173+
// Check the maximum allowed declarations.
174+
Result CheckIndexRange(Location& loc, size_t size, const char* decl);
175+
173176
Result ParseVarText(Token& token, std::string* out_text);
174177
Result ParseBindVarOpt(std::string* name);
175178
Result ParseVar(Var* out_var);

src/wast-parser.cc

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,16 @@ Result WastParser::Synchronize(SynchronizeFunc func) {
706706
return Result::Error;
707707
}
708708

709+
Result WastParser::CheckIndexRange(Location& loc,
710+
size_t size,
711+
const char* decl) {
712+
if (size >= kInvalidIndex) {
713+
Error(loc, "too many %s declarations", decl);
714+
return Result::Error;
715+
}
716+
return Result::Ok;
717+
}
718+
709719
void WastParser::ErrorUnlessOpcodeEnabled(const Token& token) {
710720
Opcode opcode = token.opcode();
711721
if (!opcode.IsEnabled(options_->features)) {
@@ -1506,6 +1516,7 @@ Result WastParser::ParseDataModuleField(Module* module) {
15061516
EXPECT(Lpar);
15071517
Location loc = GetLocation();
15081518
EXPECT(Data);
1519+
CHECK_RESULT(CheckIndexRange(loc, module->data_segments.size(), "data"));
15091520
std::string name;
15101521
CHECK_RESULT(ParseBindVarOpt(&name));
15111522
auto field = std::make_unique<DataSegmentModuleField>(loc, name);
@@ -1543,6 +1554,7 @@ Result WastParser::ParseElemModuleField(Module* module) {
15431554
EXPECT(Lpar);
15441555
Location loc = GetLocation();
15451556
EXPECT(Elem);
1557+
CHECK_RESULT(CheckIndexRange(loc, module->elem_segments.size(), "elem"));
15461558

15471559
// With MVP text format the name here was intended to refer to the table
15481560
// that the elem segment was part of, but we never did anything with this name
@@ -1620,7 +1632,7 @@ Result WastParser::ParseTagModuleField(Module* module) {
16201632
EXPECT(Lpar);
16211633
EXPECT(Tag);
16221634
Location loc = GetLocation();
1623-
1635+
CHECK_RESULT(CheckIndexRange(loc, module->tags.size(), "tag"));
16241636
std::string name;
16251637
CHECK_RESULT(ParseBindVarOpt(&name));
16261638

@@ -1629,6 +1641,7 @@ Result WastParser::ParseTagModuleField(Module* module) {
16291641

16301642
if (PeekMatchLpar(TokenType::Import)) {
16311643
CheckImportOrdering(module);
1644+
CHECK_RESULT(CheckIndexRange(loc, module->imports.size(), "import"));
16321645
auto import = std::make_unique<TagImport>(name);
16331646
Tag& tag = import->tag;
16341647
CHECK_RESULT(ParseInlineImport(import.get()));
@@ -1655,7 +1668,9 @@ Result WastParser::ParseExportModuleField(Module* module) {
16551668
WABT_TRACE(ParseExportModuleField);
16561669
EXPECT(Lpar);
16571670
auto field = std::make_unique<ExportModuleField>(GetLocation());
1671+
Location loc = GetLocation();
16581672
EXPECT(Export);
1673+
CHECK_RESULT(CheckIndexRange(loc, module->exports.size(), "export"));
16591674
CHECK_RESULT(ParseQuotedText(&field->export_.name));
16601675
CHECK_RESULT(ParseExportDesc(&field->export_));
16611676
EXPECT(Rpar);
@@ -1668,6 +1683,7 @@ Result WastParser::ParseFuncModuleField(Module* module) {
16681683
EXPECT(Lpar);
16691684
Location loc = GetLocation();
16701685
EXPECT(Func);
1686+
CHECK_RESULT(CheckIndexRange(loc, module->funcs.size(), "func"));
16711687
std::string name;
16721688
CHECK_RESULT(ParseBindVarOpt(&name));
16731689

@@ -1676,6 +1692,7 @@ Result WastParser::ParseFuncModuleField(Module* module) {
16761692

16771693
if (PeekMatchLpar(TokenType::Import)) {
16781694
CheckImportOrdering(module);
1695+
CHECK_RESULT(CheckIndexRange(loc, module->imports.size(), "import"));
16791696
auto import = std::make_unique<FuncImport>(name);
16801697
Func& func = import->func;
16811698
CHECK_RESULT(ParseInlineImport(import.get()));
@@ -1725,6 +1742,7 @@ Result WastParser::ParseTypeModuleField(Module* module) {
17251742
CHECK_RESULT(ParseBindVarOpt(&name));
17261743
EXPECT(Lpar);
17271744
Location loc = GetLocation();
1745+
CHECK_RESULT(CheckIndexRange(loc, module->types.size(), "type"));
17281746

17291747
if (Match(TokenType::Func)) {
17301748
auto func_type = std::make_unique<FuncType>(name);
@@ -1802,6 +1820,7 @@ Result WastParser::ParseGlobalModuleField(Module* module) {
18021820
EXPECT(Lpar);
18031821
Location loc = GetLocation();
18041822
EXPECT(Global);
1823+
CHECK_RESULT(CheckIndexRange(loc, module->globals.size(), "global"));
18051824
std::string name;
18061825
CHECK_RESULT(ParseBindVarOpt(&name));
18071826

@@ -1810,6 +1829,7 @@ Result WastParser::ParseGlobalModuleField(Module* module) {
18101829

18111830
if (PeekMatchLpar(TokenType::Import)) {
18121831
CheckImportOrdering(module);
1832+
CHECK_RESULT(CheckIndexRange(loc, module->imports.size(), "import"));
18131833
auto import = std::make_unique<GlobalImport>(name);
18141834
CHECK_RESULT(ParseInlineImport(import.get()));
18151835
CHECK_RESULT(ParseGlobalType(&import->global));
@@ -1835,6 +1855,7 @@ Result WastParser::ParseImportModuleField(Module* module) {
18351855
Location loc = GetLocation();
18361856
CheckImportOrdering(module);
18371857
EXPECT(Import);
1858+
CHECK_RESULT(CheckIndexRange(loc, module->imports.size(), "import"));
18381859
std::string module_name;
18391860
std::string field_name;
18401861
CHECK_RESULT(ParseQuotedText(&module_name));
@@ -1846,6 +1867,7 @@ Result WastParser::ParseImportModuleField(Module* module) {
18461867

18471868
switch (Peek()) {
18481869
case TokenType::Func: {
1870+
CHECK_RESULT(CheckIndexRange(loc, module->funcs.size(), "func"));
18491871
DropToken();
18501872
CHECK_RESULT(ParseBindVarOpt(&name));
18511873
auto import = std::make_unique<FuncImport>(name);
@@ -1859,6 +1881,7 @@ Result WastParser::ParseImportModuleField(Module* module) {
18591881
}
18601882

18611883
case TokenType::Table: {
1884+
CHECK_RESULT(CheckIndexRange(loc, module->tables.size(), "table"));
18621885
DropToken();
18631886
CHECK_RESULT(ParseBindVarOpt(&name));
18641887
auto import = std::make_unique<TableImport>(name);
@@ -1873,6 +1896,7 @@ Result WastParser::ParseImportModuleField(Module* module) {
18731896
}
18741897

18751898
case TokenType::Memory: {
1899+
CHECK_RESULT(CheckIndexRange(loc, module->memories.size(), "memory"));
18761900
DropToken();
18771901
CHECK_RESULT(ParseBindVarOpt(&name));
18781902
auto import = std::make_unique<MemoryImport>(name);
@@ -1886,6 +1910,7 @@ Result WastParser::ParseImportModuleField(Module* module) {
18861910
}
18871911

18881912
case TokenType::Global: {
1913+
CHECK_RESULT(CheckIndexRange(loc, module->globals.size(), "global"));
18891914
DropToken();
18901915
CHECK_RESULT(ParseBindVarOpt(&name));
18911916
auto import = std::make_unique<GlobalImport>(name);
@@ -1896,6 +1921,7 @@ Result WastParser::ParseImportModuleField(Module* module) {
18961921
}
18971922

18981923
case TokenType::Tag: {
1924+
CHECK_RESULT(CheckIndexRange(loc, module->tags.size(), "tag"));
18991925
DropToken();
19001926
CHECK_RESULT(ParseBindVarOpt(&name));
19011927
auto import = std::make_unique<TagImport>(name);
@@ -1923,6 +1949,7 @@ Result WastParser::ParseMemoryModuleField(Module* module) {
19231949
EXPECT(Lpar);
19241950
Location loc = GetLocation();
19251951
EXPECT(Memory);
1952+
CHECK_RESULT(CheckIndexRange(loc, module->memories.size(), "memory"));
19261953
std::string name;
19271954
CHECK_RESULT(ParseBindVarOpt(&name));
19281955

@@ -1931,6 +1958,7 @@ Result WastParser::ParseMemoryModuleField(Module* module) {
19311958

19321959
if (PeekMatchLpar(TokenType::Import)) {
19331960
CheckImportOrdering(module);
1961+
CHECK_RESULT(CheckIndexRange(loc, module->imports.size(), "import"));
19341962
auto import = std::make_unique<MemoryImport>(name);
19351963
import->memory.page_size = WABT_DEFAULT_PAGE_SIZE;
19361964
CHECK_RESULT(ParseInlineImport(import.get()));
@@ -2004,6 +2032,7 @@ Result WastParser::ParseTableModuleField(Module* module) {
20042032
EXPECT(Lpar);
20052033
Location loc = GetLocation();
20062034
EXPECT(Table);
2035+
CHECK_RESULT(CheckIndexRange(loc, module->tables.size(), "table"));
20072036
std::string name;
20082037
CHECK_RESULT(ParseBindVarOpt(&name));
20092038

@@ -2012,6 +2041,7 @@ Result WastParser::ParseTableModuleField(Module* module) {
20122041

20132042
if (PeekMatchLpar(TokenType::Import)) {
20142043
CheckImportOrdering(module);
2044+
CHECK_RESULT(CheckIndexRange(loc, module->imports.size(), "import"));
20152045
auto import = std::make_unique<TableImport>(name);
20162046
CHECK_RESULT(ParseInlineImport(import.get()));
20172047
CHECK_RESULT(ParseLimitsIndex(&import->table.elem_limits));
@@ -2032,6 +2062,7 @@ Result WastParser::ParseTableModuleField(Module* module) {
20322062

20332063
EXPECT(Lpar);
20342064
EXPECT(Elem);
2065+
CHECK_RESULT(CheckIndexRange(loc, module->elem_segments.size(), "elem"));
20352066

20362067
auto elem_segment_field = std::make_unique<ElemSegmentModuleField>(loc);
20372068
ElemSegment& elem_segment = elem_segment_field->elem_segment;

0 commit comments

Comments
 (0)