Index: llvm/trunk/include/llvm/Object/Wasm.h =================================================================== --- llvm/trunk/include/llvm/Object/Wasm.h +++ llvm/trunk/include/llvm/Object/Wasm.h @@ -203,7 +203,9 @@ bool isDefinedFunctionIndex(uint32_t Index) const; bool isValidGlobalIndex(uint32_t Index) const; bool isDefinedGlobalIndex(uint32_t Index) const; - bool isValidFunctionSymbolIndex(uint32_t Index) const; + bool isValidFunctionSymbol(uint32_t Index) const; + bool isValidGlobalSymbol(uint32_t Index) const; + bool isValidDataSymbol(uint32_t Index) const; wasm::WasmFunction &getDefinedFunction(uint32_t Index); wasm::WasmGlobal &getDefinedGlobal(uint32_t Index); Index: llvm/trunk/lib/Object/WasmObjectFile.cpp =================================================================== --- llvm/trunk/lib/Object/WasmObjectFile.cpp +++ llvm/trunk/lib/Object/WasmObjectFile.cpp @@ -339,7 +339,7 @@ wasm::WasmInitFunc Init; Init.Priority = readVaruint32(Ptr); Init.Symbol = readVaruint32(Ptr); - if (!isValidFunctionSymbolIndex(Init.Symbol)) + if (!isValidFunctionSymbol(Init.Symbol)) return make_error("Invalid function symbol: " + Twine(Init.Symbol), object_error::parse_failed); @@ -554,9 +554,10 @@ return make_error("Invalid section code", object_error::parse_failed); uint32_t RelocCount = readVaruint32(Ptr); + uint32_t LastOffset = 0; + uint32_t 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); @@ -564,12 +565,26 @@ case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + if (!isValidFunctionSymbol(Reloc.Index)) + return make_error("Bad relocation function 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; case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: + if (!isValidGlobalSymbol(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 (!isValidDataSymbol(Reloc.Index)) + return make_error("Bad relocation data index", + object_error::parse_failed); Reloc.Addend = readVarint32(Ptr); break; default: @@ -577,6 +592,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 < LastOffset || Reloc.Offset + Size > EndOffset) + return make_error("Bad relocation offset", + object_error::parse_failed); + LastOffset = Reloc.Offset; + Section->Relocations.push_back(Reloc); } if (Ptr != End) @@ -787,10 +815,18 @@ return Index >= NumImportedGlobals && isValidGlobalIndex(Index); } -bool WasmObjectFile::isValidFunctionSymbolIndex(uint32_t Index) const { +bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const { return Index < Symbols.size() && Symbols[Index].isTypeFunction(); } +bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const { + return Index < Symbols.size() && Symbols[Index].isTypeGlobal(); +} + +bool WasmObjectFile::isValidDataSymbol(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: llvm/trunk/test/ObjectYAML/wasm/code_section.yaml =================================================================== --- llvm/trunk/test/ObjectYAML/wasm/code_section.yaml +++ llvm/trunk/test/ObjectYAML/wasm/code_section.yaml @@ -37,6 +37,19 @@ - Type: I32 Count: 1 Body: 108180808000210020000F0B + - Type: CUSTOM + Name: linking + SymbolTable: + - Index: 0 + Kind: FUNCTION + Name: func1 + Flags: [ ] + Function: 0 + - Index: 1 + Kind: FUNCTION + Name: func2 + Flags: [ ] + Function: 1 ... # CHECK: --- !WASM # CHECK: FileHeader: Index: llvm/trunk/test/ObjectYAML/wasm/data_section.yaml =================================================================== --- llvm/trunk/test/ObjectYAML/wasm/data_section.yaml +++ llvm/trunk/test/ObjectYAML/wasm/data_section.yaml @@ -22,6 +22,16 @@ Index: 0 Offset: 0x00000006 Addend: -6 + - Type: CUSTOM + Name: linking + SymbolTable: + - Index: 0 + Kind: DATA + Name: dataSymbol + Flags: [ ] + Segment: 0 + Offset: 0 + Size: 4 ... # CHECK: --- !WASM # CHECK: FileHeader: @@ -44,4 +54,4 @@ # CHECK-NEXT: Opcode: I32_CONST # CHECK-NEXT: Value: 4 # CHECK-NEXT: Content: '10001000' -# CHECK-NEXT: ... +# CHECK-NEXT: - Type: CUSTOM