[llvm] [Object][WebAssembly] Make Wasm read failures recoverable (PR #215102)

James Henderson via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 10 01:43:17 PDT 2026


================
@@ -86,103 +85,121 @@ ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
 #define VARUINT7_MAX (1 << 7)
 #define VARUINT1_MAX (1)
 
-static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
+static Error parseFailed(const Twine &Msg) {
+  return make_error<GenericBinaryError>(Msg, object_error::parse_failed);
+}
+
+static Error readUint8(WasmObjectFile::ReadContext &Ctx, uint8_t &Result) {
   if (Ctx.Ptr == Ctx.End)
-    report_fatal_error("EOF while reading uint8");
-  return *Ctx.Ptr++;
+    return parseFailed("EOF while reading uint8");
+  Result = *Ctx.Ptr++;
+  return Error::success();
 }
 
-static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
+static Error readUint32(WasmObjectFile::ReadContext &Ctx, uint32_t &Result) {
   if (Ctx.Ptr + 4 > Ctx.End)
-    report_fatal_error("EOF while reading uint32");
-  uint32_t Result = support::endian::read32le(Ctx.Ptr);
+    return parseFailed("EOF while reading uint32");
+  Result = support::endian::read32le(Ctx.Ptr);
   Ctx.Ptr += 4;
-  return Result;
+  return Error::success();
 }
 
-static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
+static Error readFloat32(WasmObjectFile::ReadContext &Ctx, int32_t &Result) {
   if (Ctx.Ptr + 4 > Ctx.End)
-    report_fatal_error("EOF while reading float64");
-  int32_t Result = 0;
+    return parseFailed("EOF while reading float64");
+  Result = 0;
   memcpy(&Result, Ctx.Ptr, sizeof(Result));
   Ctx.Ptr += sizeof(Result);
-  return Result;
+  return Error::success();
 }
 
-static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
+static Error readFloat64(WasmObjectFile::ReadContext &Ctx, int64_t &Result) {
   if (Ctx.Ptr + 8 > Ctx.End)
-    report_fatal_error("EOF while reading float64");
-  int64_t Result = 0;
+    return parseFailed("EOF while reading float64");
+  Result = 0;
   memcpy(&Result, Ctx.Ptr, sizeof(Result));
   Ctx.Ptr += sizeof(Result);
-  return Result;
+  return Error::success();
 }
 
-static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
+static Error readULEB128(WasmObjectFile::ReadContext &Ctx, uint64_t &Result) {
   unsigned Count;
-  const char *Error = nullptr;
-  uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
-  if (Error)
-    report_fatal_error(Error);
+  const char *ErrorStr = nullptr;
+  Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &ErrorStr);
+  if (ErrorStr)
+    return parseFailed(ErrorStr);
   Ctx.Ptr += Count;
-  return Result;
+  return Error::success();
 }
 
-static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
-  uint32_t StringLen = readULEB128(Ctx);
-  if (Ctx.Ptr + StringLen > Ctx.End)
-    report_fatal_error("EOF while reading string");
-  StringRef Return =
-      StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
+static Error readString(WasmObjectFile::ReadContext &Ctx, StringRef &Result) {
+  uint64_t StringLen;
+  if (Error E = readULEB128(Ctx, StringLen))
+    return E;
+
+  if (StringLen > static_cast<uint64_t>(Ctx.End - Ctx.Ptr))
+    return parseFailed("EOF while reading string");
+
+  Result = StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
   Ctx.Ptr += StringLen;
-  return Return;
+  return Error::success();
 }
 
-static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
+static Error readLEB128(WasmObjectFile::ReadContext &Ctx, int64_t &Result) {
   unsigned Count;
-  const char *Error = nullptr;
-  uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
-  if (Error)
-    report_fatal_error(Error);
+  const char *ErrorStr = nullptr;
+  uint64_t Decoded = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &ErrorStr);
+  if (ErrorStr)
+    return parseFailed(ErrorStr);
+  Result = static_cast<int64_t>(Decoded);
   Ctx.Ptr += Count;
-  return Result;
+  return Error::success();
 }
 
-static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
-  int64_t Result = readLEB128(Ctx);
-  if (Result > VARUINT1_MAX || Result < 0)
-    report_fatal_error("LEB is outside Varuint1 range");
-  return Result;
+static Error readVaruint1(WasmObjectFile::ReadContext &Ctx, uint8_t &Result) {
+  int64_t Value;
+  if (Error E = readLEB128(Ctx, Value))
+    return E;
+  if (Value > VARUINT1_MAX || Value < 0)
+    return parseFailed("LEB is outside Varuint1 range");
+  Result = Value;
+  return Error::success();
 }
 
-static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
-  int64_t Result = readLEB128(Ctx);
-  if (Result > INT32_MAX || Result < INT32_MIN)
-    report_fatal_error("LEB is outside Varint32 range");
-  return Result;
+static Error readVarint32(WasmObjectFile::ReadContext &Ctx, int32_t &Result) {
+  int64_t Value;
+  if (Error E = readLEB128(Ctx, Value))
+    return E;
+  if (Value > INT32_MAX || Value < INT32_MIN)
+    return parseFailed("LEB is outside Varint32 range");
+  Result = Value;
+  return Error::success();
 }
 
-static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
-  uint64_t Result = readULEB128(Ctx);
-  if (Result > UINT32_MAX)
-    report_fatal_error("LEB is outside Varuint32 range");
-  return Result;
+static Error readVaruint32(WasmObjectFile::ReadContext &Ctx, uint32_t &Result) {
+  uint64_t Value;
+  if (Error E = readULEB128(Ctx, Value))
+    return E;
+  if (Value > UINT32_MAX)
+    return parseFailed("LEB is outside Varuint32 range");
+  Result = Value;
+  return Error::success();
 }
 
-static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
-  return readLEB128(Ctx);
+static Error readVarint64(WasmObjectFile::ReadContext &Ctx, int64_t &Result) {
+  return readLEB128(Ctx, Result);
 }
 
-static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {
-  return readULEB128(Ctx);
+static Error readVaruint64(WasmObjectFile::ReadContext &Ctx, uint64_t &Result) {
+  return readULEB128(Ctx, Result);
 }
 
-static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
-  return readUint8(Ctx);
+static Error readOpcode(WasmObjectFile::ReadContext &Ctx, uint8_t &Result) {
+  return readUint8(Ctx, Result);
 }
 
-static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx,
-                                  uint32_t Code) {
+static Error parseValType(WasmObjectFile::ReadContext &Ctx, uint32_t Code,
----------------
jh7370 wrote:

This sort of function should return `Expected<T>` (where `T` is the intended return type) and not add a new output parameter instead.

Same applies in multiple places.

https://github.com/llvm/llvm-project/pull/215102


More information about the llvm-commits mailing list