[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 09:15:57 PST 2022
oontvoo created this revision.
oontvoo added a reviewer: jyknight.
Herald added a subscriber: hiraditya.
Herald added a project: All.
oontvoo requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
PR/56746
Repository:
rG LLVM Github Monorepo
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,12 @@
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 ||
+ Ret > reinterpret_cast<long unsigned int>(Obj.getData().end()))
return malformedError("load command " + Twine(LoadCommandIndex) +
" extends past end of file");
if (CmdOrErr->cmdsize < 8)
@@ -217,8 +225,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.478266.patch
Type: text/x-patch
Size: 3285 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20221128/4567a7eb/attachment.bin>
More information about the llvm-commits
mailing list