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

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sun May 11 00:26:44 PDT 2025


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

>From 0d79165f0a936bf72c19ccf0872b833ac1c000d9 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 11 May 2025 15:22:48 +0800
Subject: [PATCH] [IR] Avoid UB in `SymbolTableListTraits`

---
 llvm/include/llvm/IR/BasicBlock.h            |  4 ++++
 llvm/include/llvm/IR/Function.h              |  4 ++++
 llvm/include/llvm/IR/Module.h                | 13 +++++++++++++
 llvm/include/llvm/IR/SymbolTableListTraits.h |  6 ++----
 4 files changed, 23 insertions(+), 4 deletions(-)

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..f93186d2ea0fc 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -25,6 +25,7 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/GlobalAlias.h"
 #include "llvm/IR/GlobalIFunc.h"
+#include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/ProfileSummary.h"
@@ -609,6 +610,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 +623,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 +665,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 +678,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);



More information about the llvm-commits mailing list