Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[PPCMergeStringPool] Only replace constant once #92996

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 27, 2024
Merged

Conversation

nikic
Copy link
Contributor

@nikic nikic commented May 22, 2024

In #88846 I changed this code to use RAUW to perform the replacement instead of manual updates -- but kept the outer loop, which means we try to perform RAUW once per user. However, some of the users might be freed by the RAUW operation, resulting in use-after-free.

I think the case where this happens is constant users where the replacement might result in the destruction of the original constant.

Fixes #92991.

@llvmbot
Copy link
Member

llvmbot commented May 22, 2024

@llvm/pr-subscribers-backend-powerpc

Author: Nikita Popov (nikic)

Changes

In #88846 I changed this code to use RAUW to perform the replacement instead of manual updates -- but kept the outer loop, which means we try to perform RAUW once per user. However, some of the users might be freed by the RAUW operation, resulting in use-after-free.

I think the case where this happens is constant users where the replacement might result in the destruction of the original constant. I wasn't able to come up with a test case though.

This is intended to fix #92991.


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

1 Files Affected:

  • (modified) llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp (+7-30)
diff --git a/llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp b/llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp
index abc5353e4a5e9..b73e25d37f8f5 100644
--- a/llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp
+++ b/llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp
@@ -302,13 +302,6 @@ bool PPCMergeStringPool::mergeModuleStringPool(Module &M) {
   return true;
 }
 
-static bool userHasOperand(User *TheUser, GlobalVariable *GVOperand) {
-  for (Value *Op : TheUser->operands())
-    if (Op == GVOperand)
-      return true;
-  return false;
-}
-
 // For pooled strings we need to add the offset into the pool for each string.
 // This is done by adding a Get Element Pointer (GEP) before each user. This
 // function adds the GEP.
@@ -319,29 +312,13 @@ void PPCMergeStringPool::replaceUsesWithGEP(GlobalVariable *GlobalToReplace,
   Indices.push_back(ConstantInt::get(Type::getInt32Ty(*Context), 0));
   Indices.push_back(ConstantInt::get(Type::getInt32Ty(*Context), ElementIndex));
 
-  // Need to save a temporary copy of each user list because we remove uses
-  // as we replace them.
-  SmallVector<User *> Users;
-  for (User *CurrentUser : GlobalToReplace->users())
-    Users.push_back(CurrentUser);
-
-  for (User *CurrentUser : Users) {
-    // The user was not found so it must have been replaced earlier.
-    if (!userHasOperand(CurrentUser, GlobalToReplace))
-      continue;
-
-    // We cannot replace operands in globals so we ignore those.
-    if (isa<GlobalValue>(CurrentUser))
-      continue;
-
-    Constant *ConstGEP = ConstantExpr::getInBoundsGetElementPtr(
-        PooledStructType, GPool, Indices);
-    LLVM_DEBUG(dbgs() << "Replacing this global:\n");
-    LLVM_DEBUG(GlobalToReplace->dump());
-    LLVM_DEBUG(dbgs() << "with this:\n");
-    LLVM_DEBUG(ConstGEP->dump());
-    GlobalToReplace->replaceAllUsesWith(ConstGEP);
-  }
+  Constant *ConstGEP = ConstantExpr::getInBoundsGetElementPtr(
+      PooledStructType, GPool, Indices);
+  LLVM_DEBUG(dbgs() << "Replacing this global:\n");
+  LLVM_DEBUG(GlobalToReplace->dump());
+  LLVM_DEBUG(dbgs() << "with this:\n");
+  LLVM_DEBUG(ConstGEP->dump());
+  GlobalToReplace->replaceAllUsesWith(ConstGEP);
 }
 
 } // namespace

Copy link

github-actions bot commented May 22, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

nikic added 3 commits May 23, 2024 09:02
In llvm#88846 I changed this code to use RAUW to perform the replacement
instead of manual updates -- but kept the outer loop, which means
we try to perform RAUW once per user. However, some of the users
might be freed by the RAUW operation, resulting in use-after-free.

I think the case where this happens is constant users where the
replacement might result in the destruction of the original
constant. I wasn't able to come up with a test case though.

This is intended to fix llvm#92991.
This previously produced use-after-free under asan.
@nikic nikic force-pushed the ppc-string-pool branch from 3a5f916 to c6ab5a3 Compare May 23, 2024 07:05
@nikic
Copy link
Contributor Author

nikic commented May 23, 2024

I've added a test case now. It would previously fail when running with asan.

@stefanp-synopsys
Copy link
Contributor

Thank you for adding a test case!
I have tried the test case but it seems to pass both with and without your patch.

$ llvm-lit -v test/CodeGen/PowerPC/mergeable-string-pool-pr92991.ll
-- Testing: 1 tests, 1 workers --
PASS: LLVM :: CodeGen/PowerPC/mergeable-string-pool-pr92991.ll (1 of 1)

Testing Time: 0.07s

Total Discovered Tests: 1
  Passed: 1 (100.00%)
$ git log --oneline
f64732195c10 (HEAD) [FunctionAttrs] Regenerate test checks (NFC)
ca478bc6cc0e [SCEV] Support ule/sle exit counts via widening (#92206)
5ec91b392d7e [AttributorLight] Without liveness checks, look at all functions (#91004)
7f5c71efc441 InterleavedLoadCombine: Correctly query PM for TargetTransformInfo (#93103)
896bceb9537e [MC/DC][Coverage] Add assertions into emitSourceRegions() (#89572)
beac910c3bfc [nfc][InstrProfWriter]Wrap vtable writes in a method. (#93081)
2375921d6734 [ProfileData] Use default member initializations (NFC) (#93120)
aa4069ea96e5 Revert "[X86] Remove knl/knm specific ISAs supports (#92883)" (#93123)

It is possible that I have done something wrong here but all I did was rewind to before your change and then copy the test in.

@nikic
Copy link
Contributor Author

nikic commented May 23, 2024

@stefanp-ibm Does your LLVM build enable -DLLVM_USE_SANITIZER=Address? Alternatively, invoking opt under valgrind should also show the issue.

Copy link
Contributor

@stefanp-synopsys stefanp-synopsys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stefanp-ibm Does your LLVM build enable -DLLVM_USE_SANITIZER=Address? Alternatively, invoking opt under valgrind should also show the issue.

I was able to add -DLLVM_USE_SANITIZER=Address to the build and get this test to fail as expected. Thank you for fixing this!

LGTM.

@nikic nikic merged commit 9f85bc8 into llvm:main May 27, 2024
3 checks passed
@nikic nikic deleted the ppc-string-pool branch May 27, 2024 06:54
llvmbot pushed a commit to llvmbot/llvm-project that referenced this pull request May 27, 2024
In llvm#88846 I changed this code to use RAUW to perform the replacement
instead of manual updates -- but kept the outer loop, which means we try
to perform RAUW once per user. However, some of the users might be freed
by the RAUW operation, resulting in use-after-free.

The case where this happens is constant users where the replacement
might result in the destruction of the original constant.

Fixes llvm#92991.

(cherry picked from commit 9f85bc8)
llvmbot pushed a commit to llvmbot/llvm-project that referenced this pull request Jun 4, 2024
In llvm#88846 I changed this code to use RAUW to perform the replacement
instead of manual updates -- but kept the outer loop, which means we try
to perform RAUW once per user. However, some of the users might be freed
by the RAUW operation, resulting in use-after-free.

The case where this happens is constant users where the replacement
might result in the destruction of the original constant.

Fixes llvm#92991.

(cherry picked from commit 9f85bc8)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants