[PATCH] D103051: [IR] Allow Value::replaceUsesWithIf() to process constants
Stanislav Mekhanoshin via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 28 13:50:30 PDT 2021
rampitec marked an inline comment as done.
rampitec added inline comments.
================
Comment at: llvm/lib/IR/Value.cpp:543
+ Use &U = *UI;
+ ++UI;
+ if (!ShouldReplace(U))
----------------
efriedma wrote:
> 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.
Thanks! A good idea, here is the patch: D105061
For the handleOperandChange() I have left a FIXME for now in the same review. This is a very good point, although not essential for the current use.
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