Re: [PATCH] Division by zero

2014-09-23 Thread Anna Zaks

 On Sep 15, 2014, at 1:59 AM, Anders Rönnholm anders.ronnh...@evidente.se 
 wrote:
 
 Hi,
 
 I feel that to change this checker and the null dereference check would take 
 a large amount of time compared to what is gained, time which could be used 
 more efficiently on other checkers.
 The null dereference check is already completed as path sensitive and works 
 well.
 
 We are talking about converting only the check after division/dereference 
 (not regular div by zero or dereference checks) because these checks require 
 all paths reasoning (See the [cfe-dev] [RFC] Creating base class for 'Test 
 after X' checkers thread). The main win is speed (flow sensitive analyzes 
 are algorithmically much simpler than the path sensitive ones), which also 
 opens a possibility of converting this into a compiler warning.
 
 I agree that it would not be a very easy task, but this is the right way to 
 approach the problem.
 
 I agree with Anna. Doing this because it's convenient is really just 
 technical debt and isn't something we'd necessarily be comfortable moving 
 out of the alpha package, meaning that plenty of users won't even know it 
 exists. I can see us very easily never coming back to do the right thing 
 here.
 
 Jordan
 
 We still need to know more of how to do the right thing. Can you help us 
 more on how to do it cfg-based? Do we need to create our own LiveVariables 
 class for our checkers and then observe it like DeadStoresChecker observes 
 LiveVariables? 
 

Consuming the result of data flow analysis in a checker is a good approach for 
producing static analyzer warnings. I can think of one reason that might need 
to change; specifically, if the analysis is cheap enough to turn it into a 
warning. It is hard to say if that will be the case ahead of time.

Anna.

 //Anders


___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-09-15 Thread Anders Rönnholm
Hi,

I feel that to change this checker and the null dereference check would take a 
large amount of time compared to what is gained, time which could be used more 
efficiently on other checkers.
The null dereference check is already completed as path sensitive and works 
well.

We are talking about converting only the check after division/dereference 
(not regular div by zero or dereference checks) because these checks require 
all paths reasoning (See the [cfe-dev] [RFC] Creating base class for 'Test 
after X' checkers thread). The main win is speed (flow sensitive analyzes 
are algorithmically much simpler than the path sensitive ones), which also 
opens a possibility of converting this into a compiler warning.

I agree that it would not be a very easy task, but this is the right way to 
approach the problem.

I agree with Anna. Doing this because it's convenient is really just technical 
debt and isn't something we'd necessarily be comfortable moving out of the 
alpha package, meaning that plenty of users won't even know it exists. I can 
see us very easily never coming back to do the right thing here.

Jordan

We still need to know more of how to do the right thing. Can you help us more 
on how to do it cfg-based? Do we need to create our own LiveVariables class for 
our checkers and then observe it like DeadStoresChecker observes LiveVariables? 

//Anders
___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-09-08 Thread Anders Rönnholm

I feel that to change this checker and the null dereference check would take a 
large amount of time compared to what is gained, time which could be used more 
efficiently on other checkers.
The null dereference check is already completed as path sensitive and works 
well.

We are talking about converting only the check after division/dereference 
(not regular div by zero or dereference checks) because these checks require 
all paths reasoning (See the [cfe-dev] [RFC] Creating base class for 'Test 
after X' checkers thread). The main win is speed (flow sensitive analyzes are 
algorithmically much simpler than the path sensitive ones), which also opens 
a possibility of converting this into a compiler warning.


I don't mean the regular dereference but the new dereference then check 
checker. We have it completed but haven't sent the patch due to this change 
that you propose. We simply suggest that we submit this check now as it's 
completed and working rather well and we currently don't have time to redo it.

I agree that it would not be a very easy task, but this is the right way to 
approach the problem.

I don't know when we can deliver this as CFG-based (definitely not this year), 
 wouldn't it be better to have it like this now?

For a possible remake of this checker to a CFG-based one in the future, we 
would need more help from you on how to make them CFG-based. What parts of 
LiveVariables and DeadStoresChecker are related to our check? I guess just 
parts of the LiveVariables framework is needed.

DeadStoresChecker is an example of other flow sensitive checks. You would need 
to create a similar one for div by zero / dereference.


Yes i know that DeadStoresChecker is an example of a flow sensitive check. It 
seems like it uses LiveVariables and only reacts to what happens there. Do we 
need to create our own LiveVariables framework for our checkers and then 
observe it like DeadStoresChecker observes LiveVariables?

Thanks,
Anders
___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-09-08 Thread Jordan Rose

On Sep 5, 2014, at 10:03 , Anna Zaks ga...@apple.com wrote:

 
 On Sep 5, 2014, at 5:24 AM, Anders Rönnholm anders.ronnh...@evidente.se 
 wrote:
 
 Hi,
 
 I feel that to change this checker and the null dereference check would take 
 a large amount of time compared to what is gained, time which could be used 
 more efficiently on other checkers.
 The null dereference check is already completed as path sensitive and works 
 well.
 
 We are talking about converting only the check after division/dereference 
 (not regular div by zero or dereference checks) because these checks require 
 all paths reasoning (See the [cfe-dev] [RFC] Creating base class for 'Test 
 after X' checkers thread). The main win is speed (flow sensitive analyzes 
 are algorithmically much simpler than the path sensitive ones), which also 
 opens a possibility of converting this into a compiler warning.
 
 I agree that it would not be a very easy task, but this is the right way to 
 approach the problem.

I agree with Anna. Doing this because it's convenient is really just technical 
debt and isn't something we'd necessarily be comfortable moving out of the 
alpha package, meaning that plenty of users won't even know it exists. I can 
see us very easily never coming back to do the right thing here.

Jordan___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


RE: [PATCH] Division by zero

2014-09-05 Thread Anders Rönnholm
Hi,

I feel that to change this checker and the null dereference check would take a 
large amount of time compared to what is gained, time which could be used more 
efficiently on other checkers.
The null dereference check is already completed as path sensitive and works 
well. I don't know when we can deliver this as CFG-based (definitely not this 
year),  wouldn't it be better to have it like this now?

For a possible remake of this checker to a CFG-based one in the future, we 
would need more help from you on how to make them CFG-based. What parts of 
LiveVariables and DeadStoresChecker are related to our check? I guess just 
parts of the LiveVariables framework is needed.

So, Anna brought up that the check as implemented is very nearly 
path-independent, i.e. it only depends on flow-sensitive properties of the 
CFG. The path-sensitivity is buying us very little; it catches this case:

int y = x;
int div = z / y;
if (x) { ...}

But also warns here, which doesn't necessarily make sense:

int foo(int x, int y, int z) {
int div = z / y;
if (x) return div;
return 0;
}

foo(a, a, b); // only coincidentally the same symbol

What would you think about turning this (and/or the null dereference check) 
into a CFG-based check instead? We lose the first example (and cases where 
inlining would help), but fix the second, and very possibly speed up analysis. 
CFG analysis is also more capable of proving that something happens on all 
paths rather than just some, since that's just propagating information along 
the graph.

I agree, this can in theory be a false positive but we believe it is an 
unlikely one. Other existing checkers in the Clang static analyser have the 
same problem. I don't have any proposal, but maybe a generic solution for such 
FP would be good. In the long run I think it would be nice to have full flow 
analysis in this checker so we can find deeper bugs that are not limited to a 
single basic block.

//Anders
___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-09-05 Thread Anna Zaks

 On Sep 5, 2014, at 5:24 AM, Anders Rönnholm anders.ronnh...@evidente.se 
 wrote:
 
 Hi,
 
 I feel that to change this checker and the null dereference check would take 
 a large amount of time compared to what is gained, time which could be used 
 more efficiently on other checkers.
 The null dereference check is already completed as path sensitive and works 
 well.

We are talking about converting only the check after division/dereference 
(not regular div by zero or dereference checks) because these checks require 
all paths reasoning (See the [cfe-dev] [RFC] Creating base class for 'Test 
after X' checkers thread). The main win is speed (flow sensitive analyzes are 
algorithmically much simpler than the path sensitive ones), which also opens a 
possibility of converting this into a compiler warning.

I agree that it would not be a very easy task, but this is the right way to 
approach the problem.

 I don't know when we can deliver this as CFG-based (definitely not this 
 year),  wouldn't it be better to have it like this now?
 
 For a possible remake of this checker to a CFG-based one in the future, we 
 would need more help from you on how to make them CFG-based. What parts of 
 LiveVariables and DeadStoresChecker are related to our check? I guess just 
 parts of the LiveVariables framework is needed.

DeadStoresChecker is an example of other flow sensitive checks. You would need 
to create a similar one for div by zero / dereference. 

 
 So, Anna brought up that the check as implemented is very nearly 
 path-independent, i.e. it only depends on flow-sensitive properties of the 
 CFG. The path-sensitivity is buying us very little; it catches this case:
 
 int y = x;
 int div = z / y;
 if (x) { ...}
 
 But also warns here, which doesn't necessarily make sense:
 
 int foo(int x, int y, int z) {
   int div = z / y;
   if (x) return div;
   return 0;
 }
 
 foo(a, a, b); // only coincidentally the same symbol
 
 What would you think about turning this (and/or the null dereference check) 
 into a CFG-based check instead? We lose the first example (and cases where 
 inlining would help), but fix the second, and very possibly speed up 
 analysis. CFG analysis is also more capable of proving that something 
 happens on all paths rather than just some, since that's just propagating 
 information along the graph.
 
 I agree, this can in theory be a false positive but we believe it is an 
 unlikely one. Other existing checkers in the Clang static analyser have the 
 same problem. I don't have any proposal, but maybe a generic solution for 
 such FP would be good. In the long run I think it would be nice to have full 
 flow analysis in this checker so we can find deeper bugs that are not limited 
 to a single basic block.
 

Again, the main issue is the algorithmic performance win, not false positives.

 //Anders

___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


RE: [PATCH] Division by zero

2014-08-12 Thread Anders Rönnholm
Hi Jordan,

I don't know if I have the time to change division by zero right away but I can 
make the dereference check CFG-based. Do you have an example of a CFG-based 
checker? I don't know how to make those.

//Anders

From: Jordan Rose [mailto:jordan_r...@apple.com]
Sent: den 21 juli 2014 19:40
To: Anders Rönnholm
Cc: cfe-commits@cs.uiuc.edu; Daniel Marjamäki; Anna Zaks
Subject: Re: [PATCH] Division by zero

So, Anna brought up that the check as implemented is very nearly 
path-independent, i.e. it only depends on flow-sensitive properties of the CFG. 
The path-sensitivity is buying us very little; it catches this case:

int y = x;
int div = z / y;
if (x) { ...}

But also warns here, which doesn't necessarily make sense:

int foo(int x, int y, int z) {
int div = z / y;
if (x) return div;
return 0;
}

foo(a, a, b); // only coincidentally the same symbol

What would you think about turning this (and/or the null dereference check) 
into a CFG-based check instead? We lose the first example (and cases where 
inlining would help), but fix the second, and very possibly speed up analysis. 
CFG analysis is also more capable of proving that something happens on all 
paths rather than just some, since that's just propagating information along 
the graph.

Jordan


On Jul 10, 2014, at 9:55 , Anders Rönnholm 
anders.ronnh...@evidente.semailto:anders.ronnh...@evidente.se wrote:


Great, no problem. I'll move forward with my dereference then check patch now 
that this one is commited, which will be pretty similar.

//Anders

...
Anders Rönnholm Senior Engineer
Evidente ES East AB  Warfvinges väg 34  SE-112 51 Stockholm  Sweden

Mobile:+46 (0)70 912 42 54
E-mail:
anders.ronnh...@evidente.semailto:anders.ronnh...@evidente.se

www.evidente.sehttp://www.evidente.se


Från: Jordan Rose [jordan_r...@apple.com]
Skickat: den 10 juli 2014 18:20
Till: Anders Rönnholm
Cc: cfe-commits@cs.uiuc.edumailto:cfe-commits@cs.uiuc.edu; Daniel Marjamäki
Ämne: Re: [PATCH] Division by zero

Thank you for going through so many rounds of review on this. Committed in 
r212731! (The one change I made was to reset the test in isZero to use assume 
instead of assumeDual, now that my confusion has been fixed.)

Jordan

___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-08-12 Thread Ted Kremenek
The dead stores checker is an example of a CFG-based check.  That checker rides 
on top of the live variables analysis (which is CFG-based), so really the guts 
of the analysis of the checker are there.  The analysis for -Wuninitialized is 
also dataflow-based, although that is a compiler warning instead of a checker, 
but it works exactly the same way.

Essentially you do a dataflow analysis to collect possible facts at each basic 
block, propagating facts forward as you analyze the statements of a basic 
block.  You then merge values at confluence points, which are the basic 
blocks with multiple predecessors.  That merging is what makes the analysis 
path-insensitive, but flow-sensitive.  Path-insensitive analyses are 
dramatically faster, but for many of the properties the static analyzer looks 
for they are too imprecise.  For this checker it may be the case you don't need 
path-sensitivity, which is why Jordan suggested it.  If it can be implemented 
as path-insensitive, it then has the possible chance of becoming a compiler 
warning one day.

 On Aug 11, 2014, at 11:58 PM, Anders Rönnholm anders.ronnh...@evidente.se 
 wrote:
 
 Hi Jordan,
  
 I don’t know if I have the time to change division by zero right away but I 
 can make the dereference check CFG-based. Do you have an example of a 
 CFG-based checker? I don’t know how to make those.
  
 //Anders
  
 From: Jordan Rose [mailto:jordan_r...@apple.com] 
 Sent: den 21 juli 2014 19:40
 To: Anders Rönnholm
 Cc: cfe-commits@cs.uiuc.edu; Daniel Marjamäki; Anna Zaks
 Subject: Re: [PATCH] Division by zero
  
 So, Anna brought up that the check as implemented is very nearly 
 path-independent, i.e. it only depends on flow-sensitive properties of the 
 CFG. The path-sensitivity is buying us very little; it catches this case:
  
 int y = x;
 int div = z / y;
 if (x) { ...}
  
 But also warns here, which doesn't necessarily make sense:
  
 int foo(int x, int y, int z) {
 int div = z / y;
 if (x) return div;
 return 0;
 }
  
 foo(a, a, b); // only coincidentally the same symbol
  
 What would you think about turning this (and/or the null dereference check) 
 into a CFG-based check instead? We lose the first example (and cases where 
 inlining would help), but fix the second, and very possibly speed up 
 analysis. CFG analysis is also more capable of proving that something happens 
 on all paths rather than just some, since that's just propagating information 
 along the graph.
  
 Jordan
  
  
 On Jul 10, 2014, at 9:55 , Anders Rönnholm anders.ronnh...@evidente.se 
 mailto:anders.ronnh...@evidente.se wrote:
 
 
 Great, no problem. I'll move forward with my dereference then check patch now 
 that this one is commited, which will be pretty similar.
 
 //Anders
 
 ...
 Anders Rönnholm Senior Engineer
 Evidente ES East AB  Warfvinges väg 34  SE-112 51 Stockholm  Sweden
 
 Mobile:+46 (0)70 912 42 54
 E-mail:anders.ronnh...@evidente.se 
 mailto:anders.ronnh...@evidente.se
 
 www.evidente.se http://www.evidente.se/
 
 
 Från: Jordan Rose [jordan_r...@apple.com]
 Skickat: den 10 juli 2014 18:20
 Till: Anders Rönnholm
 Cc: cfe-commits@cs.uiuc.edu mailto:cfe-commits@cs.uiuc.edu; Daniel Marjamäki
 Ämne: Re: [PATCH] Division by zero
 
 Thank you for going through so many rounds of review on this. Committed in 
 r212731! (The one change I made was to reset the test in isZero to use assume 
 instead of assumeDual, now that my confusion has been fixed.)
 
 Jordan
  
 ___
 cfe-commits mailing list
 cfe-commits@cs.uiuc.edu
 http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-07-21 Thread Jordan Rose
So, Anna brought up that the check as implemented is very nearly 
path-independent, i.e. it only depends on flow-sensitive properties of the CFG. 
The path-sensitivity is buying us very little; it catches this case:

 int y = x;
 int div = z / y;
 if (x) { ...}

But also warns here, which doesn't necessarily make sense:

 int foo(int x, int y, int z) {
   int div = z / y;
   if (x) return div;
   return 0;
 }
 
 foo(a, a, b); // only coincidentally the same symbol

What would you think about turning this (and/or the null dereference check) 
into a CFG-based check instead? We lose the first example (and cases where 
inlining would help), but fix the second, and very possibly speed up analysis. 
CFG analysis is also more capable of proving that something happens on all 
paths rather than just some, since that's just propagating information along 
the graph.

Jordan


On Jul 10, 2014, at 9:55 , Anders Rönnholm anders.ronnh...@evidente.se wrote:

 Great, no problem. I'll move forward with my dereference then check patch now 
 that this one is commited, which will be pretty similar.
 
 //Anders
 
 ...
 Anders Rönnholm Senior Engineer
 Evidente ES East AB  Warfvinges väg 34  SE-112 51 Stockholm  Sweden
 
 Mobile:+46 (0)70 912 42 54
 E-mail:anders.ronnh...@evidente.se
 
 www.evidente.se
 
 
 Från: Jordan Rose [jordan_r...@apple.com]
 Skickat: den 10 juli 2014 18:20
 Till: Anders Rönnholm
 Cc: cfe-commits@cs.uiuc.edu; Daniel Marjamäki
 Ämne: Re: [PATCH] Division by zero
 
 Thank you for going through so many rounds of review on this. Committed in 
 r212731! (The one change I made was to reset the test in isZero to use assume 
 instead of assumeDual, now that my confusion has been fixed.)
 
 Jordan

___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-07-10 Thread Jordan Rose
Thank you for going through so many rounds of review on this. Committed in 
r212731! (The one change I made was to reset the test in isZero to use assume 
instead of assumeDual, now that my confusion has been fixed.)

Jordan
___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-07-10 Thread Anders Rönnholm
Great, no problem. I'll move forward with my dereference then check patch now 
that this one is commited, which will be pretty similar.

//Anders

...
Anders Rönnholm Senior Engineer
Evidente ES East AB  Warfvinges väg 34  SE-112 51 Stockholm  Sweden

Mobile:+46 (0)70 912 42 54
E-mail:anders.ronnh...@evidente.se

www.evidente.se


Från: Jordan Rose [jordan_r...@apple.com]
Skickat: den 10 juli 2014 18:20
Till: Anders Rönnholm
Cc: cfe-commits@cs.uiuc.edu; Daniel Marjamäki
Ämne: Re: [PATCH] Division by zero

Thank you for going through so many rounds of review on this. Committed in 
r212731! (The one change I made was to reset the test in isZero to use assume 
instead of assumeDual, now that my confusion has been fixed.)

Jordan

___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-07-09 Thread Anders Rönnholm

We don't get into the if-case because we never get a Loc from Sval therefore it 
always returns false and our tests are passed.

OptionalLoc L = S.getAsLoc();
if (!L)
  return false;

Um. Right, we shouldn't get a Loc at that point. But we don't need a Loc. We 
just need whatever NonLoc symbol is there, and we can check to see if that is 
0. Why did we need a Loc again?

Anyway, we shouldn't have features that don't show up in the tests. I think 
this code was either trying to avoid emitting duplicate messages if the 
denominator is known to be 0 already (which won't happen because that's a fatal 
error), or trying to avoid adding the symbol to the map if it's known not to be 
0 (which is not what it's doing now, or at least not what it says it's doing). 
The latter is kind of useful but it's just optimization.

Jordan

Are you suggesting that we use NonLoc instead of Loc? Can we get an Sval from 
NonLoc? We needed Loc to get sval from state instead of looping the exploded 
node to find the range before the division.

Let's stop for a second. We want to check if the denominator's value is equal 
to 0. At this point in execution, the denominator expression is an rvalue, i.e. 
the integer value has already been loaded from the variable. That means the 
value of the denominator expression is going to be a NonLoc (because it 
represents an integer value rather than a location). Additionally, we don't 
need to load anything, because we're already past the point in analysis where 
the variable is loaded.

So if I'm right, you should be able to just take the denominator SVal as is, 
and feed it into the constraint manager if it's defined.

Jordan


Yes it seems like we can do that, don't know why it was a problem previously 
(before we began looping the exploded node) because this was what we did.

I have made a new patch now.

//Anders
Index: lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp	(revision 0)
+++ lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp	(revision 0)
@@ -0,0 +1,271 @@
+//== TestAfterDivZeroChecker.cpp - Test after division by zero checker --*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// This defines TestAfterDivZeroChecker, a builtin check that performs checks
+//  for division by zero where the division occurs before comparison with zero.
+//
+//===--===//
+
+#include ClangSACheckers.h
+#include clang/StaticAnalyzer/Core/BugReporter/BugType.h
+#include clang/StaticAnalyzer/Core/Checker.h
+#include clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+#include clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+#include llvm/ADT/FoldingSet.h
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class ZeroState {
+private:
+  SymbolRef ZeroSymbol;
+  unsigned BlockID;
+  const StackFrameContext *SFC;
+
+public:
+  ZeroState(SymbolRef S, unsigned B, const StackFrameContext *SFC)
+  : ZeroSymbol(S), BlockID(B), SFC(SFC) {}
+
+  const StackFrameContext *getStackFrameContext() const { return SFC; }
+
+  bool operator==(const ZeroState X) const {
+return BlockID == X.BlockID  SFC == X.SFC  ZeroSymbol == X.ZeroSymbol;
+  }
+
+  bool operator(const ZeroState X) const {
+if (BlockID != X.BlockID)
+  return BlockID  X.BlockID;
+if (SFC != X.SFC)
+  return SFC  X.SFC;
+return ZeroSymbol  X.ZeroSymbol;
+  }
+
+  void Profile(llvm::FoldingSetNodeID ID) const {
+ID.AddInteger(BlockID);
+ID.AddPointer(SFC);
+ID.AddPointer(ZeroSymbol);
+  }
+};
+
+class DivisionBRVisitor : public BugReporterVisitorImplDivisionBRVisitor {
+private:
+  SymbolRef ZeroSymbol;
+  const StackFrameContext *SFC;
+  bool Satisfied = false;
+
+public:
+  DivisionBRVisitor(SymbolRef ZeroSymbol, const StackFrameContext *SFC)
+  : ZeroSymbol(ZeroSymbol), SFC(SFC) {}
+
+  void Profile(llvm::FoldingSetNodeID ID) const override {
+ID.Add(ZeroSymbol);
+ID.Add(SFC);
+  }
+
+  PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ,
+ const ExplodedNode *Pred,
+ BugReporterContext BRC,
+ BugReport BR) override;
+};
+
+class TestAfterDivZeroChecker
+: public Checkercheck::PreStmtBinaryOperator, check::BranchCondition,
+ check::EndFunction {
+  mutable std::unique_ptrBuiltinBug DivZeroBug;
+  void reportBug(SVal Val, CheckerContext C) const;
+
+public:
+  void checkPreStmt(const BinaryOperator *B, CheckerContext C) const;
+  void checkBranchCondition(const Stmt *Condition, CheckerContext C) const;
+  void 

Re: [PATCH] Division by zero

2014-07-08 Thread Jordan Rose

On Jul 7, 2014, at 2:28 , Anders Rönnholm anders.ronnh...@evidente.se wrote:

 We don't get into the if-case because we never get a Loc from Sval 
 therefore it always returns false and our tests are passed.
 
 OptionalLoc L = S.getAsLoc();
 if (!L)
   return false;
 
 Um. Right, we shouldn't get a Loc at that point. But we don't need a Loc. We 
 just need whatever NonLoc symbol is there, and we can check to see if that 
 is 0. Why did we need a Loc again?
 
 Anyway, we shouldn't have features that don't show up in the tests. I think 
 this code was either trying to avoid emitting duplicate messages if the 
 denominator is known to be 0 already (which won't happen because that's a 
 fatal error), or trying to avoid adding the symbol to the map if it's known 
 not to be 0 (which is not what it's doing now, or at least not what it says 
 it's doing). The latter is kind of useful but it's just optimization.
 
 Jordan
 
 Are you suggesting that we use NonLoc instead of Loc? Can we get an Sval from 
 NonLoc? We needed Loc to get sval from state instead of looping the exploded 
 node to find the range before the division.

Let's stop for a second. We want to check if the denominator's value is equal 
to 0. At this point in execution, the denominator expression is an rvalue, i.e. 
the integer value has already been loaded from the variable. That means the 
value of the denominator expression is going to be a NonLoc (because it 
represents an integer value rather than a location). Additionally, we don't 
need to load anything, because we're already past the point in analysis where 
the variable is loaded.

So if I'm right, you should be able to just take the denominator SVal as is, 
and feed it into the constraint manager if it's defined.

Jordan___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-07-07 Thread Anders Rönnholm

Huh. So, I changed it back to the way it was:

SVal Val = State-getRawSVal(*L);
if (Val == S) {
OptionalDefinedSVal DSV = Val.getAsDefinedSVal();
  ConstraintManager CM = C.getConstraintManager();
  if (!CM.assume(State, *DSV, false))
return true;
}

and tried running the tests. No failures. Then I flipped the false to true 
in the assume...and still no failures. So we must never be getting into that 
if-case!

What would that affect?

Jordan


We don't get into the if-case because we never get a Loc from Sval therefore it 
always returns false and our tests are passed.

OptionalLoc L = S.getAsLoc();
 if (!L)
   return false;

Um. Right, we shouldn't get a Loc at that point. But we don't need a Loc. We 
just need whatever NonLoc symbol is there, and we can check to see if that is 
0. Why did we need a Loc again?

Anyway, we shouldn't have features that don't show up in the tests. I think 
this code was either trying to avoid emitting duplicate messages if the 
denominator is known to be 0 already (which won't happen because that's a fatal 
error), or trying to avoid adding the symbol to the map if it's known not to be 
0 (which is not what it's doing now, or at least not what it says it's doing). 
The latter is kind of useful but it's just optimization.

Jordan

Are you suggesting that we use NonLoc instead of Loc? Can we get an Sval from 
NonLoc? We needed Loc to get sval from state instead of looping the exploded 
node to find the range before the division.

Or should we remove the isZero check? We reason we have this is the latter, 
avoid adding the symbol to the map if it's known not to be 0.

//Anders
___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-07-05 Thread Jordan Rose

On Jul 4, 2014, at 1:15 , Anders Rönnholm anders.ronnh...@evidente.se wrote:

 Huh. So, I changed it back to the way it was:
 
 SVal Val = State-getRawSVal(*L);
 if (Val == S) {
 OptionalDefinedSVal DSV = Val.getAsDefinedSVal();
   ConstraintManager CM = C.getConstraintManager();
   if (!CM.assume(State, *DSV, false))
 return true;
 }
 
 and tried running the tests. No failures. Then I flipped the false to 
 true in the assume...and still no failures. So we must never be getting 
 into that if-case!
 
 What would that affect?
 
 Jordan
 
 
 We don't get into the if-case because we never get a Loc from Sval therefore 
 it always returns false and our tests are passed.
 
 OptionalLoc L = S.getAsLoc();
  if (!L)
return false;

Um. Right, we shouldn't get a Loc at that point. But we don't need a Loc. We 
just need whatever NonLoc symbol is there, and we can check to see if that is 
0. Why did we need a Loc again?

Anyway, we shouldn't have features that don't show up in the tests. I think 
this code was either trying to avoid emitting duplicate messages if the 
denominator is known to be 0 already (which won't happen because that's a fatal 
error), or trying to avoid adding the symbol to the map if it's known not to be 
0 (which is not what it's doing now, or at least not what it says it's doing). 
The latter is kind of useful but it's just optimization.

Jordan

___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-07-04 Thread Anders Rönnholm
 Huh. So, I changed it back to the way it was:
 
  SVal Val = State-getRawSVal(*L);
 if (Val == S) {
  OptionalDefinedSVal DSV = Val.getAsDefinedSVal();
ConstraintManager CM = C.getConstraintManager();
if (!CM.assume(State, *DSV, false))
  return true;
  }

and tried running the tests. No failures. Then I flipped the false to true 
in the assume...and still no failures. So we must never be getting into that 
if-case!

What would that affect?

Jordan


We don't get into the if-case because we never get a Loc from Sval therefore it 
always returns false and our tests are passed.

OptionalLoc L = S.getAsLoc();
  if (!L)
return false;


Should we go back to how it was previously and walk backwards on the exploded 
node or do you have a better idea? Or leave it as it is? How can i write a test 
were we actually get a Loc?

bool TestAfterDivZeroChecker::isZero(SVal S, CheckerContext C) const {
  const ExplodedNode *N = C.getPredecessor();
  while (N) {
ProgramStateRef State = N-getState();

if (const MemRegion *MR = C.getLocationRegionIfPostStore(N)) {
  SVal Val = State-getSVal(MR);
  if (Val == S) {
OptionalDefinedSVal DSV = Val.getAsDefinedSVal();
ConstraintManager CM = C.getConstraintManager();
ProgramStateRef stateNotZero, stateZero;
std::tie(stateNotZero, stateZero) = CM.assumeDual(State, *DSV);

if (!stateNotZero) {
  assert(stateZero);
  return true;
}
  }
}
N = N-pred_empty() ? nullptr : *(N-pred_begin());
  }
  return false;
}

//Anders
___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-07-03 Thread Jordan Rose

On Jul 2, 2014, at 5:27 , Anders Rönnholm anders.ronnh...@evidente.se wrote:

 Hi,
 
 New iteration with comments addressed.
 
 I still don't understand why this is a loop at all:
 
 +bool TestAfterDivZeroChecker::isZero(SVal S, CheckerContext C) const {
 +  OptionalLoc L;
 +  if (!(L = S.getAsLoc())) return false;
 +
 +  const ExplodedNode *N = C.getPredecessor();
 +  while (N) {
 +ProgramStateRef State = N-getState();
 +
 +// Find the most recent expression bound to the symbol in the current
 +// context.
 +SVal Val = State-getRawSVal(L.getValue());
 +if (Val == S) {
 +  OptionalDefinedSVal DSV = Val.getAsDefinedSVal();
 +  return !C.getConstraintManager().assume(State, *DSV, false);
 +}
 +N = N-pred_empty() ? nullptr : *(N-pred_begin());
 +  }
 +  return false;
 +}
 
 What's wrong with Val = C.getState()-getRawSVal(*L)?
 
 Sorry, thought I still had to loop, I have removed it now.
 
 
 Also, I'm reading your check as saying that the value is zero if there does 
 not exist a state where DSV is not non-zero. I must be reading something 
 wrong (since you have test cases), but what? Can you explain it to me?
 
 Yes it looks kinda strange. I have changed it slightly to more resemble how 
 DivZeroChecker does it.


Huh. So, I changed it back to the way it was:

  SVal Val = State-getRawSVal(*L);
  if (Val == S) {
OptionalDefinedSVal DSV = Val.getAsDefinedSVal();
ConstraintManager CM = C.getConstraintManager();
if (!CM.assume(State, *DSV, false))
  return true;
  }

and tried running the tests. No failures. Then I flipped the false to true 
in the assume...and still no failures. So we must never be getting into that 
if-case!

What would that affect?
Jordan___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-07-01 Thread Jordan Rose
I still don't understand why this is a loop at all:

+bool TestAfterDivZeroChecker::isZero(SVal S, CheckerContext C) const {
+  OptionalLoc L;
+  if (!(L = S.getAsLoc())) return false;
+
+  const ExplodedNode *N = C.getPredecessor();
+  while (N) {
+ProgramStateRef State = N-getState();
+
+// Find the most recent expression bound to the symbol in the current
+// context.
+SVal Val = State-getRawSVal(L.getValue());
+if (Val == S) {
+  OptionalDefinedSVal DSV = Val.getAsDefinedSVal();
+  return !C.getConstraintManager().assume(State, *DSV, false);
+}
+N = N-pred_empty() ? nullptr : *(N-pred_begin());
+  }
+  return false;
+}

What's wrong with Val = C.getState()-getRawSVal(*L)?

Also, I'm reading your check as saying that the value is zero if there does not 
exist a state where DSV is not non-zero. I must be reading something wrong 
(since you have test cases), but what? Can you explain it to me?

Smaller comments:

+  OptionalLoc L;
+  if (!(L = S.getAsLoc())) return false;

I personally think this is clearer if you put the assignment in with the 
declaration.

+  DivZeroMapTy DivZeroes = State-getDivZeroMap();
+  if (DivZeroes.isEmpty())
+return;
+
+  for (llvm::ImmutableSetZeroState::iterator I = DivZeroes.begin(),
+   E = DivZeroes.end();
+   I != E; ++I) {
+ZeroState ZS = *I;
+if (ZS.getStackFrameContext() == C.getStackFrame())
+  State = State-removeDivZeroMap(ZS);
+  }
+  C.addTransition(State);

I should have mentioned this sooner, but it's more efficient if you use the map 
factory to remove everything first and then generate one new state with the 
final map. See MallocChecker::checkDeadSymbols for an example of how to do this 
(they're using it for RegionState).

Jordan


On Jun 24, 2014, at 6:29 , Anders Rönnholm anders.ronnh...@evidente.se wrote:

 Thanks for your comments. Here's a new patch.
 
 //Anders
 
 
 Från: Jordan Rose [jordan_r...@apple.com]
 Skickat: den 19 juni 2014 18:17
 Till: Anders Rönnholm
 Cc: cfe-commits@cs.uiuc.edu; Daniel Marjamäki
 Ämne: Re: [PATCH] Division by zero
 
 On Jun 18, 2014, at 7:30 , Anders Rönnholm anders.ronnh...@evidente.se 
 wrote:
 
 Changes according to comments.
 
 I'm pretty sure PVS-Studio does not have this checker, this bug has been 
 seen in production code.
 
 
 Oops, noticing more things:
 
 +  const ExplodedNode *N = C.getPredecessor();
 +  while (N) {
 +ProgramStateRef State = N-getState();
 +
 +// Find the most recent expression bound to the symbol in the current
 +// context.
 +if (const MemRegion *MR = C.getLocationRegionIfPostStore(N)) {
 +  SVal Val = State-getSVal(MR);
 +  if (Val == S) {
 +OptionalDefinedSVal DSV = Val.getAsDefinedSVal();
 +if (!C.getConstraintManager().assume(State, *DSV, false))
 +  return true;
 +  }
 +}
 +N = N-pred_empty() ? nullptr : *(N-pred_begin());
 +  }
 
 Why are you looking for the last time a value was stored rather than just 
 asking for the value in the current state?
 
 if (OptionalLoc L = S.getAsLoc()) {
  SVal V = State-getSVal(L) // or getRawSVal if you don't want a symbol 
 constrained to 0 to be simplified to 0.
  // ...
 
 
 +if (OptionalKnownSVal V = Val.getAsKnownSVal()) {
 
 Because you needed a symbol already to get this far, you can skip this step. 
 Or assert it.
 
 
 +void TestAfterDivZeroChecker::checkPreStmt(const BinaryOperator *B,
 +   CheckerContext C) const {
 
 Strange alignment here. If the second line doesn't fit, just indent it twice 
 from the start of the function...don't try to right-align it.
 
 
 +if (!B-getRHS()-getType()-isScalarType())
 +  return;
 
 Dividing by a floating-point 0 is well-defined, so this should be a more 
 specific check.
 
 Jordan
 divzero2.diff

___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-06-24 Thread Anders Rönnholm
Thanks for your comments. Here's a new patch.

//Anders


Från: Jordan Rose [jordan_r...@apple.com]
Skickat: den 19 juni 2014 18:17
Till: Anders Rönnholm
Cc: cfe-commits@cs.uiuc.edu; Daniel Marjamäki
Ämne: Re: [PATCH] Division by zero

On Jun 18, 2014, at 7:30 , Anders Rönnholm anders.ronnh...@evidente.se wrote:

 Changes according to comments.

 I'm pretty sure PVS-Studio does not have this checker, this bug has been seen 
 in production code.


Oops, noticing more things:

+  const ExplodedNode *N = C.getPredecessor();
+  while (N) {
+ProgramStateRef State = N-getState();
+
+// Find the most recent expression bound to the symbol in the current
+// context.
+if (const MemRegion *MR = C.getLocationRegionIfPostStore(N)) {
+  SVal Val = State-getSVal(MR);
+  if (Val == S) {
+OptionalDefinedSVal DSV = Val.getAsDefinedSVal();
+if (!C.getConstraintManager().assume(State, *DSV, false))
+  return true;
+  }
+}
+N = N-pred_empty() ? nullptr : *(N-pred_begin());
+  }

Why are you looking for the last time a value was stored rather than just 
asking for the value in the current state?

if (OptionalLoc L = S.getAsLoc()) {
  SVal V = State-getSVal(L) // or getRawSVal if you don't want a symbol 
constrained to 0 to be simplified to 0.
  // ...


+if (OptionalKnownSVal V = Val.getAsKnownSVal()) {

Because you needed a symbol already to get this far, you can skip this step. Or 
assert it.


+void TestAfterDivZeroChecker::checkPreStmt(const BinaryOperator *B,
+   CheckerContext C) const {

Strange alignment here. If the second line doesn't fit, just indent it twice 
from the start of the function...don't try to right-align it.


+if (!B-getRHS()-getType()-isScalarType())
+  return;

Dividing by a floating-point 0 is well-defined, so this should be a more 
specific check.

Jordan
Index: lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp	(revision 0)
+++ lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp	(revision 0)
@@ -0,0 +1,276 @@
+//== TestAfterDivZeroChecker.cpp - Test after division by zero checker --*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// This defines TestAfterDivZeroChecker, a builtin check that performs checks
+//  for division by zero where the division occurs before comparison with zero.
+//
+//===--===//
+
+#include ClangSACheckers.h
+#include clang/StaticAnalyzer/Core/BugReporter/BugType.h
+#include clang/StaticAnalyzer/Core/Checker.h
+#include clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+#include clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+#include llvm/ADT/FoldingSet.h
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class ZeroState {
+private:
+  SymbolRef ZeroSymbol;
+  unsigned BlockID;
+  const StackFrameContext *SFC;
+
+public:
+  ZeroState(SymbolRef S, unsigned B, const StackFrameContext *SFC)
+  : ZeroSymbol(S), BlockID(B), SFC(SFC) {}
+
+  const StackFrameContext *getStackFrameContext() const { return SFC; }
+
+  bool operator==(const ZeroState X) const {
+return BlockID == X.BlockID  SFC == X.SFC  ZeroSymbol == X.ZeroSymbol;
+  }
+
+  bool operator(const ZeroState X) const {
+if (BlockID != X.BlockID)
+  return BlockID  X.BlockID;
+if (SFC != X.SFC)
+  return SFC  X.SFC;
+return ZeroSymbol  X.ZeroSymbol;
+  }
+
+  void Profile(llvm::FoldingSetNodeID ID) const {
+ID.AddInteger(BlockID);
+ID.AddPointer(SFC);
+ID.AddPointer(ZeroSymbol);
+  }
+};
+
+class DivisionBRVisitor : public BugReporterVisitorImplDivisionBRVisitor {
+private:
+  SymbolRef ZeroSymbol;
+  const StackFrameContext *SFC;
+  bool Satisfied = false;
+
+public:
+  DivisionBRVisitor(SymbolRef ZeroSymbol, const StackFrameContext *SFC)
+  : ZeroSymbol(ZeroSymbol), SFC(SFC) {}
+
+  void Profile(llvm::FoldingSetNodeID ID) const override {
+ID.Add(ZeroSymbol);
+ID.Add(SFC);
+  }
+
+  PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ,
+ const ExplodedNode *Pred,
+ BugReporterContext BRC,
+ BugReport BR) override;
+};
+
+class TestAfterDivZeroChecker
+: public Checkercheck::PreStmtBinaryOperator, check::BranchCondition,
+ check::EndFunction {
+  mutable std::unique_ptrBuiltinBug DivZeroBug;
+  void reportBug(SVal Val, CheckerContext C) const;
+
+public:
+  void checkPreStmt(const BinaryOperator *B, CheckerContext C) const;
+  void

Re: [PATCH] Division by zero

2014-06-19 Thread Jordan Rose

On Jun 18, 2014, at 7:30 , Anders Rönnholm anders.ronnh...@evidente.se wrote:

 Changes according to comments. 
 
 I'm pretty sure PVS-Studio does not have this checker, this bug has been seen 
 in production code.


Oops, noticing more things:

+  const ExplodedNode *N = C.getPredecessor();
+  while (N) {
+ProgramStateRef State = N-getState();
+
+// Find the most recent expression bound to the symbol in the current
+// context.
+if (const MemRegion *MR = C.getLocationRegionIfPostStore(N)) {
+  SVal Val = State-getSVal(MR);
+  if (Val == S) {
+OptionalDefinedSVal DSV = Val.getAsDefinedSVal();
+if (!C.getConstraintManager().assume(State, *DSV, false))
+  return true;
+  }
+}
+N = N-pred_empty() ? nullptr : *(N-pred_begin());
+  }

Why are you looking for the last time a value was stored rather than just 
asking for the value in the current state?

if (OptionalLoc L = S.getAsLoc()) {
  SVal V = State-getSVal(L) // or getRawSVal if you don't want a symbol 
constrained to 0 to be simplified to 0.
  // ...


+if (OptionalKnownSVal V = Val.getAsKnownSVal()) {

Because you needed a symbol already to get this far, you can skip this step. Or 
assert it.


+void TestAfterDivZeroChecker::checkPreStmt(const BinaryOperator *B,
+   CheckerContext C) const {

Strange alignment here. If the second line doesn't fit, just indent it twice 
from the start of the function...don't try to right-align it.


+if (!B-getRHS()-getType()-isScalarType())
+  return;

Dividing by a floating-point 0 is well-defined, so this should be a more 
specific check.

Jordan
___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-06-18 Thread Anders Rönnholm
Changes according to comments. 

I'm pretty sure PVS-Studio does not have this checker, this bug has been seen 
in production code.

//Anders


Från: Jordan Rose [jordan_r...@apple.com]
Skickat: den 16 juni 2014 18:39
Till: Anders Rönnholm
Cc: cfe-commits@cs.uiuc.edu; Daniel Marjamäki
Ämne: Re: [PATCH] Division by zero

On Jun 5, 2014, at 5:16 , Anders Rönnholm 
anders.ronnh...@evidente.semailto:anders.ronnh...@evidente.se wrote:

Hi Jordan,

New patch and some comments.

+inline void inline_func3(int x) {
+  var = 77 / x;
+}
+void ok_inline(int x) {
+  var = 77 / x;
+  inline_func3(x);
+  if (x==0){}
+}

This is an example where we should still be warning. Why aren't we?

It doesn't warn here because blockid is in the value and not the key as it 
should. I have made a set of symbol-block-frame as you suggested and that fixes 
this problem.


+// RUN: %clang_cc1 -analyze -analyzer-checker=core.DivideZero2 
-analyzer-output=text -verify %s

We should never be running path-sensitive checks without the rest of the core 
checkers.

There is a small problem here. It looks like the DivideZero checker makes the 
assumtion that because it can't see that a variable is zero then it's not zero 
so all variables in our tests have the range reg_$0x : { [-2147483648, -1], 
[1, 2147483647] }. I have removed the range check in my checker to make it work 
otherwise i would have to change the DivideZero checker.

Hm. The important thing is that a variable is zero before the division; in the 
absence of this checker, it's a reasonable assumption that it's zero if we made 
it past the division. Would it make sense to step back through ExplodedNodes 
instead until we found a ProgramPoint before the division statement itself, and 
then look at the value of the variable in that state?


+  const ZeroState *ZS = C.getState()-getDivZeroMap(SR);
+  return (ZS  *ZS == ZeroState(C.getBlockID(), C.getStackFrame()));

...now I'm wondering about the wisdom of using a map for this. What if the same 
symbol is constrained in two stack frames? Would it make more sense to keep 
around a set of symbol-block-frame triples, rather than a map from symbols to 
block/frame pairs?

Or can this not happen because a value can only be used once along a certain 
path before it is constrained to be non-zero?

Changed to a set of symbol-block-frame triples to make the above example work.


+def DivZeroChecker2 : CheckerDivideZero2,
+  HelpTextCheck for division by variable that is later compared against 0. 
Either the comparison is useless or there is division by zero.,
+  DescFileDivZeroChecker2.cpp;
+

I'm not sure this is really a core checker, since it's safe to run the analyzer 
without it. But we don't have a category for useful C checks that should be on 
by default yet. Anton was looking at reorganizing the categories, but the 
problem is that everything outside of alpha is something people expect to be 
able to rely on when using scan-build.

Any ideas for this particular checker, or for the general issue?

I ok with having it as an alpha, or something else. I just put it in core since 
the other DivideZero checker is there.

Let's put it in alpha for now.

Code comments:

+class DivZeroChecker2
+: public Checkercheck::PreStmtBinaryOperator, check::BranchCondition,
+ check::EndFunction {

Since we're not doing the normal divide-by-zero check in this checker, let's 
name it something else. TestAfterDivideChecker, maybe?


+  DivZeroMapTy DivZeroes = C.getState()-getDivZeroMap();
+  if (DivZeroes.isEmpty())
+return false;
+
+  for (llvm::ImmutableSetZeroState::iterator I = DivZeroes.begin(),
+   E = DivZeroes.end();
+   I != E; ++I) {
+if (*I == ZeroState(SR, C.getBlockID(), C.getStackFrame()))
+  return true;
+  }
+  return false;

This whole thing can be simplified quite a bit:

ZeroState ZS(SR, C.getBlockID(), C.getStackFrame());
return C.getState()-containsDivZeroMap(ZS);


...and other than that it's looking pretty good! Has this checker found any 
real bugs that you know of? (Does PVS-Studio have a similar checker?)

JordanIndex: include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
===
--- include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h	(revision 210244)
+++ include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h	(working copy)
@@ -174,8 +172,13 @@
 return Pred-getLocationContext()-getAnalysisDeclContext();
   }
 
-  /// \brief If the given node corresponds to a PostStore program point, retrieve
-  /// the location region as it was uttered in the code.
+  /// \brief Get the blockID.
+  unsigned getBlockID() const {
+return NB.getContext().getBlock()-getBlockID();
+  }
+
+  /// \brief If the given node corresponds to a PostStore program point,
+  /// retrieve the location region as it was uttered in the code

Re: [PATCH] Division by zero

2014-06-16 Thread Anders Rönnholm
Ping.

 -Original Message-
 From: Anders Rönnholm
 Sent: den 5 juni 2014 14:17
 To: Jordan Rose
 Cc: cfe-commits@cs.uiuc.edu; Daniel Marjamäki
 Subject: Re: [PATCH] Division by zero
 
 Hi Jordan,
 
 New patch and some comments.
 
 +inline void inline_func3(int x) {
 +  var = 77 / x;
 +}
 +void ok_inline(int x) {
 +  var = 77 / x;
 +  inline_func3(x);
 +  if (x==0){}
 +}
 
 This is an example where we should still be warning. Why aren't we?
 
 It doesn't warn here because blockid is in the value and not the key as it
 should. I have made a set of symbol-block-frame as you suggested and that
 fixes this problem.
 
 
 +// RUN: %clang_cc1 -analyze -analyzer-checker=core.DivideZero2 -analyzer-
 output=text -verify %s
 
 We should never be running path-sensitive checks without the rest of the
 core checkers.
 
 There is a small problem here. It looks like the DivideZero checker makes the
 assumtion that because it can't see that a variable is zero then it's not 
 zero so
 all variables in our tests have the range reg_$0x : { [-2147483648, -1], [1,
 2147483647] }. I have removed the range check in my checker to make it
 work otherwise i would have to change the DivideZero checker.
 
 
 +  const ZeroState *ZS = C.getState()-getDivZeroMap(SR);
 +  return (ZS  *ZS == ZeroState(C.getBlockID(), C.getStackFrame()));
 
 ...now I'm wondering about the wisdom of using a map for this. What if the
 same symbol is constrained in two stack frames? Would it make more sense
 to keep around a set of symbol-block-frame triples, rather than a map from
 symbols to block/frame pairs?
 
 Or can this not happen because a value can only be used once along a certain
 path before it is constrained to be non-zero?
 
 Changed to a set of symbol-block-frame triples to make the above example
 work.
 
 
 +def DivZeroChecker2 : CheckerDivideZero2,
 +  HelpTextCheck for division by variable that is later compared against 0.
 Either the comparison is useless or there is division by zero.,
 +  DescFileDivZeroChecker2.cpp;
 +
 
 I'm not sure this is really a core checker, since it's safe to run the 
 analyzer
 without it. But we don't have a category for useful C checks that should be
 on by default yet. Anton was looking at reorganizing the categories, but the
 problem is that everything outside of alpha is something people expect to
 be able to rely on when using scan-build.
 
 Any ideas for this particular checker, or for the general issue?
 
 I ok with having it as an alpha, or something else. I just put it in core 
 since the
 other DivideZero checker is there.
 
 //Anders


divzero2.diff
Description: divzero2.diff
___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-06-16 Thread Jordan Rose

On Jun 5, 2014, at 5:16 , Anders Rönnholm anders.ronnh...@evidente.se wrote:

 Hi Jordan,
 
 New patch and some comments.
 
 +inline void inline_func3(int x) {
 +  var = 77 / x;
 +}
 +void ok_inline(int x) {
 +  var = 77 / x;
 +  inline_func3(x);
 +  if (x==0){}
 +}
 
 This is an example where we should still be warning. Why aren't we?
 
 It doesn't warn here because blockid is in the value and not the key as it 
 should. I have made a set of symbol-block-frame as you suggested and that 
 fixes this problem.
 
 
 +// RUN: %clang_cc1 -analyze -analyzer-checker=core.DivideZero2 
 -analyzer-output=text -verify %s
 
 We should never be running path-sensitive checks without the rest of the 
 core checkers.
 
 There is a small problem here. It looks like the DivideZero checker makes the 
 assumtion that because it can't see that a variable is zero then it's not 
 zero so all variables in our tests have the range reg_$0x : { [-2147483648, 
 -1], [1, 2147483647] }. I have removed the range check in my checker to make 
 it work otherwise i would have to change the DivideZero checker.

Hm. The important thing is that a variable is zero before the division; in the 
absence of this checker, it's a reasonable assumption that it's zero if we made 
it past the division. Would it make sense to step back through ExplodedNodes 
instead until we found a ProgramPoint before the division statement itself, and 
then look at the value of the variable in that state?


 +  const ZeroState *ZS = C.getState()-getDivZeroMap(SR);
 +  return (ZS  *ZS == ZeroState(C.getBlockID(), C.getStackFrame()));
 
 ...now I'm wondering about the wisdom of using a map for this. What if the 
 same symbol is constrained in two stack frames? Would it make more sense to 
 keep around a set of symbol-block-frame triples, rather than a map from 
 symbols to block/frame pairs?
 
 Or can this not happen because a value can only be used once along a certain 
 path before it is constrained to be non-zero?
 
 Changed to a set of symbol-block-frame triples to make the above example work.
 
 
 +def DivZeroChecker2 : CheckerDivideZero2,
 +  HelpTextCheck for division by variable that is later compared against 
 0. Either the comparison is useless or there is division by zero.,
 +  DescFileDivZeroChecker2.cpp;
 +
 
 I'm not sure this is really a core checker, since it's safe to run the 
 analyzer without it. But we don't have a category for useful C checks that 
 should be on by default yet. Anton was looking at reorganizing the 
 categories, but the problem is that everything outside of alpha is 
 something people expect to be able to rely on when using scan-build.
 
 Any ideas for this particular checker, or for the general issue?
 
 I ok with having it as an alpha, or something else. I just put it in core 
 since the other DivideZero checker is there.

Let's put it in alpha for now.

Code comments:

+class DivZeroChecker2
+: public Checkercheck::PreStmtBinaryOperator, check::BranchCondition,
+ check::EndFunction {

Since we're not doing the normal divide-by-zero check in this checker, let's 
name it something else. TestAfterDivideChecker, maybe?


+  DivZeroMapTy DivZeroes = C.getState()-getDivZeroMap();
+  if (DivZeroes.isEmpty())
+return false;
+
+  for (llvm::ImmutableSetZeroState::iterator I = DivZeroes.begin(),
+   E = DivZeroes.end();
+   I != E; ++I) {
+if (*I == ZeroState(SR, C.getBlockID(), C.getStackFrame()))
+  return true;
+  }
+  return false;

This whole thing can be simplified quite a bit:

ZeroState ZS(SR, C.getBlockID(), C.getStackFrame());
return C.getState()-containsDivZeroMap(ZS);


...and other than that it's looking pretty good! Has this checker found any 
real bugs that you know of? (Does PVS-Studio have a similar checker?)

Jordan___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-06-05 Thread Anders Rönnholm
Hi Jordan,

New patch and some comments.

+inline void inline_func3(int x) {
+  var = 77 / x;
+}
+void ok_inline(int x) {
+  var = 77 / x;
+  inline_func3(x);
+  if (x==0){}
+}

This is an example where we should still be warning. Why aren't we?

It doesn't warn here because blockid is in the value and not the key as it 
should. I have made a set of symbol-block-frame as you suggested and that fixes 
this problem.


+// RUN: %clang_cc1 -analyze -analyzer-checker=core.DivideZero2 
-analyzer-output=text -verify %s

We should never be running path-sensitive checks without the rest of the core 
checkers.

There is a small problem here. It looks like the DivideZero checker makes the 
assumtion that because it can't see that a variable is zero then it's not zero 
so all variables in our tests have the range reg_$0x : { [-2147483648, -1], 
[1, 2147483647] }. I have removed the range check in my checker to make it work 
otherwise i would have to change the DivideZero checker.


+  const ZeroState *ZS = C.getState()-getDivZeroMap(SR);
+  return (ZS  *ZS == ZeroState(C.getBlockID(), C.getStackFrame()));

...now I'm wondering about the wisdom of using a map for this. What if the same 
symbol is constrained in two stack frames? Would it make more sense to keep 
around a set of symbol-block-frame triples, rather than a map from symbols to 
block/frame pairs?

Or can this not happen because a value can only be used once along a certain 
path before it is constrained to be non-zero?

Changed to a set of symbol-block-frame triples to make the above example work.


+def DivZeroChecker2 : CheckerDivideZero2,
+  HelpTextCheck for division by variable that is later compared against 0. 
Either the comparison is useless or there is division by zero.,
+  DescFileDivZeroChecker2.cpp;
+

I'm not sure this is really a core checker, since it's safe to run the analyzer 
without it. But we don't have a category for useful C checks that should be on 
by default yet. Anton was looking at reorganizing the categories, but the 
problem is that everything outside of alpha is something people expect to be 
able to rely on when using scan-build.

Any ideas for this particular checker, or for the general issue?

I ok with having it as an alpha, or something else. I just put it in core since 
the other DivideZero checker is there.

//AndersIndex: lib/StaticAnalyzer/Checkers/DivZeroChecker2.cpp
===
--- lib/StaticAnalyzer/Checkers/DivZeroChecker2.cpp	(revision 0)
+++ lib/StaticAnalyzer/Checkers/DivZeroChecker2.cpp	(revision 0)
@@ -0,0 +1,266 @@
+//== DivZeroChecker2.cpp - Division by zero checker -*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// This defines DivZeroChecker2, a builtin check that performs checks for
+// division by zero where the division occurs before comparison with zero.
+//
+//===--===//
+
+#include ClangSACheckers.h
+#include clang/StaticAnalyzer/Core/BugReporter/BugType.h
+#include clang/StaticAnalyzer/Core/Checker.h
+#include clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+#include clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+#include llvm/ADT/FoldingSet.h
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class ZeroState {
+private:
+  SymbolRef ZeroSymbol;
+  unsigned BlockID;
+  const StackFrameContext *SFC;
+
+public:
+  ZeroState(SymbolRef S, unsigned B, const StackFrameContext *SFC)
+  : ZeroSymbol(S), BlockID(B), SFC(SFC) {}
+
+  const StackFrameContext *getStackFrameContext() const { return SFC; }
+
+  bool operator==(const ZeroState X) const {
+return BlockID == X.BlockID  SFC == X.SFC  ZeroSymbol == X.ZeroSymbol;
+  }
+
+  bool operator(const ZeroState X) const {
+if (BlockID != X.BlockID)
+  return BlockID  X.BlockID;
+if (SFC != X.SFC)
+  return SFC  X.SFC;
+return ZeroSymbol  X.ZeroSymbol;
+  }
+
+  void Profile(llvm::FoldingSetNodeID ID) const {
+ID.AddInteger(BlockID);
+ID.AddPointer(SFC);
+ID.AddPointer(ZeroSymbol);
+  }
+};
+
+class DivisionBRVisitor : public BugReporterVisitorImplDivisionBRVisitor {
+private:
+  SymbolRef ZeroSymbol;
+  const StackFrameContext *SFC;
+  bool Satisfied = false;
+
+public:
+  DivisionBRVisitor(SymbolRef ZeroSymbol, const StackFrameContext *SFC)
+  : ZeroSymbol(ZeroSymbol), SFC(SFC) {}
+
+  void Profile(llvm::FoldingSetNodeID ID) const override {
+ID.Add(ZeroSymbol);
+ID.Add(SFC);
+  }
+
+  PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ,
+ const ExplodedNode *Pred,
+ BugReporterContext BRC,
+ BugReport BR) 

Re: [PATCH] Division by zero

2014-05-29 Thread Jordan Rose
Okay, this definitely looks promising! I still see some issues, though.

+inline void inline_func3(int x) {
+  var = 77 / x;
+}
+void ok_inline(int x) {
+  var = 77 / x;
+  inline_func3(x);
+  if (x==0){}
+}

This is an example where we should still be warning. Why aren't we?

+// RUN: %clang_cc1 -analyze -analyzer-checker=core.DivideZero2 
-analyzer-output=text -verify %s

We should never be running path-sensitive checks without the rest of the core 
checkers.


On the code itself (mostly small things):

+struct ZeroState {
+private:

Small style note: this should probably be a class. The LLVM coding standards 
prefer to use 'struct' only when all members are public. 
http://llvm.org/docs/CodingStandards.html#use-of-class-and-struct-keywords


+  unsigned B;

I'd appreciate this having a more descriptive name, like a full BlockID.


+class DivisionBRVisitor : public BugReporterVisitorImplDivisionBRVisitor {
+protected:

Why protected?


+  DivisionBRVisitor(KnownSVal V) : V(V), Satisfied(false) {}

Now that we're using C++11, it probably makes more sense to move the 
initialization of Satisfied into the member declaration itself. The 
constructor should also be marked explicit.

(But good job making the visitor at all. This makes the error report much more 
helpful!)


+  mutable std::unique_ptrBuiltinBug BB;

The name of this variable should describe the bug, not just be the type.


+bool DivZeroChecker2::hasDivZeroMapSval(SVal Var,
+const CheckerContext C) const {

The SVal part of this really isn't important, so I would drop it from the 
name. But...

+  const ZeroState *ZS = C.getState()-getDivZeroMap(SR);
+  return (ZS  *ZS == ZeroState(C.getBlockID(), C.getStackFrame()));

...now I'm wondering about the wisdom of using a map for this. What if the same 
symbol is constrained in two stack frames? Would it make more sense to keep 
around a set of symbol-block-frame triples, rather than a map from symbols to 
block/frame pairs?

Or can this not happen because a value can only be used once along a certain 
path before it is constrained to be non-zero?

+  } else if (const ImplicitCastExpr *IE =
+ dyn_castImplicitCastExpr(Condition)) {
+SVal Val = C.getSVal(IE-getSubExpr());
+
+if (hasDivZeroMapSval(Val, C))
+  reportBug(Value being compared against zero has already been used for 
+division,
+Val, C);
+  }

I'm not sure there's always an ImplicitCastExpr. There is in C++, of course, 
but I don't think C uses an integer-to-boolean conversion for if-statements. I 
suggest renaming the test to div-zero2.c, and then having two RUN lines, with 
the second including -x c++.


+def DivZeroChecker2 : CheckerDivideZero2,
+  HelpTextCheck for division by variable that is later compared against 0. 
Either the comparison is useless or there is division by zero.,
+  DescFileDivZeroChecker2.cpp;
+  

I'm not sure this is really a core checker, since it's safe to run the analyzer 
without it. But we don't have a category for useful C checks that should be on 
by default yet. Anton was looking at reorganizing the categories, but the 
problem is that everything outside of alpha is something people expect to be 
able to rely on when using scan-build.

Any ideas for this particular checker, or for the general issue?

Jordan
___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-05-23 Thread Anders Rönnholm
Ping

Från: Anders Rönnholm
Skickat: den 16 maj 2014 13:15
Till: Jordan Rose
Cc: cfe-commits@cs.uiuc.edu; Daniel Marjamäki
Ämne: Re: [PATCH] Division by zero

 Clearing the map at the end of a function is a start, but you ought to make 
sure you don't clear it for the function that called this one. I suppose that's 
a refinement that can be made  later, since it only produces false negatives. 
(I'm not super happy about not being able to merge branches within the 
function, though.)

No I don't like it either and would like to fix it but I haven't figured out 
how. Can I find out the current function somehow when the division occurs?

I would just put the current StackFrameContext in as part of the key for the 
map, or make a two-tiered map. Then when you hit the end of the function, you 
can just drop things that match the current StackFrameContext.
Added as value, couldn't get it to work as key.


 +unsigned DivZeroChecker2::getBlockID(const Expr *B, CheckerContext C) const 
{
 +  const CFG cfg = C.getPredecessor()-getCFG();
 +  for (CFG::const_iterator I = cfg.begin(); I != cfg.end(); ++I) {
 +for (CFGBlock::const_iterator BI = (*I)-begin(), BE = (*I)-end();
 + BI != BE; ++BI) {
 +  OptionalCFGStmt stmt = BI-getAsCFGStmt();
 +  if (stmt  stmt-getStmt() == B)
 +return (*I)-getBlockID();
 +}
 +  }
 +  return 0;
 +}

 This is much too expensive. The CheckerContext has a NodeBuilder, which has a 
NodeBuilderContext, which has a CFGBlock. We should just expose that somewhere 
(probably on CheckerContext).

  have made a get function in CheckerContext to retrieve the NodeBuilder. Is 
there something better than blockid? Scope id would have been nice. Blockid 
creates false negatives like below when an if-statement that has nothing to do 
with the division comes in between.

Ok, only blockid exposed now


void err_not(int x, int y) {
var = 77 / x;

if (y)
   int v = 0;

if (!x){}// should warn here but don't since this is a new blockid.
}

We don't currently track scopes, but that still wouldn't eliminate all the 
false positives. I guess it would be closer, though—some day if we start 
tracking scopes again, we can switch to that.

I don't think it makes sense to expose the whole NodeBuilder through the 
CheckerContext, just the block ID.


 Finally, please include some test cases with inlining so that the 
clear-at-end-of-function logic is exercised.

What's the difference with inline and normal functions in this case? As I have 
understood it inline functions are still treated like normal functions when 
walking the ast.

When doing path-sensitive checks, the analyzer can choose to inline any 
function call that it can see the definition for. I want to make sure that we 
still detect test-after-uses when the test and use are both within the inlined 
function and when there is an inlined function call between the test and use in 
the top-most function. (The latter would hit the first issue I noted, that 
clearing the entire state at the end of a function is a bit too destructive.)

I have added a couple of inline functions.

Index: test/Analysis/div-zero2.cpp
===
--- test/Analysis/div-zero2.cpp	(revision 0)
+++ test/Analysis/div-zero2.cpp	(revision 0)
@@ -0,0 +1,190 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core.DivideZero2 -analyzer-output=text -verify %s
+
+int var;
+
+void err_eq(int x) {
+  var = 77 / x; // expected-note {{Division with compared value made here}}
+  if (x==0){} // expected-warning {{Value being compared against zero has already been used for division}}
+} // expected-note@-1 {{Value being compared against zero has already been used for division}}
+
+void err_eq2(int x) {
+  var = 77 / x; // expected-note {{Division with compared value made here}}
+  if (0==x){} // expected-warning {{Value being compared against zero has already been used for division}}
+} // expected-note@-1 {{Value being compared against zero has already been used for division}}
+
+void err_ne(int x) {
+  var = 77 / x; // expected-note {{Division with compared value made here}}
+  if (x!=0){} // expected-warning {{Value being compared against zero has already been used for division}}
+} // expected-note@-1 {{Value being compared against zero has already been used for division}}
+
+void err_ge(int x) {
+  var = 77 / x; // expected-note {{Division with compared value made here}}
+  if (x=0){} // expected-warning {{Value being compared against zero has already been used for division}}
+} // expected-note@-1 {{Value being compared against zero has already been used for division}}
+
+void err_le(int x) {
+  var = 77 / x; // expected-note {{Division with compared value made here}}
+  if (x=0){} // expected-warning {{Value being compared against zero has already been used for division}}
+} // expected-note@-1 {{Value being

Re: [PATCH] Division by zero

2014-05-16 Thread Anders Rönnholm

 Clearing the map at the end of a function is a start, but you ought to make 
sure you don't clear it for the function that called this one. I suppose that's 
a refinement that can be made  later, since it only produces false negatives. 
(I'm not super happy about not being able to merge branches within the 
function, though.)

No I don't like it either and would like to fix it but I haven't figured out 
how. Can I find out the current function somehow when the division occurs?

I would just put the current StackFrameContext in as part of the key for the 
map, or make a two-tiered map. Then when you hit the end of the function, you 
can just drop things that match the current StackFrameContext.
Added as value, couldn't get it to work as key.


 +unsigned DivZeroChecker2::getBlockID(const Expr *B, CheckerContext C) const 
{
 +  const CFG cfg = C.getPredecessor()-getCFG();
 +  for (CFG::const_iterator I = cfg.begin(); I != cfg.end(); ++I) {
 +for (CFGBlock::const_iterator BI = (*I)-begin(), BE = (*I)-end();
 + BI != BE; ++BI) {
 +  OptionalCFGStmt stmt = BI-getAsCFGStmt();
 +  if (stmt  stmt-getStmt() == B)
 +return (*I)-getBlockID();
 +}
 +  }
 +  return 0;
 +}

 This is much too expensive. The CheckerContext has a NodeBuilder, which has a 
NodeBuilderContext, which has a CFGBlock. We should just expose that somewhere 
(probably on CheckerContext).

  have made a get function in CheckerContext to retrieve the NodeBuilder. Is 
there something better than blockid? Scope id would have been nice. Blockid 
creates false negatives like below when an if-statement that has nothing to do 
with the division comes in between.

Ok, only blockid exposed now


void err_not(int x, int y) {
var = 77 / x;

if (y)
   int v = 0;

if (!x){}// should warn here but don't since this is a new blockid.
}

We don't currently track scopes, but that still wouldn't eliminate all the 
false positives. I guess it would be closer, though—some day if we start 
tracking scopes again, we can switch to that.

I don't think it makes sense to expose the whole NodeBuilder through the 
CheckerContext, just the block ID.


 Finally, please include some test cases with inlining so that the 
clear-at-end-of-function logic is exercised.

What's the difference with inline and normal functions in this case? As I have 
understood it inline functions are still treated like normal functions when 
walking the ast.

When doing path-sensitive checks, the analyzer can choose to inline any 
function call that it can see the definition for. I want to make sure that we 
still detect test-after-uses when the test and use are both within the inlined 
function and when there is an inlined function call between the test and use in 
the top-most function. (The latter would hit the first issue I noted, that 
clearing the entire state at the end of a function is a bit too destructive.)

I have added a couple of inline functions.

Index: test/Analysis/div-zero2.cpp
===
--- test/Analysis/div-zero2.cpp	(revision 0)
+++ test/Analysis/div-zero2.cpp	(revision 0)
@@ -0,0 +1,190 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core.DivideZero2 -analyzer-output=text -verify %s
+
+int var;
+
+void err_eq(int x) {
+  var = 77 / x; // expected-note {{Division with compared value made here}}
+  if (x==0){} // expected-warning {{Value being compared against zero has already been used for division}}
+} // expected-note@-1 {{Value being compared against zero has already been used for division}}
+
+void err_eq2(int x) {
+  var = 77 / x; // expected-note {{Division with compared value made here}}
+  if (0==x){} // expected-warning {{Value being compared against zero has already been used for division}}
+} // expected-note@-1 {{Value being compared against zero has already been used for division}}
+
+void err_ne(int x) {
+  var = 77 / x; // expected-note {{Division with compared value made here}}
+  if (x!=0){} // expected-warning {{Value being compared against zero has already been used for division}}
+} // expected-note@-1 {{Value being compared against zero has already been used for division}}
+
+void err_ge(int x) {
+  var = 77 / x; // expected-note {{Division with compared value made here}}
+  if (x=0){} // expected-warning {{Value being compared against zero has already been used for division}}
+} // expected-note@-1 {{Value being compared against zero has already been used for division}}
+
+void err_le(int x) {
+  var = 77 / x; // expected-note {{Division with compared value made here}}
+  if (x=0){} // expected-warning {{Value being compared against zero has already been used for division}}
+} // expected-note@-1 {{Value being compared against zero has already been used for division}}
+
+void err_yes(int x) {
+  var = 77 / x; // expected-note {{Division with compared value made here}}
+  if (x){} // expected-warning {{Value 

Re: [PATCH] Division by zero

2014-05-01 Thread Jordan Rose

On Apr 30, 2014, at 3:54 , Anders Rönnholm anders.ronnh...@evidente.se wrote:

  Clearing the map at the end of a function is a start, but you ought to make 
 sure you don't clear it for the function that called this one. I suppose 
 that's a refinement that can be made  later, since it only produces false 
 negatives. (I'm not super happy about not being able to merge branches within 
 the function, though.)
 
 No I don't like it either and would like to fix it but I haven't figured out 
 how. Can I find out the current function somehow when the division occurs?

I would just put the current StackFrameContext in as part of the key for the 
map, or make a two-tiered map. Then when you hit the end of the function, you 
can just drop things that match the current StackFrameContext.

 
  +unsigned DivZeroChecker2::getBlockID(const Expr *B, CheckerContext C) 
 const {
  +  const CFG cfg = C.getPredecessor()-getCFG();
  +  for (CFG::const_iterator I = cfg.begin(); I != cfg.end(); ++I) {
  +for (CFGBlock::const_iterator BI = (*I)-begin(), BE = (*I)-end();
  + BI != BE; ++BI) {
  +  OptionalCFGStmt stmt = BI-getAsCFGStmt();
  +  if (stmt  stmt-getStmt() == B)
  +return (*I)-getBlockID();
  +}
  +  }
  +  return 0;
  +}
 
  This is much too expensive. The CheckerContext has a NodeBuilder, which has 
 a NodeBuilderContext, which has a CFGBlock. We should just expose that 
 somewhere (probably on CheckerContext).
 
 I have made a get function in CheckerContext to retrieve the NodeBuilder. Is 
 there something better than blockid? Scope id would have been nice. Blockid 
 creates false negatives like below when an if-statement that has nothing to 
 do with the division comes in between.
 
 void err_not(int x, int y) {
  var = 77 / x;
 
  if (y)
int v = 0;
 
  if (!x){}// should warn here but don't since this is a new blockid.
 }

We don't currently track scopes, but that still wouldn't eliminate all the 
false positives. I guess it would be closer, though—some day if we start 
tracking scopes again, we can switch to that.

I don't think it makes sense to expose the whole NodeBuilder through the 
CheckerContext, just the block ID.


  Finally, please include some test cases with inlining so that the 
 clear-at-end-of-function logic is exercised.
 
 What's the difference with inline and normal functions in this case? As I 
 have understood it inline functions are still treated like normal functions 
 when walking the ast.

When doing path-sensitive checks, the analyzer can choose to inline any 
function call that it can see the definition for. I want to make sure that we 
still detect test-after-uses when the test and use are both within the inlined 
function and when there is an inlined function call between the test and use in 
the top-most function. (The latter would hit the first issue I noted, that 
clearing the entire state at the end of a function is a bit too destructive.)

Jordan___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


RE: [PATCH] Division by zero

2014-04-30 Thread Anders Rönnholm
 Clearing the map at the end of a function is a start, but you ought to make 
sure you don't clear it for the function that called this one. I suppose that's 
a refinement that can be made  later, since it only produces false negatives. 
(I'm not super happy about not being able to merge branches within the 
function, though.)

No I don't like it either and would like to fix it but I haven't figured out 
how. Can I find out the current function somehow when the division occurs?

 +unsigned DivZeroChecker2::getBlockID(const Expr *B, CheckerContext C) const 
{
 +  const CFG cfg = C.getPredecessor()-getCFG();
 +  for (CFG::const_iterator I = cfg.begin(); I != cfg.end(); ++I) {
 +for (CFGBlock::const_iterator BI = (*I)-begin(), BE = (*I)-end();
 + BI != BE; ++BI) {
 +  OptionalCFGStmt stmt = BI-getAsCFGStmt();
 +  if (stmt  stmt-getStmt() == B)
 +return (*I)-getBlockID();
 +}
 +  }
 +  return 0;
 +}

 This is much too expensive. The CheckerContext has a NodeBuilder, which has a 
NodeBuilderContext, which has a CFGBlock. We should just expose that somewhere 
(probably on CheckerContext).

I have made a get function in CheckerContext to retrieve the NodeBuilder. Is 
there something better than blockid? Scope id would have been nice. Blockid 
creates false negatives like below when an if-statement that has nothing to do 
with the division comes in between.

void err_not(int x, int y) {
  var = 77 / x;

  if (y)
int v = 0;

  if (!x){}// should warn here but don't since this is a new blockid.
}

 Finally, please include some test cases with inlining so that the 
clear-at-end-of-function logic is exercised.

What's the difference with inline and normal functions in this case? As I have 
understood it inline functions are still treated like normal functions when 
walking the ast.

 Thanks for working on this, and sorry for the slow responses.
 Jordan
It's ok I'm not that fast either. 

On Apr 24, 2014, at 7:50 , Anders Rönnholm 
anders.ronnh...@evidente.semailto:anders.ronnh...@evidente.se wrote:


Hi Jordan,

I have changed the patch to store $foo instead of the variable. I also make 
sure that the divison and check is in the same block by comparing the blockid. 
This handles your second example.

//Anders


Från: Jordan Rose [jordan_r...@apple.commailto:jordan_r...@apple.com]
Skickat: den 5 april 2014 04:03
Till: Anders Rönnholm
Cc: cfe-commits@cs.uiuc.edumailto:cfe-commits@cs.uiuc.edu; Daniel Marjamäki
Ämne: Re: [PATCH] Division by zero

On Apr 3, 2014, at 7:18 , Anders Rönnholm 
anders.ronnh...@evidente.semailto:anders.ronnh...@evidente.semailto:anders.ronnh...@evidente.se
 wrote:

Hi Jordan, see below for comments and questions.

 Hi, Anders. I have some high-level concerns about this checker as it's 
structured now. First (and most mundanely), the checker is conflating values 
and locations. A particular symbol in the analyzer can  never change, so 
there's no reason to ever have to remove something from the DivZeroMap because 
of invalidation.

 int x = foo(); // The value stored in 'x' is some symbol '$foo'
 int y = 5 / x; // use $foo
 x = bar(); // The value stored in 'x' is now some symbol '$bar', but '$foo' 
hasn't changed.

 On the flip side, I'm concerned that values never leave the map. You could 
clean up some of them with a checkDeadSymbols callback, but that's still a 
large amount of state for values that may have been  checked quite a while 
ago. In particular, this will result in false positives if a value is used in 
one function and then checked in another.

Why don't we have to remove it? When x changes as you say we need to remove it 
or flag it so we don't check x against zero anymore since x has changed after 
the division.

I guess we could remove all items in DivZeroMap when we leave the function, do 
you think that would work?

When 'x' changes is the interesting part. '$foo' can't change, and that's 
what you're inserting into the map. The value stored in 'x' can change, and 
that's why 'x' is being removed from the map. But 'x' should never be in the 
map in the first place; it's '$foo', the value, that's important.

Here's another example:

int x = foo();
int y = x;

use(5 / x);
if (y == 0) // warn!

If we track the variable 'x', then we won't catch this case, even though it's 
pretty much equivalent to what you had before.

Here's another problem with doing things this way: doing this as a 
path-sensitive check says that there's a spurious comparison along one path, 
but you really need to know if it happens along all paths:

void foo() {
bool isPositive;
int x = getValue(isPositive);
if (isPositive) {
use(5 / x);
}

if (x == 0) {
log(x is zero);
}
}

In this case, there exists a path where 'x' checked against 0 after being used 
as a denominator, but it's not actually a problem. You can argue that the test 
should be moved up before the use, or that an assertion should be added, but I 
don't know if we want

Re: [PATCH] Division by zero

2014-04-28 Thread Jordan Rose
I don't understand why the DivZeroMap uses a MemRegion as a key at all. In this 
patch you never look things up by MemRegion. I would expect it to be a map from 
SymbolRef to block ID.

Clearing the map at the end of a function is a start, but you ought to make 
sure you don't clear it for the function that called this one. I suppose that's 
a refinement that can be made later, since it only produces false negatives. 
(I'm not super happy about not being able to merge branches within the 
function, though.)

I'm not sure why you only update the DivZeroMap with the first BlockID that 
gets used. If I do a division operation, and then I do another one in another 
block, and then I do a check of the variable, shouldn't that still count as a 
reversed check?

Smaller comments:

+unsigned DivZeroChecker2::getBlockID(const Expr *B, CheckerContext C) const {
+  const CFG cfg = C.getPredecessor()-getCFG();
+  for (CFG::const_iterator I = cfg.begin(); I != cfg.end(); ++I) {
+for (CFGBlock::const_iterator BI = (*I)-begin(), BE = (*I)-end();
+ BI != BE; ++BI) {
+  OptionalCFGStmt stmt = BI-getAsCFGStmt();
+  if (stmt  stmt-getStmt() == B)
+return (*I)-getBlockID();
+}
+  }
+  return 0;
+}

This is much too expensive. The CheckerContext has a NodeBuilder, which has a 
NodeBuilderContext, which has a CFGBlock. We should just expose that somewhere 
(probably on CheckerContext).

+  if (ExplodedNode *N = C.generateSink(C.getState())) {
+if (!BB)
+  BB.reset(new BuiltinBug(this, Division by zero));

Before this checker goes non-alpha, we definitely need a visitor that says 
where the most recent division or remainder operation happened.

+  if (IntLiteral  IntLiteral-getValue() != 0)
+return;

This check should be if (!IntLiteral || IntLiteral-getValue() != 0).

+reportBug(Comparison is useless, 
+  or there is division by zero previously,

Now that the checker is restricted to a guaranteed check-after-division, we can 
probably improve the error message to be more precise. Value being compared 
against zero has already been used for division or something.

Finally, please include some test cases with inlining so that the 
clear-at-end-of-function logic is exercised.

Thanks for working on this, and sorry for the slow responses.
Jordan


On Apr 24, 2014, at 7:50 , Anders Rönnholm anders.ronnh...@evidente.se wrote:

 Hi Jordan,
 
 I have changed the patch to store $foo instead of the variable. I also make 
 sure that the divison and check is in the same block by comparing the 
 blockid. This handles your second example.
 
 //Anders
 
 
 Från: Jordan Rose [jordan_r...@apple.com]
 Skickat: den 5 april 2014 04:03
 Till: Anders Rönnholm
 Cc: cfe-commits@cs.uiuc.edu; Daniel Marjamäki
 Ämne: Re: [PATCH] Division by zero
 
 On Apr 3, 2014, at 7:18 , Anders Rönnholm 
 anders.ronnh...@evidente.semailto:anders.ronnh...@evidente.se wrote:
 
 Hi Jordan, see below for comments and questions.
 
  Hi, Anders. I have some high-level concerns about this checker as it's 
 structured now. First (and most mundanely), the checker is conflating values 
 and locations. A particular symbol in the analyzer can  never change, so 
 there's no reason to ever have to remove something from the DivZeroMap 
 because of invalidation.
 
  int x = foo(); // The value stored in 'x' is some symbol '$foo'
  int y = 5 / x; // use $foo
  x = bar(); // The value stored in 'x' is now some symbol '$bar', but '$foo' 
 hasn't changed.
 
  On the flip side, I'm concerned that values never leave the map. You could 
 clean up some of them with a checkDeadSymbols callback, but that's still a 
 large amount of state for values that may have been  checked quite a while 
 ago. In particular, this will result in false positives if a value is used in 
 one function and then checked in another.
 
 Why don't we have to remove it? When x changes as you say we need to remove 
 it or flag it so we don't check x against zero anymore since x has changed 
 after the division.
 
 I guess we could remove all items in DivZeroMap when we leave the function, 
 do you think that would work?
 
 When 'x' changes is the interesting part. '$foo' can't change, and that's 
 what you're inserting into the map. The value stored in 'x' can change, and 
 that's why 'x' is being removed from the map. But 'x' should never be in the 
 map in the first place; it's '$foo', the value, that's important.
 
 Here's another example:
 
 int x = foo();
 int y = x;
 
 use(5 / x);
 if (y == 0) // warn!
 
 If we track the variable 'x', then we won't catch this case, even though it's 
 pretty much equivalent to what you had before.
 
 Here's another problem with doing things this way: doing this as a 
 path-sensitive check says that there's a spurious comparison along one path, 
 but you really need to know if it happens along all paths:
 
 void foo() {
 bool isPositive;
 int x = getValue(isPositive

Re: [PATCH] Division by zero

2014-04-04 Thread Jordan Rose

On Apr 3, 2014, at 7:18 , Anders Rönnholm anders.ronnh...@evidente.se wrote:

 Hi Jordan, see below for comments and questions.
 
  Hi, Anders. I have some high-level concerns about this checker as it's 
 structured now. First (and most mundanely), the checker is conflating values 
 and locations. A particular symbol in the analyzer can  never change, so 
 there's no reason to ever have to remove something from the DivZeroMap 
 because of invalidation.
 
  int x = foo(); // The value stored in 'x' is some symbol '$foo'
  int y = 5 / x; // use $foo
  x = bar(); // The value stored in 'x' is now some symbol '$bar', but '$foo' 
 hasn't changed.
 
  On the flip side, I'm concerned that values never leave the map. You could 
 clean up some of them with a checkDeadSymbols callback, but that's still a 
 large amount of state for values that may have been  checked quite a while 
 ago. In particular, this will result in false positives if a value is used in 
 one function and then checked in another.
 
 Why don't we have to remove it? When x changes as you say we need to remove 
 it or flag it so we don't check x against zero anymore since x has changed 
 after the division. 
 
 I guess we could remove all items in DivZeroMap when we leave the function, 
 do you think that would work?

When 'x' changes is the interesting part. '$foo' can't change, and that's 
what you're inserting into the map. The value stored in 'x' can change, and 
that's why 'x' is being removed from the map. But 'x' should never be in the 
map in the first place; it's '$foo', the value, that's important.

Here's another example:

int x = foo();
int y = x;

use(5 / x);
if (y == 0) // warn!

If we track the variable 'x', then we won't catch this case, even though it's 
pretty much equivalent to what you had before.

Here's another problem with doing things this way: doing this as a 
path-sensitive check says that there's a spurious comparison along one path, 
but you really need to know if it happens along all paths:

void foo() {
bool isPositive;
int x = getValue(isPositive);
if (isPositive) {
use(5 / x);
}

if (x == 0) {
log(x is zero);
}
}

In this case, there exists a path where 'x' checked against 0 after being used 
as a denominator, but it's not actually a problem. You can argue that the test 
should be moved up before the use, or that an assertion should be added, but I 
don't know if we want to tackle that. OTOH, you would have to add an assertion 
if you did move the test before the use.

I like the idea of clearing the map/set on function exit, because it's somewhat 
reasonable to add asserts within a function...but you'd basically also have to 
clear it on function entrance too. Which means you have one set per 
LocationContext. I haven't fully thought that through yet.


 
 
  (The opposite order hit us so much when dealing with C++ support that we 
 coined a term for it: inlined defensive checks. This occurs when one 
 function accepts null pointers and so does a check, the   caller knows the 
 value is never null but doesn't actually assert it, and then the value is 
 used. We ended up having to silence all bugs where the first null check came 
 from an inlined function, which  definitely through out some true positives 
 with the false ones.)
 
  What do you think?
  Jordan
  
  P.S. If your map entries always map to true, you might as well use a set. 
 ;-)
 
 Is it possible to get a specific entry using set or do you have to iterate 
 through all items to find the one your looking for?
 
 With map you can do this,:
 const bool D = State-getDivZeroMap(MR);
 
 but with set i'm only able to get them all.
 DivZeroMapTy DivZeroes = State-getDivZeroMap();

For future reference, set traits get a State-containsDivZeroMap().

Jordan___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-04-03 Thread Anders Rönnholm
Hi Jordan, see below for comments and questions.

 Hi, Anders. I have some high-level concerns about this checker as it's 
structured now. First (and most mundanely), the checker is conflating values 
and locations. A particular symbol in the analyzer can  never change, so 
there's no reason to ever have to remove something from the DivZeroMap because 
of invalidation.

 int x = foo(); // The value stored in 'x' is some symbol '$foo'
 int y = 5 / x; // use $foo
 x = bar(); // The value stored in 'x' is now some symbol '$bar', but '$foo' 
hasn't changed.

 On the flip side, I'm concerned that values never leave the map. You could 
clean up some of them with a checkDeadSymbols callback, but that's still a 
large amount of state for values that may have been  checked quite a while 
ago. In particular, this will result in false positives if a value is used in 
one function and then checked in another.

Why don't we have to remove it? When x changes as you say we need to remove it 
or flag it so we don't check x against zero anymore since x has changed after 
the division. 

I guess we could remove all items in DivZeroMap when we leave the function, do 
you think that would work?


 (The opposite order hit us so much when dealing with C++ support that we 
coined a term for it: inlined defensive checks. This occurs when one function 
accepts null pointers and so does a check, the   caller knows the value is 
never null but doesn't actually assert it, and then the value is used. We ended 
up having to silence all bugs where the first null check came from an inlined 
function, which  definitely through out some true positives with the false 
ones.)

 What do you think?
 Jordan
 
 P.S. If your map entries always map to true, you might as well use a set. 
;-)

Is it possible to get a specific entry using set or do you have to iterate 
through all items to find the one your looking for?

With map you can do this,:
const bool D = State-getDivZeroMap(MR);

but with set i'm only able to get them all.
DivZeroMapTy DivZeroes = State-getDivZeroMap();

/Anders

On Apr 1, 2014, at 7:45 , Anders Rönnholm 
anders.ronnh...@evidente.semailto:anders.ronnh...@evidente.se wrote:

Hi,

I have a new patch i'd like to get reviewed for a different kind of division by 
zero than the already existing one.

This patch check for division by variable that is later compared against 0. 
Either the comparison is useless or there is division by zero.

It catches scenarios like these:

void f(int y) {
x = 100 / y;
if (y == 0) {}
}

//Andersdivzero2.diff___
cfe-commits mailing list
cfe-commits@cs.uiuc.edumailto:cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


Re: [PATCH] Division by zero

2014-04-02 Thread Jordan Rose
Hi, Anders. I have some high-level concerns about this checker as it's 
structured now. First (and most mundanely), the checker is conflating values 
and locations. A particular symbol in the analyzer can never change, so there's 
no reason to ever have to remove something from the DivZeroMap because of 
invalidation.

int x = foo(); // The value stored in 'x' is some symbol '$foo'
int y = 5 / x; // use $foo
x = bar(); // The value stored in 'x' is now some symbol '$bar', but '$foo' 
hasn't changed.

On the flip side, I'm concerned that values never leave the map. You could 
clean up some of them with a checkDeadSymbols callback, but that's still a 
large amount of state for values that may have been checked quite a while ago. 
In particular, this will result in false positives if a value is used in one 
function and then checked in another.

(The opposite order hit us so much when dealing with C++ support that we coined 
a term for it: inlined defensive checks. This occurs when one function 
accepts null pointers and so does a check, the caller knows the value is never 
null but doesn't actually assert it, and then the value is used. We ended up 
having to silence all bugs where the first null check came from an inlined 
function, which definitely through out some true positives with the false ones.)

What do you think?
Jordan

P.S. If your map entries always map to true, you might as well use a set. ;-)


On Apr 1, 2014, at 7:45 , Anders Rönnholm anders.ronnh...@evidente.se wrote:

 Hi,
 
 I have a new patch i'd like to get reviewed for a different kind of division 
 by zero than the already existing one. 
 
 This patch check for division by variable that is later compared against 0. 
 Either the comparison is useless or there is division by zero.
 
 It catches scenarios like these:
 
 void f(int y) {
 x = 100 / y;
 if (y == 0) {}
 }
 
 //Andersdivzero2.diff___
 cfe-commits mailing list
 cfe-commits@cs.uiuc.edu
 http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

___
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits