Szelethus added a comment.

In D72705#2199333 <https://reviews.llvm.org/D72705#2199333>, @balazske wrote:

> Test results for tmux are available here 
> <https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=tmux_errorreturn&review-status=Unreviewed&review-status=Confirmed%20bug&detection-status=New&detection-status=Reopened&detection-status=Unresolved>.
>  (Could not manage to get other results uploaded.)

I guess this is a somewhat smarter version, correct? You seem to have 
`NoteTag`s and handling for `localtime` etc. Anyways, I trust that the logic of 
mostly the same.

I don't know how likely it is for time management functions to fail, I guess 
its a rarity, but I guess this is exactly what static analysis is for. I think 
these results are nice, but as cheap of a response this is, I crave some more. 
You specifically mentioned a few false positives, I wonder what is up with them.

In D72705#2161576 <https://reviews.llvm.org/D72705#2161576>, @balazske wrote:

> This checker can have two purposes, one is to verify that all paths have the 
> error check, other is to find at least one path without error check. The 
> first is the one that can be done with dataflow based analysis but looks like 
> a difficult problem. For example is it possible to handle this case (`X` does 
> not change)?
>
>   int Ret;
>   if (X)
>     Ret = fgetc(fd);
>   else
>     Ret = strtol(SomeString);
>   ...
>   bool IsError;
>   if (X)
>     IsError = (Ret == EOF);
>   else
>     IsError = (Ret < -100 || Ret > 100);
>
> The other "purpose" is to find one path with missing error check, the current 
> code should do something like that. The path sensitivity is used here to 
> store for a symbol from which function call it comes from, and probably to 
> determine value of other symbols in the program if they appear in a 
> comparison.

You are right, dataflow definitely has shortcomings that pathsensitivity 
doesn't, but it is true the other way around as well, which is why I believe 
(D72705#2141439 <https://reviews.llvm.org/D72705#2141439>) the combination of 
the two would be the correct solution, even if the question is whether the 
return value is checked on a given path of execution (that is precisely what 
the example in the comment demonstrates, not to mention that it could be far 
more obfuscated).

---

I think we have dedicated a lot of time to discuss our long term plans. I feel 
confident in my stance regarding the future of this checker, you seem to have a 
good grasp on it, we've gotten feedback a wide range of reviewers, and we also 
have this as a feature request outside Ericsson. Since this patch intends to 
lend an alpha checker, I think its about time we start talking about moving 
forward.

Here is what I like about this patch and want to see it in clang sooner rather 
than later:

- Documentation is great. Its hard to overstate the value of that, when I 
literally have to sink in weeks into a codebase to understand whats going on 
due to the lack of it.
- @NoQ mentioned the callback choice may not be ideal/wrong, but I personally 
disagree. Its far easier, and I think cheaper to climb up on the AST. The high 
level idea behind the visitor analyzing whether a statement constitutes as a 
check is great, I don't we have anything similar.
- I think you tested the added functionality for an alpha checker quite well.
- If my worries (did we think about all the  cases that could constitute as a 
check?) won't be an issue, the infrastructure proposed by this patch seems 
easily expandable.

Here is what I want to see moving forward:

- This comment D72705#2088319 <https://reviews.llvm.org/D72705#2088319> worries 
me. @NoQ, could you please expand on this? I feel like you have a legitimate 
worry I'm not seeing, and I perceive you to be a bit skeptical about this whole 
shebang. While I'd hate to stall the progress of this patch, it'd be nice to be 
settled on this before moving too fast forward.
- More evaluations. I realize that reviewers don't demand too much on this 
front for an initial patch for an alpha checker, but both the problem and our 
different visions on the solution could use some backing up. It would be a 
shame if an issue we could've easily foreseen came about that would require 
serious architectural changes. What was the problem in uploading the results 
you already had on hand?

I left some inlines, but I didn't go too nitty just yet. For the time being, 
lets have these two goals met, and after that I'll definitely do my best to 
help you get this landed ASAP.



================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrorReturnChecker.cpp:55-60
+  /// Test if an encountered binary operator where the return value is involved
+  /// is a valid check statement. The return value appears in one side of the
+  /// operator (`ChildIsLHS` indicates if it is on the LHS). If the other side
+  /// contains a known (mostly constant) value, it is already calculated in
+  /// `KnownValue`. `RetTy` is the type of the return value (return type of the
+  /// function call in the code to check).
----------------
So, for the time being we're saying that a checking must involve a binary 
operator. That sounds about right, but I wonder if there is a case we're not 
thinking about.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrorReturnChecker.cpp:63
+                                          const BinaryOperator *BinOp,
+                                          const llvm::APSInt *KnownValue,
+                                          QualType RetTy,
----------------
This is the value we're checking //against//, I think the name `KnownValue` 
doesn't convey this.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrorReturnChecker.cpp:79-80
+                                  bool ChildIsLHS) const override {
+    if (!KnownValue)
+      return false;
+
----------------
So if we failed to get retrieve the value we're checking against, we 
automatically assume that its not a proper check? Shouldn't we be conservative 
here? What if that value is something like `getEOFValue()`?


================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrorReturnChecker.cpp:83
+    bool KnownNull = KnownValue->isNullValue();
+    bool KnownEOF = ((*KnownValue) == BVF.getValue(-1, RetTy));
+
----------------
We have a smarter EOF getter thanks to @martong, don't we?


================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrorReturnChecker.cpp:284-287
+    // It is assumed that any system function does not accept value that is
+    // an error return value from any other function.
+    // In other words error check is required before system function is called
+    // with the value.
----------------
This is a very broad statement. I can't come up with a counterexample on top of 
my head, but we should keep this in mind. What this totally deserves however, 
is a distinct warning message, like "xth argument to system/standard function 
call is an unchecked return value".

Please put a TODO here.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrorReturnChecker.cpp:295-296
+
+  // Value appears in other expression.
+  VisitResult VisitExpr(const Stmt *S) { return NoCheckUseFound; }
+
----------------
Aha, interesting. So the thing to note here is that if the parent (which is 
stripped of all the cast/paren expressions) in a non-call expression, it 
constitutes as an improper use before checking. Again, I don't have an 
immediate counter example, but let's keep this in mind as a likely source of 
false positives. Which may not be too bad, we'll at least immediately be 
notified that there are additional cases to handle.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrorReturnChecker.cpp:329-330
+  // Value appears in other statement.
+  // FIXME: Statements that affects control-flow should be checked separately.
+  // For example `Child` may appear as a condition of `if`.
+  VisitResult VisitStmt(const Stmt *S) { return StopExamineNoError; }
----------------
Why?


================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrorReturnChecker.cpp:428-432
+  // Check for explicit cast to void.
+  if (auto *Cast = dyn_cast<const CStyleCastExpr>(S)) {
+    if (Cast->getTypeAsWritten().getTypePtr()->isVoidType())
+      return nullptr;
+  }
----------------
Ah, okay, so you mean to check whether someone did something like this:
```lang=c++
// Silence compiler warning.
(void)localtime(...);
```

I don't think that the parent though will get you the correct answer, how about 
this: 

```lang=c++
// Silence compiler warning.
(void) (coin() ? NULL : localtime(...));
```

Please put a TODO here.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72705/new/

https://reviews.llvm.org/D72705

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to