[cfe-dev] How to access SVal of SubExpr with LocationContext

Jordan Rose jordan_rose at apple.com
Tue Feb 18 09:04:57 PST 2014


Hi, Per. Yeah, what you're trying to do isn't directly supported. The structure that maps from statements (Stmt*) to values (SVal) is called the Environment, and it very deliberately only holds values necessary to compute the next expression. For example, in the expression "(x + y) + z", the value for the subexpression "x + y" is live when trying to evaluate the whole thing, as is "z", but "x" and "y" have already been consumed and so have been taken out of the map to save memory.

What you should actually do here is load the value stored in 'par'. That will look something like this:

SVal ArgVal = Call.getArgSVal(0); // "par"
const MemRegion *MR = ArgVal.getAsRegion();
if (!MR)
  return;
SVal DerefVal = State->getSVal(MR); // "*par"

And now you can check if DerefVal is uninitialized. (Another advantage of this code is that it's also correct for a reference argument.)

By the way, this is a good idea for a check. Thanks for working on it!
Jordan


On Feb 17, 2014, at 9:58 , Per Viberg <Per.Viberg at evidente.se> wrote:

> Hi, 
> 
> I was wondering if there is a way to get SVal of a SubExpr with 
> the LocationContext at a function call. 
> 
> Here is what I mean:
> 
> A function fun is declared and called like this:
> 
> Type arg; //1.
> fun(Type* par){...} //2.
> fun(&arg); //3.
> 
> 
> If I wanted to detect if arg was uninitialized when the function fun is called (line 3.), I would use: 
> 
> const CallEvent Call;
> CheckerContext C;
> Expr* argExp = Call.getArgExpr(0);
> ProgramStateRef state = C.getState(); 
> const LocationContext *LCtx = C.getLocationContext();
> SVal LV = state->getSVal(argExp, LCtx);
> bool FirstArgIsUndef = LV.isUndef();
> 
> FirstArgIsUndef will be false, because the address of  arg does exist.
> 
> But now I want to detect if that which arg/par is pointing at is uninitialized, how would I do that?.
> 
> 
> I started experimenting with this in CallAndMessageChecker::checkPreCall:
> 
> const Expr* argExp = Call.getArgExpr(i);
> const Expr* argExpPure = argExp->IgnoreImpCasts();
> 
> if(const UnaryOperator* unOp = dyn_cast<UnaryOperator>(argExpPure))
> {
>    UnaryOperator::Opcode opc = unOp->getOpcode();
>    if(opc == UO_AddrOf)// '&' operator
>    {
>       Expr* referencedInputArg = unOp->getSubExpr(); // in a dump() I see that this is really the argument arg (not par)
>       SVal refVal = state->getSVal(referencedInputArg, LCtx);
>       bool unknownRefVal = refVal.isUnknown();
>       bool validRefVal = refVal.isValid();
>       bool undefRefVal = refVal.isUndef();
>    }
> }
> 
> it turns out that it will set refVal to isUnknown() instead of isUndef(). The context LCtx seems to forget that the SubExpr  (that is here 
> arg) is uninitialized. I put this code in the CallAndMessageChecker::checkPreCall, perhaps this is the wrong place? or do I need to use the LCtx in another way so that it remembers the SVal of SubExpr too?.
> 
> 
> /Per
> 
> .......................................................................................................................
> Per Viberg Senior Engineer
> Evidente ES East AB  Warfvinges väg 34  SE-112 51 Stockholm  Sweden
> Phone:    +46 (0)8 402 79 00
> Mobile:    +46 (0)70 912 42 52
> E-mail:     Per.Viberg at evidente.se 
> 
> www.evidente.se
> This e-mail, which might contain confidential information, is addressed to the above stated person/company. If you are not the correct addressee, employee or in any other way the person concerned, please notify the sender immediately. At the same time, please delete this e-mail and destroy any prints. Thank You.
> Från: Per Viberg
> Skickat: den 14 februari 2014 13:41
> Till: Clang Dev ‎[cfe-dev at cs.uiuc.edu]‎
> Ämne: improving detection of uninitialized arguments (the CallAndMessageChecker)
> 
> 
> Hi,
> 
> I'm looking into extending the check that warns for uninitialized arguments. Below I've described what should be detected. Any opinions on if it's a useful check or potential problems/drawbacks with it?.
> 
> Check: should this be detected as a warning for uninitialized argument?:"warning: Function call argument is an uninitialized value"
> 
> void doStuff(const int *p);
> void f(void);
> 
> void f(void) {
>       int x;
>       doStuff(&x);  // ← warning?
> }
> 
> My rationale behind the warning:
> 1. it's not possible to write to *p, because it's of type const
> 2. content of *p is uninitialized stack value, and shouldn't be used.
> 3. the value of p is of no interest, since it's an address of an stack variable.
> 
> if any of the above criteria are not fulfilled, then no warning. Thus the function prototype must state pointer to const for the argument, the variable that the function is called with must be address of local/stack variable.
> 
> currently, only this is detected:
> 
> void doStuff2(int p);
> void g(void);
> 
> void g(void) {
>       int y;
>       doStuff2(y);  // warning: Function call argument is an uninitialized value
> 
> 
> /Per
> 
> 
> 
> .......................................................................................................................
> Per Viberg Senior Engineer
> Evidente ES East AB  Warfvinges väg 34  SE-112 51 Stockholm  Sweden
> Phone:    +46 (0)8 402 79 00
> Mobile:    +46 (0)70 912 42 52
> E-mail:     Per.Viberg at evidente.se 
> 
> www.evidente.se
> This e-mail, which might contain confidential information, is addressed to the above stated person/company. If you are not the correct addressee, employee or in any other way the person concerned, please notify the sender immediately. At the same time, please delete this e-mail and destroy any prints. Thank You.
> 
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140218/d31a681e/attachment.html>


More information about the cfe-dev mailing list