-
Notifications
You must be signed in to change notification settings - Fork 807
Expand file tree
/
Copy pathtest-binary-reader.cc
More file actions
146 lines (124 loc) Β· 5.21 KB
/
test-binary-reader.cc
File metadata and controls
146 lines (124 loc) Β· 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
* Copyright 2018 WebAssembly Community Group participants
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "gtest/gtest.h"
#include "wabt/binary-reader-nop.h"
#include "wabt/binary-reader.h"
#include "wabt/leb128.h"
#include "wabt/opcode.h"
using namespace wabt;
namespace {
struct BinaryReaderError : BinaryReaderNop {
bool OnError(const Error& error) override {
first_error = error;
return true; // Error handled.
}
Error first_error;
};
} // End of anonymous namespace
TEST(BinaryReader, DisabledOpcodes) {
// Use the default features.
ReadBinaryOptions options;
// Loop through all opcodes.
for (uint32_t i = 0; i < static_cast<uint32_t>(Opcode::Invalid); ++i) {
Opcode opcode(static_cast<Opcode::Enum>(i));
if (opcode.IsEnabled(options.features)) {
continue;
}
// Use a shorter name to make the clang-formatted table below look nicer.
std::vector<uint8_t> b = opcode.GetBytes();
assert(b.size() <= 3);
b.resize(3);
uint8_t data[] = {
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, // magic + version
0x01, 0x04, 0x01, 0x60, 0x00, 0x00, // type section: 1 type, (func)
0x03, 0x02, 0x01, 0x00, // func section: 1 func, type 0
0x0a, 0x07, 0x01, 0x05, 0x00, // code section: 1 func, 0 locals
b[0], b[1], b[2], // The instruction, padded with zeroes
0x0b, // end
};
const size_t size = sizeof(data);
BinaryReaderError reader;
Result result = ReadBinary(data, size, &reader, options);
EXPECT_EQ(Result::Error, result);
// This relies on the binary reader checking whether the opcode is allowed
// before reading any further data needed by the instruction.
const std::string& message = reader.first_error.message;
EXPECT_EQ(0u, message.find("unexpected opcode"))
<< "Got error message: " << message;
}
}
TEST(BinaryReader, InvalidFunctionBodySize) {
// A wasm module where the function body size extends past the end of the
// code section. Without the bounds check this would allow the binary reader
// to read past the section boundary.
// TODO: Move this test upstream into the spec repo.
uint8_t data[] = {
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, // magic + version
0x01, 0x04, 0x01, 0x60, 0x00, 0x00, // type section: 1 type, (func)
0x03, 0x02, 0x01, 0x00, // func section: 1 func, type 0
// Code section: 1 func, but body_size claims 0xFF bytes
0x0a, 0x04, // code section, size=4
0x01, // 1 function body
0xff, 0x01, // body size = 255 (LEB128), far exceeds section
0x00, // would be local decl count, but body_size is invalid
};
BinaryReaderError reader;
ReadBinaryOptions options;
Result result = ReadBinary(data, sizeof(data), &reader, options);
EXPECT_EQ(Result::Error, result);
EXPECT_NE(std::string::npos,
reader.first_error.message.find("invalid function body size"))
<< "Got: " << reader.first_error.message;
}
TEST(BinaryReader, OversizedSectionSize) {
// A module whose section size extends past the end of the data. The
// subtraction-based overflow check must reject this before computing
// read_end_ = offset + section_size, which would overflow on platforms
// where size_t is 32-bit.
// TODO: Move this test upstream into the spec repo.
uint8_t data[] = {
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, // magic + version
0x01, // section code: Type
0x80, 0x80, 0x80, 0x80, 0x08, // section size: 0x80000000 (LEB128)
};
BinaryReaderError reader;
ReadBinaryOptions options;
Result result = ReadBinary(data, sizeof(data), &reader, options);
EXPECT_EQ(Result::Error, result);
EXPECT_NE(std::string::npos,
reader.first_error.message.find("invalid section size"))
<< "Got: " << reader.first_error.message;
}
TEST(BinaryReader, OversizedSubsectionSize) {
// A module with a name section containing a subsection whose size extends
// past the section boundary.
// TODO: Move this test upstream into the spec repo.
uint8_t data[] = {
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, // magic + version
// Custom section (name section)
0x00, // section code: custom
0x09, // section size: 9 bytes
0x04, // name length
'n', 'a', 'm', 'e',
0x01, // subsection type: function names
0x80, 0x80, 0x04, // subsection size: 65536 (LEB128), exceeds section
};
BinaryReaderError reader;
ReadBinaryOptions options;
Result result = ReadBinary(data, sizeof(data), &reader, options);
// Custom section errors are not fatal by default, but ensure no crash.
(void)result;
}