[llvm] [IR] Avoid UB in `SymbolTableListTraits` (PR #139096)

via llvm-commits llvm-commits at lists.llvm.org
Thu May 29 04:14:56 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-ir

Author: Yingwei Zheng (dtcxzyw)

<details>
<summary>Changes</summary>

This patch fixes the "dereferencing null" UB. Unfortunately, C++ doesn't provide an inverse operation for `p->*pmf`.
See also https://github.com/llvm/llvm-project/pull/130952.


---
Full diff: https://github.com/llvm/llvm-project/pull/139096.diff


4 Files Affected:

- (modified) llvm/include/llvm/IR/BasicBlock.h (+4) 
- (modified) llvm/include/llvm/IR/Function.h (+4) 
- (modified) llvm/include/llvm/IR/Module.h (+12) 
- (modified) llvm/include/llvm/IR/SymbolTableListTraits.h (+2-4) 


``````````diff
diff --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h
index 9ee0bacb5c258..10617db09fde6 100644
--- a/llvm/include/llvm/IR/BasicBlock.h
+++ b/llvm/include/llvm/IR/BasicBlock.h
@@ -546,6 +546,10 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
     return &BasicBlock::InstList;
   }
 
+  static size_t getSublistOffset(Instruction *) {
+    return offsetof(BasicBlock, InstList);
+  }
+
   /// Dedicated function for splicing debug-info: when we have an empty
   /// splice (i.e. zero instructions), the caller may still intend any
   /// debug-info in between the two "positions" to be spliced.
diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h
index 6d4a53da7ff22..63100568d07e4 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -811,6 +811,10 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
     return &Function::BasicBlocks;
   }
 
+  static size_t getSublistOffset(BasicBlock *) {
+    return offsetof(Function, BasicBlocks);
+  }
+
 public:
   const BasicBlock       &getEntryBlock() const   { return front(); }
         BasicBlock       &getEntryBlock()         { return front(); }
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index 53d1005333ee1..298ccab3bfae1 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -609,6 +609,9 @@ class LLVM_ABI Module {
   static GlobalListType Module::*getSublistAccess(GlobalVariable*) {
     return &Module::GlobalList;
   }
+  static size_t getSublistOffset(GlobalVariable *) {
+    return offsetof(Module, GlobalList);
+  }
   friend class llvm::SymbolTableListTraits<llvm::GlobalVariable>;
 
 public:
@@ -619,6 +622,9 @@ class LLVM_ABI Module {
   static FunctionListType Module::*getSublistAccess(Function*) {
     return &Module::FunctionList;
   }
+  static size_t getSublistOffset(Function *) {
+    return offsetof(Module, FunctionList);
+  }
 
   /// Detach \p Alias from the list but don't delete it.
   void removeAlias(GlobalAlias *Alias) { AliasList.remove(Alias); }
@@ -658,6 +664,9 @@ class LLVM_ABI Module {
   static AliasListType Module::*getSublistAccess(GlobalAlias*) {
     return &Module::AliasList;
   }
+  static size_t getSublistOffset(GlobalAlias *) {
+    return offsetof(Module, AliasList);
+  }
   friend class llvm::SymbolTableListTraits<llvm::GlobalAlias>;
 
   /// Get the Module's list of ifuncs (constant).
@@ -668,6 +677,9 @@ class LLVM_ABI Module {
   static IFuncListType Module::*getSublistAccess(GlobalIFunc*) {
     return &Module::IFuncList;
   }
+  static size_t getSublistOffset(GlobalIFunc *) {
+    return offsetof(Module, IFuncList);
+  }
   friend class llvm::SymbolTableListTraits<llvm::GlobalIFunc>;
 
   /// Get the Module's list of named metadata (constant).
diff --git a/llvm/include/llvm/IR/SymbolTableListTraits.h b/llvm/include/llvm/IR/SymbolTableListTraits.h
index fcf6f0fb15280..456833fff62ce 100644
--- a/llvm/include/llvm/IR/SymbolTableListTraits.h
+++ b/llvm/include/llvm/IR/SymbolTableListTraits.h
@@ -77,10 +77,8 @@ class SymbolTableListTraits : public ilist_alloc_traits<ValueSubClass> {
   /// getListOwner - Return the object that owns this list.  If this is a list
   /// of instructions, it returns the BasicBlock that owns them.
   ItemParentClass *getListOwner() {
-    size_t Offset = reinterpret_cast<size_t>(
-        &((ItemParentClass *)nullptr->*ItemParentClass::getSublistAccess(
-                                           static_cast<ValueSubClass *>(
-                                               nullptr))));
+    size_t Offset = ItemParentClass::getSublistOffset(
+        static_cast<ValueSubClass *>(nullptr));
     ListTy *Anchor = static_cast<ListTy *>(this);
     return reinterpret_cast<ItemParentClass*>(reinterpret_cast<char*>(Anchor)-
                                               Offset);

``````````

</details>


https://github.com/llvm/llvm-project/pull/139096


More information about the llvm-commits mailing list