https://github.com/qiyao updated 
https://github.com/llvm/llvm-project/pull/205134

>From 859badc5696398fa397e09a9ddb2d20ae04c8c28 Mon Sep 17 00:00:00 2001
From: Yao Qi <[email protected]>
Date: Mon, 22 Jun 2026 17:25:36 +0100
Subject: [PATCH 1/3] [lldb][Mach-O] Fix load-command loops spinning on cmdsize
 = 0

Every function in `ObjectFileMachO` and `ObjectContainerMachOFileset`
that iterates over load commands advances the file offset by
`lc.cmdsize` after reading each command.  A malformed command with
cmdsize smaller than `sizeof(load_command)` (in particular cmdsize = 0)
does not make forward progress, so the loop spins for ncmds iterations.
With `ncmds` close to `INT_MAX` the function never returns in practice.

Factor the read-and-validate step into a static template helper
`ReadMachOCommand<T>` in each plugin's translation unit.  It reads the
8-byte cmd/cmdsize header and returns false on EOF or on a cmdsize that
is too small to make forward progress.  All load-command loops now use
this helper, replacing the previously duplicated GetU32 + cmdsize
check.  `T` may be `llvm::MachO::load_command` or any of its richer
variants (uuid_command, dylib_command, thread_command, ident_command,
encryption_info_command, ...).   The helper only touches the leading
cmd/cmdsize fields, leaving the rest of `T` for the caller to fill in.

Affected loops in `ObjectFileMachO`:
  IsStripped, GetEncryptedFileRanges, CreateSections, ParseSymtab,
  GetUUID (static), GetAllArchSpecs (two loops), GetDependentModules,
  GetEntryPointAddress, GetNumThreadContexts, FindLC_NOTEByName,
  GetIdentifierString, GetVersion, FindMinimumVersionInfo

And in ObjectContainerMachOFileset:
  ParseFileset

Add unit tests (`ObjectFileMachOTest::ZeroCmdSize` and
`ObjectContainerMachOFilesetTest::ZeroCmdSize`) that feed a 40-byte
Mach-O with `ncmds = 0x7FFFFFFF` and `cmdsize = 0` into the relevant
parsers.  Without the fix the tests spin ~2 billion iterations; with
the fix they return immediately.  Found by lldb-target-fuzzer.

Assisted-by: Claude
---
 .../ObjectContainerMachOFileset.cpp           | 20 +++++-
 .../ObjectFile/Mach-O/ObjectFileMachO.cpp     | 46 ++++++++----
 lldb/unittests/ObjectContainer/CMakeLists.txt |  1 +
 .../ObjectContainerUniversalMachOTest.cpp     | 72 +++++++++++++++++++
 .../ObjectFile/MachO/TestObjectFileMachO.cpp  | 65 +++++++++++++++++
 5 files changed, 189 insertions(+), 15 deletions(-)

diff --git 
a/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp
 
b/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp
index 706b8e38e9510..fb6b3de6a0c81 100644
--- 
a/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp
+++ 
b/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp
@@ -21,6 +21,24 @@ using namespace lldb;
 using namespace lldb_private;
 using namespace llvm::MachO;
 
+/// Read a Mach-O load-command header (cmd + cmdsize) from \p data at
+/// \p offset into \p cmd, advancing \p offset by 8 bytes.  \p T may be
+/// \c llvm::MachO::load_command or any of its richer variants
+/// (\c thread_command, \c dylib_command, \c encryption_info_command, ...);
+/// only the leading cmd/cmdsize fields are touched by this read.  Returns
+/// false on EOF or on a cmdsize smaller than sizeof(load_command), in which
+/// case callers should break out of their load-command loop to avoid spinning
+/// on malformed input.
+template <typename T>
+static bool ReadMachOCommand(DataExtractor &data, lldb::offset_t &offset,
+                             T &cmd) {
+  if (data.GetU32(&offset, &cmd, 2) == nullptr)
+    return false;
+  if (cmd.cmdsize < sizeof(load_command))
+    return false;
+  return true;
+}
+
 LLDB_PLUGIN_DEFINE(ObjectContainerMachOFileset)
 
 void ObjectContainerMachOFileset::Initialize() {
@@ -142,7 +160,7 @@ ParseFileset(DataExtractor &extractor, mach_header header,
   for (uint32_t i = 0; i < header.ncmds; ++i) {
     const lldb::offset_t load_cmd_offset = offset;
     load_command lc = {};
-    if (extractor.GetU32(&offset, &lc.cmd, 2) == nullptr)
+    if (!ReadMachOCommand(extractor, offset, lc))
       break;
 
     // If we know the load address we can compute the slide.
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp 
b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index a7096fa83315f..a4b23c162d194 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -139,6 +139,24 @@ static constexpr llvm::StringLiteral g_executable_path = 
"@executable_path";
 
 LLDB_PLUGIN_DEFINE(ObjectFileMachO)
 
+/// Read a Mach-O load-command header (cmd + cmdsize) from \p data at
+/// \p offset into \p cmd, advancing \p offset by 8 bytes.  \p T may be
+/// \c llvm::MachO::load_command or any of its richer variants
+/// (\c thread_command, \c dylib_command, \c encryption_info_command, ...);
+/// only the leading cmd/cmdsize fields are touched by this read.  Returns
+/// false on EOF or on a cmdsize smaller than sizeof(load_command), in which
+/// case callers should break out of their load-command loop to avoid spinning
+/// on malformed input.
+template <typename T>
+static bool ReadMachOCommand(const DataExtractor &data, lldb::offset_t &offset,
+                             T &cmd) {
+  if (data.GetU32(&offset, &cmd, 2) == nullptr)
+    return false;
+  if (cmd.cmdsize < sizeof(load_command))
+    return false;
+  return true;
+}
+
 static void PrintRegisterValue(RegisterContext *reg_ctx, const char *name,
                                const char *alt_name, size_t reg_byte_size,
                                Stream &data) {
@@ -1305,7 +1323,7 @@ bool ObjectFileMachO::IsStripped() {
         const lldb::offset_t load_cmd_offset = offset;
 
         llvm::MachO::load_command lc = {};
-        if (m_data_nsp->GetU32(&offset, &lc.cmd, 2) == nullptr)
+        if (!ReadMachOCommand(*m_data_nsp, offset, lc))
           break;
         if (lc.cmd == LC_DYSYMTAB) {
           m_dysymtab.cmd = lc.cmd;
@@ -1334,7 +1352,7 @@ ObjectFileMachO::EncryptedFileRanges 
ObjectFileMachO::GetEncryptedFileRanges() {
   llvm::MachO::encryption_info_command encryption_cmd;
   for (uint32_t i = 0; i < m_header.ncmds; ++i) {
     const lldb::offset_t load_cmd_offset = offset;
-    if (m_data_nsp->GetU32(&offset, &encryption_cmd, 2) == nullptr)
+    if (!ReadMachOCommand(*m_data_nsp, offset, encryption_cmd))
       break;
 
     // LC_ENCRYPTION_INFO and LC_ENCRYPTION_INFO_64 have the same sizes for the
@@ -1883,7 +1901,7 @@ void ObjectFileMachO::CreateSections(SectionList 
&unified_section_list) {
   llvm::MachO::load_command load_cmd;
   for (uint32_t i = 0; i < m_header.ncmds; ++i) {
     const lldb::offset_t load_cmd_offset = offset;
-    if (m_data_nsp->GetU32(&offset, &load_cmd, 2) == nullptr)
+    if (!ReadMachOCommand(*m_data_nsp, offset, load_cmd))
       break;
 
     if (load_cmd.cmd == LC_SEGMENT || load_cmd.cmd == LC_SEGMENT_64)
@@ -2116,7 +2134,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
     const lldb::offset_t cmd_offset = offset;
     // Read in the load command and load command size
     llvm::MachO::load_command lc;
-    if (m_data_nsp->GetU32(&offset, &lc, 2) == nullptr)
+    if (!ReadMachOCommand(*m_data_nsp, offset, lc))
       break;
     // Watch for the symbol table load command
     switch (lc.cmd) {
@@ -4470,7 +4488,7 @@ UUID ObjectFileMachO::GetUUID(const 
llvm::MachO::mach_header &header,
   lldb::offset_t offset = lc_offset;
   for (i = 0; i < header.ncmds; ++i) {
     const lldb::offset_t cmd_offset = offset;
-    if (data.GetU32(&offset, &load_cmd, 2) == nullptr)
+    if (!ReadMachOCommand(data, offset, load_cmd))
       break;
 
     if (load_cmd.cmd == LC_UUID) {
@@ -4629,7 +4647,7 @@ void ObjectFileMachO::GetAllArchSpecs(const 
llvm::MachO::mach_header &header,
   lldb::offset_t offset = lc_offset;
   for (uint32_t i = 0; i < header.ncmds; ++i) {
     const lldb::offset_t cmd_offset = offset;
-    if (data.GetU32(&offset, &load_cmd, 2) == nullptr)
+    if (!ReadMachOCommand(data, offset, load_cmd))
       break;
 
     llvm::MachO::version_min_command version_min;
@@ -4679,7 +4697,7 @@ void ObjectFileMachO::GetAllArchSpecs(const 
llvm::MachO::mach_header &header,
   offset = lc_offset;
   for (uint32_t i = 0; i < header.ncmds; ++i) {
     const lldb::offset_t cmd_offset = offset;
-    if (data.GetU32(&offset, &load_cmd, 2) == nullptr)
+    if (!ReadMachOCommand(data, offset, load_cmd))
       break;
 
     do {
@@ -4765,7 +4783,7 @@ uint32_t 
ObjectFileMachO::GetDependentModules(FileSpecList &files) {
   uint32_t i;
   for (i = 0; i < m_header.ncmds; ++i) {
     const uint32_t cmd_offset = offset;
-    if (m_data_nsp->GetU32(&offset, &load_cmd, 2) == nullptr)
+    if (!ReadMachOCommand(*m_data_nsp, offset, load_cmd))
       break;
 
     switch (load_cmd.cmd) {
@@ -4914,7 +4932,7 @@ lldb_private::Address 
ObjectFileMachO::GetEntryPointAddress() {
 
     for (i = 0; i < m_header.ncmds; ++i) {
       const lldb::offset_t cmd_offset = offset;
-      if (m_data_nsp->GetU32(&offset, &load_cmd, 2) == nullptr)
+      if (!ReadMachOCommand(*m_data_nsp, offset, load_cmd))
         break;
 
       switch (load_cmd.cmd) {
@@ -5054,7 +5072,7 @@ uint32_t ObjectFileMachO::GetNumThreadContexts() {
       llvm::MachO::thread_command thread_cmd;
       for (uint32_t i = 0; i < m_header.ncmds; ++i) {
         const uint32_t cmd_offset = offset;
-        if (m_data_nsp->GetU32(&offset, &thread_cmd, 2) == nullptr)
+        if (!ReadMachOCommand(*m_data_nsp, offset, thread_cmd))
           break;
 
         if (thread_cmd.cmd == LC_THREAD) {
@@ -5080,7 +5098,7 @@ ObjectFileMachO::FindLC_NOTEByName(std::string name) {
     for (uint32_t i = 0; i < m_header.ncmds; ++i) {
       const uint32_t cmd_offset = offset;
       llvm::MachO::load_command lc = {};
-      if (m_data_nsp->GetU32(&offset, &lc.cmd, 2) == nullptr)
+      if (!ReadMachOCommand(*m_data_nsp, offset, lc))
         break;
       if (lc.cmd == LC_NOTE) {
         char data_owner[17];
@@ -5130,7 +5148,7 @@ std::string ObjectFileMachO::GetIdentifierString() {
     for (uint32_t i = 0; i < m_header.ncmds; ++i) {
       const uint32_t cmd_offset = offset;
       llvm::MachO::ident_command ident_command;
-      if (m_data_nsp->GetU32(&offset, &ident_command, 2) == nullptr)
+      if (!ReadMachOCommand(*m_data_nsp, offset, ident_command))
         break;
       if (ident_command.cmd == LC_IDENT && ident_command.cmdsize != 0) {
         std::string result(ident_command.cmdsize, '\0');
@@ -5555,7 +5573,7 @@ llvm::VersionTuple ObjectFileMachO::GetVersion() {
     uint32_t i;
     for (i = 0; i < m_header.ncmds; ++i) {
       const lldb::offset_t cmd_offset = offset;
-      if (m_data_nsp->GetU32(&offset, &load_cmd, 2) == nullptr)
+      if (!ReadMachOCommand(*m_data_nsp, offset, load_cmd))
         break;
 
       if (load_cmd.cmd == LC_ID_DYLIB) {
@@ -5715,7 +5733,7 @@ static llvm::VersionTuple 
FindMinimumVersionInfo(DataExtractor &data,
   for (size_t i = 0; i < ncmds; i++) {
     const lldb::offset_t load_cmd_offset = offset;
     llvm::MachO::load_command lc = {};
-    if (data.GetU32(&offset, &lc.cmd, 2) == nullptr)
+    if (!ReadMachOCommand(data, offset, lc))
       break;
 
     uint32_t version = 0;
diff --git a/lldb/unittests/ObjectContainer/CMakeLists.txt 
b/lldb/unittests/ObjectContainer/CMakeLists.txt
index 80778d1c32f17..8acfccf12f4dd 100644
--- a/lldb/unittests/ObjectContainer/CMakeLists.txt
+++ b/lldb/unittests/ObjectContainer/CMakeLists.txt
@@ -3,6 +3,7 @@ add_lldb_unittest(ObjectContainerTests
 
   LINK_LIBS
     lldbPluginObjectContainerMachOArchive
+    lldbPluginObjectContainerMachOFileset
     lldbCore
     lldbUtilityHelpers
     LLVMTestingSupport
diff --git 
a/lldb/unittests/ObjectContainer/ObjectContainerUniversalMachOTest.cpp 
b/lldb/unittests/ObjectContainer/ObjectContainerUniversalMachOTest.cpp
index a4346befbfd8b..374c3c96b1a9f 100644
--- a/lldb/unittests/ObjectContainer/ObjectContainerUniversalMachOTest.cpp
+++ b/lldb/unittests/ObjectContainer/ObjectContainerUniversalMachOTest.cpp
@@ -7,11 +7,14 @@
 
//===----------------------------------------------------------------------===//
 
 #include 
"Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h"
+#include "Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.h"
 #include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/DataExtractor.h"
 #include "lldb/Utility/FileSpec.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Testing/Support/Error.h"
@@ -117,3 +120,72 @@ TEST_F(ObjectContainerUniversalMachOTest, SliceOffsetZero) 
{
 
   ASSERT_THAT_ERROR(TmpFile->discard(), llvm::Succeeded());
 }
+
+// Regression fixture: a Mach-O fileset whose single load command has
+// cmdsize = 0.  With ncmds set near INT_MAX the function hangs.  The
+// fix breaks out of the loop as soon as
+// cmdsize < sizeof(load_command).  Found by lldb-target-fuzzer.
+namespace {
+class ObjectContainerMachOFilesetTest : public ::testing::Test {
+  SubsystemRAII<FileSystem, ObjectContainerMachOFileset> subsystems;
+};
+} // namespace
+
+TEST_F(ObjectContainerMachOFilesetTest, ZeroCmdSize) {
+  // Minimal little-endian x86_64 Mach-O fileset: mach_header_64 (32 bytes)
+  // followed by a single load_command with cmdsize = 0.  ncmds is set to
+  // 0x7FFFFFFF so that without the fix ParseFileset spins ~2 billion times and
+  // never returns in practice; with the fix it breaks on the first iteration.
+  // Reaching the assertion below is the regression check.
+  const uint8_t kData[] = {
+      // mach_header_64 (little-endian)
+      0xCF,
+      0xFA,
+      0xED,
+      0xFE, // magic:      MH_MAGIC_64
+      0x07,
+      0x00,
+      0x00,
+      0x01, // cputype:    CPU_TYPE_X86_64
+      0x03,
+      0x00,
+      0x00,
+      0x80, // cpusubtype: CPU_SUBTYPE_X86_64_ALL
+      0x0C,
+      0x00,
+      0x00,
+      0x00, // filetype:   MH_FILESET
+      0xFF,
+      0xFF,
+      0xFF,
+      0x7F, // ncmds:      0x7FFFFFFF
+      0x08,
+      0x00,
+      0x00,
+      0x00, // sizeofcmds: 8
+      0x00,
+      0x00,
+      0x00,
+      0x00, // flags:      0
+      0x00,
+      0x00,
+      0x00,
+      0x00, // reserved:   0
+      // load_command
+      0x19,
+      0x00,
+      0x00,
+      0x00, // cmd:     LC_SEGMENT_64 (arbitrary)
+      0x00,
+      0x00,
+      0x00,
+      0x00, // cmdsize: 0  ← causes the spin
+  };
+  auto Buf = std::make_shared<DataBufferHeap>(kData, sizeof(kData));
+  lldb::DataExtractorSP DataSP =
+      std::make_shared<lldb_private::DataExtractor>(Buf, 
lldb::eByteOrderLittle,
+                                                    /*addr_size=*/8);
+  // Before the fix ParseFileset loops ~0x7FFFFFFF times and never returns.
+  (void)ObjectContainerMachOFileset::GetModuleSpecifications(FileSpec(), 
DataSP,
+                                                             0, sizeof(kData));
+}
diff --git a/lldb/unittests/ObjectFile/MachO/TestObjectFileMachO.cpp 
b/lldb/unittests/ObjectFile/MachO/TestObjectFileMachO.cpp
index 147ea55e85efa..70e0b570fca8b 100644
--- a/lldb/unittests/ObjectFile/MachO/TestObjectFileMachO.cpp
+++ b/lldb/unittests/ObjectFile/MachO/TestObjectFileMachO.cpp
@@ -15,6 +15,9 @@
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/DataExtractor.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/lldb-defines.h"
 #include "gtest/gtest.h"
@@ -107,3 +110,65 @@ TEST_F(ObjectFileMachOTest, 
IndirectSymbolsInTheSharedCache) {
     OF->ParseSymtab(symtab);
 }
 #endif
+
+// Regression fixture: a Mach-O whose load commands all have cmdsize = 0.
+// With ncmds set near INT_MAX the functions hang.  The fix breaks out of
+// the loop as soon as cmdsize < sizeof(load_command).  Found by
+// lldb-target-fuzzer.
+TEST_F(ObjectFileMachOTest, ZeroCmdSize) {
+  // Minimal little-endian x86_64 Mach-O: mach_header_64 (32 bytes) followed
+  // by a single load_command with cmdsize = 0.  ncmds is set to 0x7FFFFFFF so
+  // that without the fix the loops in GetAllArchSpecs/GetUUID never return in
+  // practice; with the fix they break on the very first iteration.
+  // Reaching the assertion below is the regression check.
+  const uint8_t kData[] = {
+      // mach_header_64 (little-endian)
+      0xCF,
+      0xFA,
+      0xED,
+      0xFE, // magic:      MH_MAGIC_64
+      0x07,
+      0x00,
+      0x00,
+      0x01, // cputype:    CPU_TYPE_X86_64
+      0x03,
+      0x00,
+      0x00,
+      0x80, // cpusubtype: CPU_SUBTYPE_X86_64_ALL
+      0x02,
+      0x00,
+      0x00,
+      0x00, // filetype:   MH_EXECUTE
+      0xFF,
+      0xFF,
+      0xFF,
+      0x7F, // ncmds:      0x7FFFFFFF
+      0x08,
+      0x00,
+      0x00,
+      0x00, // sizeofcmds: 8
+      0x00,
+      0x00,
+      0x00,
+      0x00, // flags:      0
+      0x00,
+      0x00,
+      0x00,
+      0x00, // reserved:   0
+      // load_command
+      0x19,
+      0x00,
+      0x00,
+      0x00, // cmd:     LC_SEGMENT_64 (arbitrary)
+      0x00,
+      0x00,
+      0x00,
+      0x00, // cmdsize: 0  ← causes the spin
+  };
+  auto Buf = std::make_shared<DataBufferHeap>(kData, sizeof(kData));
+  lldb::DataExtractorSP DataSP = std::make_shared<lldb_private::DataExtractor>(
+      Buf, lldb::eByteOrderLittle, /*addr_size=*/8);
+  // Before the fix GetAllArchSpecs loops ~0x7FFFFFFF times and never returns.
+  (void)ObjectFile::GetModuleSpecifications(FileSpec(), DataSP, 0,
+                                            sizeof(kData));
+}

>From 7cfd1cf0ae8c1ab1d85432c418e7dd13f518ae9e Mon Sep 17 00:00:00 2001
From: Yao Qi <[email protected]>
Date: Tue, 23 Jun 2026 16:47:40 +0100
Subject: [PATCH 2/3] [lldb][Mach-O] Statically check ReadMachOCommand<T>'s
 leading-field contract

Address review feedback on the prior commit: document and enforce that
T must start with `uint32_t cmd` followed by `uint32_t cmdsize`, since
`ReadMachOCommand<T>` writes those eight bytes via `GetU32(..., &cmd, 2)`
and then reads `cmd.cmdsize` by name.

Add four `static_assert`s at the top of the helper:

  - offsetof(T, cmd)     == 0
  - offsetof(T, cmdsize) == sizeof(uint32_t)
  - decltype(T::cmd)     is uint32_t
  - decltype(T::cmdsize) is uint32_t

If a future MachO command variant (or an accidental wrong T) breaks the
contract, the build fails with a clear message instead of silently
corrupting memory or misreading cmdsize.

No behaviour change at runtime; all instantiations in ObjectFileMachO
and ObjectContainerMachOFileset (load_command, encryption_info_command,
fileset_entry_command, ...) compile cleanly.

Assisted-by: Claude
---
 .../Mach-O-Fileset/ObjectContainerMachOFileset.cpp        | 8 ++++++++
 lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp | 8 ++++++++
 2 files changed, 16 insertions(+)

diff --git 
a/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp
 
b/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp
index fb6b3de6a0c81..82947ecaa643d 100644
--- 
a/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp
+++ 
b/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp
@@ -32,6 +32,14 @@ using namespace llvm::MachO;
 template <typename T>
 static bool ReadMachOCommand(DataExtractor &data, lldb::offset_t &offset,
                              T &cmd) {
+  static_assert(offsetof(T, cmd) == 0,
+                "T::cmd must be the first field");
+  static_assert(offsetof(T, cmdsize) == sizeof(uint32_t),
+                "T::cmdsize must immediately follow T::cmd");
+  static_assert(std::is_same<decltype(T::cmd), uint32_t>::value,
+                "T::cmd must be uint32_t");
+  static_assert(std::is_same<decltype(T::cmdsize), uint32_t>::value,
+                "T::cmdsize must be uint32_t");
   if (data.GetU32(&offset, &cmd, 2) == nullptr)
     return false;
   if (cmd.cmdsize < sizeof(load_command))
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp 
b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index a4b23c162d194..565669de7b76d 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -150,6 +150,14 @@ LLDB_PLUGIN_DEFINE(ObjectFileMachO)
 template <typename T>
 static bool ReadMachOCommand(const DataExtractor &data, lldb::offset_t &offset,
                              T &cmd) {
+  static_assert(offsetof(T, cmd) == 0,
+                "T::cmd must be the first field");
+  static_assert(offsetof(T, cmdsize) == sizeof(uint32_t),
+                "T::cmdsize must immediately follow T::cmd");
+  static_assert(std::is_same<decltype(T::cmd), uint32_t>::value,
+                "T::cmd must be uint32_t");
+  static_assert(std::is_same<decltype(T::cmdsize), uint32_t>::value,
+                "T::cmdsize must be uint32_t");
   if (data.GetU32(&offset, &cmd, 2) == nullptr)
     return false;
   if (cmd.cmdsize < sizeof(load_command))

>From ebeb66c74984750027232a6dff9cce420bc8f825 Mon Sep 17 00:00:00 2001
From: Yao Qi <[email protected]>
Date: Tue, 23 Jun 2026 17:04:30 +0100
Subject: [PATCH 3/3] [lldb][Mach-O] Format fix in ReadMachOCommand
 static_asserts

CI's clang-format wants the first static_assert on a single line, it
fits in 80 columns.  No semantic change.
---
 .../Mach-O-Fileset/ObjectContainerMachOFileset.cpp             | 3 +--
 lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp      | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git 
a/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp
 
b/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp
index 82947ecaa643d..bc60c00e64317 100644
--- 
a/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp
+++ 
b/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp
@@ -32,8 +32,7 @@ using namespace llvm::MachO;
 template <typename T>
 static bool ReadMachOCommand(DataExtractor &data, lldb::offset_t &offset,
                              T &cmd) {
-  static_assert(offsetof(T, cmd) == 0,
-                "T::cmd must be the first field");
+  static_assert(offsetof(T, cmd) == 0, "T::cmd must be the first field");
   static_assert(offsetof(T, cmdsize) == sizeof(uint32_t),
                 "T::cmdsize must immediately follow T::cmd");
   static_assert(std::is_same<decltype(T::cmd), uint32_t>::value,
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp 
b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 565669de7b76d..391ffe240551b 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -150,8 +150,7 @@ LLDB_PLUGIN_DEFINE(ObjectFileMachO)
 template <typename T>
 static bool ReadMachOCommand(const DataExtractor &data, lldb::offset_t &offset,
                              T &cmd) {
-  static_assert(offsetof(T, cmd) == 0,
-                "T::cmd must be the first field");
+  static_assert(offsetof(T, cmd) == 0, "T::cmd must be the first field");
   static_assert(offsetof(T, cmdsize) == sizeof(uint32_t),
                 "T::cmdsize must immediately follow T::cmd");
   static_assert(std::is_same<decltype(T::cmd), uint32_t>::value,

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to