[PATCH] D138830: [llvm] Check for overflows when computing load-command's addresses.

Vy Nguyen via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 28 10:38:27 PST 2022


oontvoo updated this revision to Diff 478279.
oontvoo marked an inline comment as done.
oontvoo added a comment.

- updated type
- separate overflow case to different err msg to make debugging easier


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D138830/new/

https://reviews.llvm.org/D138830

Files:
  llvm/lib/Object/MachOObjectFile.cpp


Index: llvm/lib/Object/MachOObjectFile.cpp
===================================================================
--- llvm/lib/Object/MachOObjectFile.cpp
+++ llvm/lib/Object/MachOObjectFile.cpp
@@ -35,6 +35,7 @@
 #include "llvm/Support/Format.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/LEB128.h"
+#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/SwapByteOrder.h"
@@ -84,7 +85,9 @@
 template <typename T>
 static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
   // Don't read before the beginning or past the end of the file
-  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
+  bool Overflowed = false;
+  uintptr_t Ret = llvm::SaturatingAdd<uintptr_t>(P, sizeof(T), &Overflowed);
+  if (P < O.getData().begin() || Overflowed || Ret > O.getData().end())
     return malformedError("Structure read out-of-range");
 
   T Cmd;
@@ -191,7 +194,14 @@
 getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
                    uint32_t LoadCommandIndex) {
   if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
-    if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
+    bool Overflowed = false;
+    uintptr_t Ret = llvm::SaturatingAdd<uintptr_t>(
+        CmdOrErr->cmdsize, reinterpret_cast<uintptr_t>(Ptr), &Overflowed);
+
+    if (Overflowed)
+      return malformedError("load command " + Twine(LoadCommandIndex) +
+                            " results in overflowed address");
+    if (Ret > reinterpret_cast<uintptr_t>(Obj.getData().end()))
       return malformedError("load command " + Twine(LoadCommandIndex) +
                             " extends past end of file");
     if (CmdOrErr->cmdsize < 8)
@@ -217,8 +227,28 @@
                        const MachOObjectFile::LoadCommandInfo &L) {
   unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
                                       : sizeof(MachO::mach_header);
-  if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
-      Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
+
+  bool Overflowed = false;
+  // FIXME: Perhaps this validation on the Obj file should have been
+  // done somewhere else (earlier).
+  uint32_t LoadCmdsEnd = llvm::SaturatingAdd<uintptr_t>(
+      reinterpret_cast<uintptr_t>(Obj.getData().data()), HeaderSize,
+      &Overflowed);
+  assert(!Overflowed && "Load commands range extends past uint32_t type limit");
+  LoadCmdsEnd = llvm::SaturatingAdd<uintptr_t>(
+      LoadCmdsEnd, Obj.getHeader().sizeofcmds, &Overflowed);
+  assert(!Overflowed && "Load commands range extends past uint32_t type limit");
+
+  uint32_t PtrEnd = llvm::SaturatingAdd<uintptr_t>(
+      reinterpret_cast<uintptr_t>(L.Ptr), L.C.cmdsize, &Overflowed);
+  if (!Overflowed)
+    PtrEnd = llvm::SaturatingAdd<uintptr_t>(PtrEnd, sizeof(MachO::load_command),
+                                            &Overflowed);
+  if (Overflowed)
+    return malformedError("load command " + Twine(LoadCommandIndex + 1) +
+                          " extends past uint32_t type limit.");
+
+  if (PtrEnd > LoadCmdsEnd)
     return malformedError("load command " + Twine(LoadCommandIndex + 1) +
                           " extends past the end all load commands in the file");
   return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D138830.478279.patch
Type: text/x-patch
Size: 3412 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20221128/38300f47/attachment.bin>


More information about the llvm-commits mailing list