[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