|
19 | 19 | #include "llvm/Support/Error.h" |
20 | 20 | #include "llvm/Support/FormatVariadic.h" |
21 | 21 | #include "llvm/Support/LEB128.h" |
22 | | -#include "llvm/Support/YAMLTraits.h" |
23 | 22 | #include "llvm/Support/SystemZ/zOSSupport.h" |
| 23 | +#include "llvm/Support/WithColor.h" |
| 24 | +#include "llvm/Support/YAMLTraits.h" |
24 | 25 | #include "llvm/Support/raw_ostream.h" |
25 | 26 |
|
26 | 27 | using namespace llvm; |
27 | 28 |
|
28 | 29 | namespace { |
29 | 30 |
|
| 31 | +static const char *getLoadCommandName(uint32_t cmd) { |
| 32 | + switch (cmd) { |
| 33 | +#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ |
| 34 | + case MachO::LCName: \ |
| 35 | + return #LCName; |
| 36 | +#include "llvm/BinaryFormat/MachO.def" |
| 37 | + default: |
| 38 | + return nullptr; |
| 39 | + } |
| 40 | +} |
| 41 | + |
30 | 42 | class MachOWriter { |
31 | 43 | public: |
32 | 44 | MachOWriter(MachOYAML::Object &Obj) : Obj(Obj), fileStart(0) { |
@@ -244,7 +256,8 @@ void MachOWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) { |
244 | 256 | } |
245 | 257 |
|
246 | 258 | void MachOWriter::writeLoadCommands(raw_ostream &OS) { |
247 | | - for (auto &LC : Obj.LoadCommands) { |
| 259 | + for (size_t i = 0; i < Obj.LoadCommands.size(); ++i) { |
| 260 | + auto &LC = Obj.LoadCommands[i]; |
248 | 261 | size_t BytesWritten = 0; |
249 | 262 | llvm::MachO::macho_load_command Data = LC.Data; |
250 | 263 |
|
@@ -285,7 +298,25 @@ void MachOWriter::writeLoadCommands(raw_ostream &OS) { |
285 | 298 |
|
286 | 299 | // Fill remaining bytes with 0. This will only get hit in partially |
287 | 300 | // specified test cases. |
288 | | - auto BytesRemaining = LC.Data.load_command_data.cmdsize - BytesWritten; |
| 301 | + // Prevent integer underflow if BytesWritten exceeds cmdsize. |
| 302 | + if (BytesWritten > LC.Data.load_command_data.cmdsize) { |
| 303 | + std::string Name; |
| 304 | + const char *NameCStr = getLoadCommandName(LC.Data.load_command_data.cmd); |
| 305 | + if (NameCStr) |
| 306 | + Name = NameCStr; |
| 307 | + else |
| 308 | + Name = ("(0x" + Twine::utohexstr(LC.Data.load_command_data.cmd) + ")") |
| 309 | + .str(); |
| 310 | + |
| 311 | + WithColor::warning() << "load command " << i << " " << Name |
| 312 | + << " cmdsize too small (" |
| 313 | + << LC.Data.load_command_data.cmdsize |
| 314 | + << " bytes) for actual size (" << BytesWritten |
| 315 | + << " bytes)\n"; |
| 316 | + } |
| 317 | + auto BytesRemaining = (BytesWritten < LC.Data.load_command_data.cmdsize) |
| 318 | + ? LC.Data.load_command_data.cmdsize - BytesWritten |
| 319 | + : 0; |
289 | 320 | if (BytesRemaining > 0) { |
290 | 321 | ZeroFillBytes(OS, BytesRemaining); |
291 | 322 | } |
|
0 commit comments