[llvm] r197178 - Fix a use-after-free error in GlobalOpt CleanupConstantGlobalUsers

Hal Finkel hfinkel at anl.gov
Fri Dec 13 02:22:42 PST 2013


Chris,

This seems like a low-risk fix, and it is pretty easy to write C code which triggers this (I've only ever seen this either assert or cause a segfault, but I can imagine it miscompiling something with NDEBUG). How do you feel about putting this into the release branch?

 -Hal

----- Original Message -----
> From: "Hal Finkel" <hfinkel at anl.gov>
> To: llvm-commits at cs.uiuc.edu
> Sent: Thursday, December 12, 2013 2:45:24 PM
> Subject: [llvm] r197178 - Fix a use-after-free error in GlobalOpt	CleanupConstantGlobalUsers
> 
> Author: hfinkel
> Date: Thu Dec 12 14:45:24 2013
> New Revision: 197178
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=197178&view=rev
> Log:
> Fix a use-after-free error in GlobalOpt CleanupConstantGlobalUsers
> 
> GlobalOpt's CleanupConstantGlobalUsers function uses a worklist array
> to manage
> constant users to be visited. The pointers in this array need to be
> weak
> handles because when we delete a constant array, we may also be
> holding a
> pointer to one of its elements (or an element of one of its elements
> if we're
> dealing with an array of arrays) in the worklist.
> 
> Fixes PR17347.
> 
> Added:
>     llvm/trunk/test/Transforms/GlobalOpt/array-elem-refs.ll
> Modified:
>     llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
> 
> Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=197178&r1=197177&r2=197178&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Thu Dec 12 14:45:24
> 2013
> @@ -37,6 +37,7 @@
>  #include "llvm/Support/GetElementPtrTypeIterator.h"
>  #include "llvm/Support/MathExtras.h"
>  #include "llvm/Support/raw_ostream.h"
> +#include "llvm/Support/ValueHandle.h"
>  #include "llvm/Target/TargetLibraryInfo.h"
>  #include "llvm/Transforms/Utils/GlobalStatus.h"
>  #include "llvm/Transforms/Utils/ModuleUtils.h"
> @@ -267,9 +268,17 @@ static bool CleanupPointerRootUsers(Glob
>  static bool CleanupConstantGlobalUsers(Value *V, Constant *Init,
>                                         DataLayout *TD,
>                                         TargetLibraryInfo *TLI) {
>    bool Changed = false;
> -  SmallVector<User*, 8> WorkList(V->use_begin(), V->use_end());
> +  // Note that we need to use a weak value handle for the worklist
> items. When
> +  // we delete a constant array, we may also be holding pointer to
> one of its
> +  // elements (or an element of one of its elements if we're dealing
> with an
> +  // array of arrays) in the worklist.
> +  SmallVector<WeakVH, 8> WorkList(V->use_begin(), V->use_end());
>    while (!WorkList.empty()) {
> -    User *U = WorkList.pop_back_val();
> +    Value *UV = WorkList.pop_back_val();
> +    if (!UV)
> +      continue;
> +
> +    User *U = cast<User>(UV);
>  
>      if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
>        if (Init) {
> 
> Added: llvm/trunk/test/Transforms/GlobalOpt/array-elem-refs.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/array-elem-refs.ll?rev=197178&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/GlobalOpt/array-elem-refs.ll (added)
> +++ llvm/trunk/test/Transforms/GlobalOpt/array-elem-refs.ll Thu Dec
> 12 14:45:24 2013
> @@ -0,0 +1,32 @@
> +; RUN: opt < %s -S -globalopt | FileCheck %s
> +target datalayout =
> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
> +target triple = "x86_64-unknown-linux-gnu"
> +
> +%struct.S = type { i8, i8 }
> +
> + at c = internal global i8** bitcast (i8* getelementptr (i8* bitcast
> ([8 x i8*]* @b to i8*), i64 48) to i8**), align 8
> + at b = internal global [8 x i8*] [i8* null, i8* null, i8* null, i8*
> null, i8* null, i8* null, i8* getelementptr inbounds (%struct.S* @a,
> i32 0, i32 0), i8* getelementptr (i8* getelementptr inbounds
> (%struct.S* @a, i32 0, i32 0), i64 1)], align 16
> + at a = internal global %struct.S zeroinitializer, align 1
> +
> +; Function Attrs: nounwind uwtable
> +define signext i8 @foo() #0 {
> +entry:
> +  %0 = load i8*** @c, align 8
> +  %1 = load i8** %0, align 8
> +  %2 = load i8* %1, align 1
> +  ret i8 %2
> +
> +; CHECK-LABEL: @foo
> +; CHECK: ret i8 0
> +}
> +
> +; Function Attrs: nounwind uwtable
> +define i32 @main() #0 {
> +entry:
> +  %retval = alloca i32, align 4
> +  store i32 0, i32* %retval
> +  ret i32 0
> +}
> +
> +attributes #0 = { nounwind uwtable }
> +
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> 

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory



More information about the llvm-commits mailing list