Fix crashes due to mishandling custom sections.
[WebKit-https.git] / Source / JavaScriptCore / wasm / WasmSections.h
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 #pragma once
27
28 #if ENABLE(WEBASSEMBLY)
29
30 #if COMPILER(GCC) && ASSERT_DISABLED
31 #pragma GCC diagnostic push
32 #pragma GCC diagnostic ignored "-Wreturn-type"
33 #endif // COMPILER(GCC) && ASSERT_DISABLED
34
35 namespace JSC { namespace Wasm {
36
37 #define FOR_EACH_KNOWN_WASM_SECTION(macro) \
38     macro(Type,     1, "Function signature declarations") \
39     macro(Import,   2, "Import declarations") \
40     macro(Function, 3, "Function declarations") \
41     macro(Table,    4, "Indirect function table and other tables") \
42     macro(Memory,   5, "Memory attributes") \
43     macro(Global,   6, "Global declarations") \
44     macro(Export,   7, "Exports") \
45     macro(Start,    8, "Start function declaration") \
46     macro(Element,  9, "Elements section") \
47     macro(Code,    10, "Function bodies (code)") \
48     macro(Data,    11, "Data segments")
49
50 enum class Section : uint8_t {
51     // It's important that Begin is less than every other section number and that Custom is greater.
52     // This only works because section numbers are currently monotonically increasing.
53     // Also, Begin is not a real section but is used as a marker for validating the ordering
54     // of sections.
55     Begin = 0,
56 #define DEFINE_WASM_SECTION_ENUM(NAME, ID, DESCRIPTION) NAME = ID,
57     FOR_EACH_KNOWN_WASM_SECTION(DEFINE_WASM_SECTION_ENUM)
58 #undef DEFINE_WASM_SECTION_ENUM
59     Custom
60 };
61 static_assert(static_cast<uint8_t>(Section::Begin) < static_cast<uint8_t>(Section::Type), "Begin should come before the first known section.");
62
63 template<typename Int>
64 inline bool isKnownSection(Int section)
65 {
66     switch (section) {
67 #define VALIDATE_SECTION(NAME, ID, DESCRIPTION) case static_cast<Int>(Section::NAME): return true;
68         FOR_EACH_KNOWN_WASM_SECTION(VALIDATE_SECTION)
69 #undef VALIDATE_SECTION
70     default:
71         return false;
72     }
73 }
74
75 inline bool decodeSection(uint8_t sectionByte, Section& section)
76 {
77     section = Section::Custom;
78     if (!sectionByte)
79         return true;
80
81     if (!isKnownSection(sectionByte))
82         return false;
83
84     section = static_cast<Section>(sectionByte);
85     return true;
86 }
87
88 inline bool validateOrder(Section previousKnown, Section next)
89 {
90     ASSERT(isKnownSection(previousKnown) || previousKnown == Section::Begin);
91     return static_cast<uint8_t>(previousKnown) < static_cast<uint8_t>(next);
92 }
93
94 inline const char* makeString(Section section)
95 {
96     switch (section) {
97     case Section::Begin:
98         return "Begin";
99     case Section::Custom:
100         return "Custom";
101 #define STRINGIFY_SECTION_NAME(NAME, ID, DESCRIPTION) case Section::NAME: return #NAME;
102         FOR_EACH_KNOWN_WASM_SECTION(STRINGIFY_SECTION_NAME)
103 #undef STRINGIFY_SECTION_NAME
104     }
105     ASSERT_NOT_REACHED();
106 }
107
108 } } // namespace JSC::Wasm
109
110 #if COMPILER(GCC) && ASSERT_DISABLED
111 #pragma GCC diagnostic pop
112 #endif // COMPILER(GCC) && ASSERT_DISABLED
113
114 #endif // ENABLE(WEBASSEMBLY)