[PATCH] D103051: [IR] Allow Value::replaceUsesWithIf() to process constants
Eli Friedman via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 28 13:10:07 PDT 2021
efriedma added inline comments.
================
Comment at: llvm/lib/IR/Value.cpp:543
+ Use &U = *UI;
+ ++UI;
+ if (!ShouldReplace(U))
----------------
rampitec wrote:
> efriedma wrote:
> > I'm suspicious of the way you're iterating over the use list here; incrementing early isn't enough to avoid a use-after-free, I think. The incremented `UI` might refer to the same constant.
> >
> > `doRAUW` repeatedly accesses `*use_begin()` to avoid issues.
> I do not think this is currently exploitable as the only caller with constants `convertConstantExprsToInstructions()` guards it, but this may be true in general. Since not all uses are going to be replaced I cannot do the same thing as `doRAUW`. Do you think this will resolve the potential issue?
>
> ```
> @@ -527,22 +527,26 @@ void Value::replaceNonMetadataUsesWith(Value *New) {
>
> void Value::replaceUsesWithIf(Value *New,
> llvm::function_ref<bool(Use &U)> ShouldReplace) {
> assert(New && "Value::replaceUsesWithIf(<null>) is invalid!");
> assert(New->getType() == getType() &&
> "replaceUses of value with new value of different type!");
>
> + SmallPtrSet<Constant *, 8> Visited;
> for (use_iterator UI = use_begin(), E = use_end(); UI != E;) {
> Use &U = *UI;
> ++UI;
> + auto *C = dyn_cast<Constant>(U.getUser());
> + if (C && !Visited.insert(C).second)
> + continue;
> if (!ShouldReplace(U))
> continue;
> // Must handle Constants specially, we cannot call replaceUsesOfWith on a
> // constant because they are uniqued.
> - if (auto *C = dyn_cast<Constant>(U.getUser())) {
> + if (C) {
> if (!isa<GlobalValue>(C)) {
> C->handleOperandChange(this, New);
> continue;
> }
> }
> U.set(New);
> }
> ```
I don't think that's quite right. The problem is ensuring that UI points to something valid when we execute the `++UI`. Adding a "continue" after that doesn't really help.
The most straightforward solution I can think of is to dodge the issue by not calling handleOperandChange with an active use_iterator. Instead, we collect all the constant users into a vector of TrackingVH, then iterate over that.
Also, minor related issue: handleOperandChange updates all the uses in a given Constant, not just the one passed to ShouldReplace.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D103051/new/
https://reviews.llvm.org/D103051
More information about the llvm-commits
mailing list