55c212e39bea6a1be1f49f23e8631e76df2e2c5f
[WebKit-https.git] / Source / JavaScriptCore / wasm / WasmModuleParser.cpp
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WasmModuleParser.h"
28
29 #if ENABLE(WEBASSEMBLY)
30
31 #include "WasmFormat.h"
32 #include "WasmOps.h"
33 #include "WasmSections.h"
34
35 #include <sys/mman.h>
36
37 namespace JSC { namespace Wasm {
38
39 static const bool verbose = false;
40
41 bool ModuleParser::parse()
42 {
43     const size_t minSize = 8;
44     if (length() < minSize) {
45         m_errorMessage = "Module is " + String::number(length()) + " bytes, expected at least " + String::number(minSize) + " bytes";
46         return false;
47     }
48     if (!consumeCharacter(0) || !consumeString("asm")) {
49         m_errorMessage = "Modules doesn't start with '\\0asm'";
50         return false;
51     }
52
53     // Skip the version number for now since we don't do anything with it.
54     uint32_t versionNumber;
55     if (!parseUInt32(versionNumber)) {
56         // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
57         m_errorMessage = "couldn't parse version number";
58         return false;
59     }
60
61     if (versionNumber != magicNumber) {
62         // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
63         m_errorMessage = "unexpected version number";
64         return false;
65     }
66
67
68     if (verbose)
69         dataLogLn("Passed processing header.");
70
71     Sections::Section previousSection = Sections::Unknown;
72     while (m_offset < length()) {
73         if (verbose)
74             dataLogLn("Starting to parse next section at offset: ", m_offset);
75
76         uint8_t sectionByte;
77         if (!parseUInt7(sectionByte)) {
78             // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
79             m_errorMessage = "couldn't get section byte";
80             return false;
81         }
82
83         if (verbose)
84             dataLogLn("Section byte: ", sectionByte);
85
86         Sections::Section section = Sections::Unknown;
87         if (sectionByte) {
88             if (sectionByte < Sections::Unknown)
89                 section = static_cast<Sections::Section>(sectionByte);
90         }
91
92         if (!Sections::validateOrder(previousSection, section)) {
93             // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
94             m_errorMessage = "invalid section order";
95             return false;
96         }
97
98         uint32_t sectionLength;
99         if (!parseVarUInt32(sectionLength)) {
100             // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
101             m_errorMessage = "couldn't get section length";
102             return false;
103         }
104
105         if (sectionLength > length() - m_offset) {
106             // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
107             m_errorMessage = "section content would overflow Module's size";
108             return false;
109         }
110
111         auto end = m_offset + sectionLength;
112
113         switch (section) {
114
115         case Sections::Memory: {
116             if (verbose)
117                 dataLogLn("Parsing Memory.");
118             if (!parseMemory()) {
119                 // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
120                 m_errorMessage = "couldn't parse memory";
121                 return false;
122             }
123             break;
124         }
125
126         case Sections::FunctionTypes: {
127             if (verbose)
128                 dataLogLn("Parsing types.");
129             if (!parseFunctionTypes()) {
130                 // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
131                 m_errorMessage = "couldn't parse types";
132                 return false;
133             }
134             break;
135         }
136
137         case Sections::Signatures: {
138             if (verbose)
139                 dataLogLn("Parsing function signatures.");
140             if (!parseFunctionSignatures()) {
141                 // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
142                 m_errorMessage = "couldn't parse function signatures";
143                 return false;
144             }
145             break;
146         }
147
148         case Sections::Definitions: {
149             if (verbose)
150                 dataLogLn("Parsing function definitions.");
151             if (!parseFunctionDefinitions()) {
152                 // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
153                 m_errorMessage = "couldn't parse function definitions";
154                 return false;
155             }
156             break;
157         }
158
159         case Sections::Unknown:
160         // FIXME: Delete this when we support all the sections.
161         default: {
162             if (verbose)
163                 dataLogLn("Unknown section, skipping.");
164             // Ignore section's name LEB and bytes: they're already included in sectionLength.
165             m_offset += sectionLength;
166             break;
167         }
168         }
169
170         if (verbose)
171             dataLogLn("Finished parsing section.");
172
173         if (end != m_offset) {
174             // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
175             m_errorMessage = "parsing ended before the end of the section";
176             return false;
177         }
178
179         previousSection = section;
180     }
181
182     // TODO
183     m_failed = false;
184     return true;
185 }
186
187 bool ModuleParser::parseMemory()
188 {
189     uint8_t flags;
190     if (!parseVarUInt1(flags))
191         return false;
192
193     uint32_t size;
194     if (!parseVarUInt32(size))
195         return false;
196     if (size > maxPageCount)
197         return false;
198
199     uint32_t capacity = maxPageCount;
200     if (flags) {
201         if (!parseVarUInt32(capacity))
202             return false;
203         if (size > capacity || capacity > maxPageCount)
204             return false;
205     }
206
207     capacity *= pageSize;
208     size *= pageSize;
209
210     Vector<unsigned> pinnedSizes = { 0 };
211     m_memory = std::make_unique<Memory>(size, capacity, pinnedSizes);
212     return m_memory->memory();
213 }
214
215 bool ModuleParser::parseFunctionTypes()
216 {
217     uint32_t count;
218     if (!parseVarUInt32(count))
219         return false;
220
221     if (verbose)
222         dataLogLn("count: ", count);
223
224     m_signatures.resize(count);
225
226     for (uint32_t i = 0; i < count; ++i) {
227         uint8_t type;
228         if (!parseUInt7(type))
229             return false;
230         if (type != 0x40) // Function type constant.
231             return false;
232
233         if (verbose)
234             dataLogLn("Got function type.");
235
236         uint32_t argumentCount;
237         if (!parseVarUInt32(argumentCount))
238             return false;
239
240         if (verbose)
241             dataLogLn("argumentCount: ", argumentCount);
242
243         Vector<Type> argumentTypes;
244         argumentTypes.resize(argumentCount);
245
246         for (unsigned i = 0; i < argumentCount; ++i) {
247             if (!parseUInt7(type) || !isValueType(static_cast<Type>(type)))
248                 return false;
249             argumentTypes[i] = static_cast<Type>(type);
250         }
251
252         if (!parseVarUInt1(type))
253             return false;
254         Type returnType;
255
256         if (verbose)
257             dataLogLn(type);
258
259         if (type) {
260             Type value;
261             if (!parseValueType(value))
262                 return false;
263             returnType = static_cast<Type>(value);
264         } else
265             returnType = Type::Void;
266
267         m_signatures[i] = { returnType, WTFMove(argumentTypes) };
268     }
269     return true;
270 }
271
272 bool ModuleParser::parseFunctionSignatures()
273 {
274     uint32_t count;
275     if (!parseVarUInt32(count))
276         return false;
277
278     m_functions.resize(count);
279
280     for (uint32_t i = 0; i < count; ++i) {
281         uint32_t typeNumber;
282         if (!parseVarUInt32(typeNumber))
283             return false;
284
285         if (typeNumber >= m_signatures.size())
286             return false;
287
288         m_functions[i].signature = &m_signatures[typeNumber];
289     }
290
291     return true;
292 }
293
294 bool ModuleParser::parseFunctionDefinitions()
295 {
296     uint32_t count;
297     if (!parseVarUInt32(count))
298         return false;
299
300     if (count != m_functions.size())
301         return false;
302
303     for (uint32_t i = 0; i < count; ++i) {
304         uint32_t functionSize;
305         if (!parseVarUInt32(functionSize))
306             return false;
307
308         FunctionInformation& info = m_functions[i];
309         info.start = m_offset;
310         info.end = m_offset + functionSize;
311         m_offset = info.end;
312     }
313
314     return true;
315 }
316
317 } } // namespace JSC::Wasm
318
319 #endif // ENABLE(WEBASSEMBLY)