public:
// We define orders for all core wasm sections and known custom sections.
enum : int {
+ // Sentinel, must be zero
+ WASM_SEC_ORDER_NONE = 0,
+
// Core sections
- // The order of standard sections is precisely given by the spec.
- WASM_SEC_ORDER_TYPE = 1,
- WASM_SEC_ORDER_IMPORT = 2,
- WASM_SEC_ORDER_FUNCTION = 3,
- WASM_SEC_ORDER_TABLE = 4,
- WASM_SEC_ORDER_MEMORY = 5,
- WASM_SEC_ORDER_GLOBAL = 6,
- WASM_SEC_ORDER_EVENT = 7,
- WASM_SEC_ORDER_EXPORT = 8,
- WASM_SEC_ORDER_START = 9,
- WASM_SEC_ORDER_ELEM = 10,
- WASM_SEC_ORDER_DATACOUNT = 11,
- WASM_SEC_ORDER_CODE = 12,
- WASM_SEC_ORDER_DATA = 13,
+ WASM_SEC_ORDER_TYPE,
+ WASM_SEC_ORDER_IMPORT,
+ WASM_SEC_ORDER_FUNCTION,
+ WASM_SEC_ORDER_TABLE,
+ WASM_SEC_ORDER_MEMORY,
+ WASM_SEC_ORDER_GLOBAL,
+ WASM_SEC_ORDER_EVENT,
+ WASM_SEC_ORDER_EXPORT,
+ WASM_SEC_ORDER_START,
+ WASM_SEC_ORDER_ELEM,
+ WASM_SEC_ORDER_DATACOUNT,
+ WASM_SEC_ORDER_CODE,
+ WASM_SEC_ORDER_DATA,
// Custom sections
// "dylink" should be the very first section in the module
- WASM_SEC_ORDER_DYLINK = 0,
+ WASM_SEC_ORDER_DYLINK,
// "linking" section requires DATA section in order to validate data symbols
- WASM_SEC_ORDER_LINKING = 100,
+ WASM_SEC_ORDER_LINKING,
// Must come after "linking" section in order to validate reloc indexes.
- WASM_SEC_ORDER_RELOC = 101,
+ WASM_SEC_ORDER_RELOC,
// "name" section must appear after DATA. Comes after "linking" to allow
// symbol table to set default function name.
- WASM_SEC_ORDER_NAME = 102,
+ WASM_SEC_ORDER_NAME,
// "producers" section must appear after "name" section.
- WASM_SEC_ORDER_PRODUCERS = 103
+ WASM_SEC_ORDER_PRODUCERS,
+
+ // Must be last
+ WASM_NUM_SEC_ORDERS
+
};
+ // Sections that may or may not be present, but cannot be predecessors
+ static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS];
+
bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName = "");
private:
- int LastOrder = -1; // Lastly seen known section's order
+ bool Seen[WASM_NUM_SEC_ORDERS] = {}; // Sections that have been seen already
// Returns -1 for unknown sections.
int getSectionOrder(unsigned ID, StringRef CustomSectionName = "");
.StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
.Case("name", WASM_SEC_ORDER_NAME)
.Case("producers", WASM_SEC_ORDER_PRODUCERS)
- .Default(-1);
+ .Default(WASM_SEC_ORDER_NONE);
case wasm::WASM_SEC_TYPE:
return WASM_SEC_ORDER_TYPE;
case wasm::WASM_SEC_IMPORT:
}
}
+// Represents the edges in a directed graph where any node B reachable from node
+// A is not allowed to appear before A in the section ordering, but may appear
+// afterward.
+int WasmSectionOrderChecker::DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
+ {}, // WASM_SEC_ORDER_NONE
+ {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT}, // WASM_SEC_ORDER_TYPE,
+ {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION}, // WASM_SEC_ORDER_IMPORT,
+ {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE}, // WASM_SEC_ORDER_FUNCTION,
+ {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY}, // WASM_SEC_ORDER_TABLE,
+ {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_GLOBAL}, // WASM_SEC_ORDER_MEMORY,
+ {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EVENT}, // WASM_SEC_ORDER_GLOBAL,
+ {WASM_SEC_ORDER_EVENT, WASM_SEC_ORDER_EXPORT}, // WASM_SEC_ORDER_EVENT,
+ {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START}, // WASM_SEC_ORDER_EXPORT,
+ {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM}, // WASM_SEC_ORDER_START,
+ {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT}, // WASM_SEC_ORDER_ELEM,
+ {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE}, // WASM_SEC_ORDER_DATACOUNT,
+ {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA}, // WASM_SEC_ORDER_CODE,
+ {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING}, // WASM_SEC_ORDER_DATA,
+
+ // Custom Sections
+ {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE}, // WASM_SEC_ORDER_DYLINK,
+ {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME}, // WASM_SEC_ORDER_LINKING,
+ {}, // WASM_SEC_ORDER_RELOC (can be repeated),
+ {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS}, // WASM_SEC_ORDER_NAME,
+ {WASM_SEC_ORDER_PRODUCERS}, // WASM_SEC_ORDER_PRODUCERS,
+};
+
bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
StringRef CustomSectionName) {
int Order = getSectionOrder(ID, CustomSectionName);
- if (Order == -1) // Skip unknown sections
+ if (Order == WASM_SEC_ORDER_NONE)
return true;
- // There can be multiple "reloc." sections. Otherwise there shouldn't be any
- // duplicate section orders.
- bool IsValid = (LastOrder == Order && Order == WASM_SEC_ORDER_RELOC) ||
- LastOrder < Order;
- LastOrder = Order;
- return IsValid;
+
+ // Disallowed predecessors we need to check for
+ SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
+
+ // Keep track of completed checks to avoid repeating work
+ bool Checked[WASM_NUM_SEC_ORDERS] = {};
+
+ int Curr = Order;
+ while (true) {
+ // Add new disallowed predecessors to work list
+ for (size_t I = 0;; ++I) {
+ int Next = DisallowedPredecessors[Curr][I];
+ if (Next == WASM_SEC_ORDER_NONE)
+ break;
+ if (Checked[Next])
+ continue;
+ WorkList.push_back(Next);
+ Checked[Next] = true;
+ }
+
+ if (WorkList.empty())
+ break;
+
+ // Consider next disallowed predecessor
+ Curr = WorkList.pop_back_val();
+ if (Seen[Curr])
+ return false;
+ }
+
+ // Have not seen any disallowed predecessors
+ Seen[Order] = true;
+ return true;
}