Index: include/llvm/Object/Wasm.h =================================================================== --- include/llvm/Object/Wasm.h +++ include/llvm/Object/Wasm.h @@ -204,6 +204,8 @@ bool isValidGlobalIndex(uint32_t Index) const; bool isDefinedGlobalIndex(uint32_t Index) const; bool isValidFunctionSymbolIndex(uint32_t Index) const; + bool isValidGlobalSymbolIndex(uint32_t Index) const; + bool isValidDataSymbolIndex(uint32_t Index) const; wasm::WasmFunction &getDefinedFunction(uint32_t Index); wasm::WasmGlobal &getDefinedGlobal(uint32_t Index); @@ -238,6 +240,7 @@ Error parseLinkingSectionComdat(const uint8_t *&Ptr, const uint8_t *End); Error parseRelocSection(StringRef Name, const uint8_t *Ptr, const uint8_t *End); + Error validateRelocSection(); wasm::WasmObjectHeader Header; std::vector Sections; Index: lib/Object/WasmObjectFile.cpp =================================================================== --- lib/Object/WasmObjectFile.cpp +++ lib/Object/WasmObjectFile.cpp @@ -232,6 +232,9 @@ Sections.push_back(Sec); } + + if ((Err = validateRelocSection())) + return; } Error WasmObjectFile::parseSection(WasmSection &Sec) { @@ -565,9 +568,9 @@ return make_error("Invalid section code", object_error::parse_failed); uint32_t RelocCount = readVaruint32(Ptr); + uint64_t StartOffset = 0, EndOffset = Section->Content.size(); while (RelocCount--) { - wasm::WasmRelocation Reloc; - memset(&Reloc, 0, sizeof(Reloc)); + wasm::WasmRelocation Reloc = {}; Reloc.Type = readVaruint32(Ptr); Reloc.Offset = readVaruint32(Ptr); Reloc.Index = readVaruint32(Ptr); @@ -588,6 +591,19 @@ Twine(Reloc.Type), object_error::parse_failed); } + + // Relocations must fit inside the section, and must appear in order. They + // also shouldn't overlap a function/element boundary, but we don't bother + // to check that. + uint64_t Size = 5; + if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 || + Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32) + Size = 4; + if (Reloc.Offset < StartOffset || Reloc.Offset + Size > EndOffset) + return make_error("Bad relocation offset", + object_error::parse_failed); + StartOffset = Reloc.Offset; + Section->Relocations.push_back(Reloc); } if (Ptr != End) @@ -596,6 +612,40 @@ return Error::success(); } +Error WasmObjectFile::validateRelocSection() { + for (const WasmSection &Section : Sections) { + for (const wasm::WasmRelocation &Reloc : Section.Relocations) { + switch (Reloc.Type) { + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + if (!isValidFunctionSymbolIndex(Reloc.Index)) + return make_error("Bad relocation function index", + object_error::parse_failed); + break; + case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: + if (!isValidGlobalSymbolIndex(Reloc.Index)) + return make_error("Bad relocation global index", + object_error::parse_failed); + break; + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: + if (!isValidDataSymbolIndex(Reloc.Index)) + return make_error("Bad relocation data index", + object_error::parse_failed); + break; + case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: + if (Reloc.Index >= Signatures.size()) + return make_error("Bad relocation type index", + object_error::parse_failed); + break; + } + } + } + return Error::success(); +} + Error WasmObjectFile::parseCustomSection(WasmSection &Sec, const uint8_t *Ptr, const uint8_t *End) { Sec.Name = readString(Ptr); @@ -797,6 +847,14 @@ return Index < Symbols.size() && Symbols[Index].isTypeFunction(); } +bool WasmObjectFile::isValidGlobalSymbolIndex(uint32_t Index) const { + return Index < Symbols.size() && Symbols[Index].isTypeGlobal(); +} + +bool WasmObjectFile::isValidDataSymbolIndex(uint32_t Index) const { + return Index < Symbols.size() && Symbols[Index].isTypeData(); +} + wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) { assert(isDefinedFunctionIndex(Index)); return Functions[Index - NumImportedFunctions]; Index: test/ObjectYAML/wasm/code_section.yaml =================================================================== --- test/ObjectYAML/wasm/code_section.yaml +++ test/ObjectYAML/wasm/code_section.yaml @@ -37,6 +37,20 @@ - Type: I32 Count: 1 Body: 108180808000210020000F0B + - Type: CUSTOM + Name: linking + DataSize: 0 + SymbolTable: + - Index: 0 + Kind: FUNCTION + Name: func1 + Flags: [ ] + Function: 0 + - Index: 1 + Kind: FUNCTION + Name: func2 + Flags: [ ] + Function: 1 ... # CHECK: --- !WASM # CHECK: FileHeader: Index: test/ObjectYAML/wasm/data_section.yaml =================================================================== --- test/ObjectYAML/wasm/data_section.yaml +++ test/ObjectYAML/wasm/data_section.yaml @@ -22,6 +22,17 @@ Index: 0 Offset: 0x00000006 Addend: -6 + - Type: CUSTOM + Name: linking + DataSize: 4 + SymbolTable: + - Index: 0 + Kind: DATA + Name: dataSymbol + Flags: [ ] + Segment: 0 + Offset: 0 + Size: 4 ... # CHECK: --- !WASM # CHECK: FileHeader: @@ -44,4 +55,4 @@ # CHECK-NEXT: Opcode: I32_CONST # CHECK-NEXT: Value: 4 # CHECK-NEXT: Content: '10001000' -# CHECK-NEXT: ... +# CHECK-NEXT: - Type: CUSTOM