steakhal added a comment.

Looks pretty good.



================
Comment at: clang/docs/analyzer/checkers.rst:704
+optin.portabilityMinor.UnixAPI
+"""""""""""""""""""""""""
+Finds non-severe implementation-defined behavior in UNIX/Posix functions.
----------------
This line should be just as long, as the line above.


================
Comment at: clang/docs/analyzer/checkers.rst:705
+"""""""""""""""""""""""""
+Finds non-severe implementation-defined behavior in UNIX/Posix functions.
+
----------------
Our docs aren't great, but we should have a brief description what the checker 
detects, basically here it would be "Find null pointers being passed to 
printf-like functions. Usually, passing null pointers to such functions is 
implementation defined, thus non-portable. Printf-like functions are: x, y, z."
Illustrate one example for diagnosing a case. Also illustrate one case similar 
to the bad one, that is fixed (basically ensure that the pointer is not null 
there).
And that's it.


================
Comment at: clang/include/clang/StaticAnalyzer/Checkers/Checkers.td:45-50
+// The PortabilityMinor package is for checkers that find non-severe 
portability
+// issues (see also the Portability package). Such checks may be unwanted for
+// developers who want to ignore minor portability issues, hence they are put 
in
+// a separate package.
+def PortabilityMinorOptIn : Package<"portabilityMinor">, ParentPackage<OptIn>;
+
----------------
I don't think we should create a separate package. A separate checker should be 
enough in `alpha.unix`, or `alpha.optin`, or just `optin`.


================
Comment at: clang/include/clang/StaticAnalyzer/Checkers/Checkers.td:1671
+
+def UnixAPIPortabilityMinorChecker : Checker<"UnixAPI">,
+  HelpText<"Finds non-severe implementation-defined behavior in UNIX/Posix 
functions">,
----------------
Usually, the user-facing checker name which is the `<"...">` part there, 
matches the name of the checker's class name. It helps for maintenance.
I would strongly suggest keeping this naming convention.


================
Comment at: clang/include/clang/StaticAnalyzer/Checkers/Checkers.td:1673
+  HelpText<"Finds non-severe implementation-defined behavior in UNIX/Posix 
functions">,
+  Documentation<NotDocumented>;
+
----------------
Docs are not really optional these days, but we can come back later once the 
checker is ironed out.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp:88
 
+class UnixAPIPortabilityMinorChecker
+    : public Checker<check::PreStmt<CallExpr>> {
----------------
Usually, we put separate checkers into their own file.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp:89
+class UnixAPIPortabilityMinorChecker
+    : public Checker<check::PreStmt<CallExpr>> {
+public:
----------------
Prefer using the `check::PreCall` callback over the `PreStmt`.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp:94
+private:
+  mutable std::unique_ptr<BugType> BT_printfPointerConversionSpecifierNULL;
+
----------------
Nowdays, if I'm not mistaken, we just inline initialize these eagerly.
That way you could also avoid marking it mutable.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp:102
+  void
+  ReportPrintfPointerConversionSpecifierNULL(clang::ento::CheckerContext &C,
+                                             ProgramStateRef nullState,
----------------
Feel free to just call it `reportBug`.
Also, in the cpp file, usually we use the namespaces `clang,llvm,ento` already. 
You don't need to fully-qualify these names.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp:593-594
+
+  if (FName == "printf")
+    CheckPrintfPointerConversionSpecifierNULL(C, CE, 1);
+
----------------
For matching names, we usually use `CallDescriptions` to do it for us.
If think you could use them while also checking if the Call is a 
`CallEvent::isGlobalCFunction()`. I suspect, you only wanna check those.
I think you should define a `CallDescriptionMap`, because you will also need 
your specific `data_arg_index`...
Look for uses of such maps and you will get inspired.


================
Comment at: clang/test/Analysis/unix-fns.c:81-92
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif
+
+struct FILE_t;
+typedef struct FILE_t FILE;
+
----------------
I'd highly recommend not touching this file to avoid the bulk change in the 
expected plist output. Please just introduce a new test file.


================
Comment at: clang/test/Analysis/unix-fns.c:280-289
+// Test pointer constraint.
+void printf_pointer_conversion_specifier_null_pointer_constraint(char *format, 
void *pointer1) {
+  void *pointer2 = NULL;
+  printf(format, pointer2); // expected-warning{{The result of passing a null 
pointer to the pointer conversion specifier of the printf family of functions 
is implementation defined}}
+  if (pointer1 != NULL) {
+    printf(format, pointer1); // no-warning
+    return;
----------------
I would appreciate a test demonstrating that the pointer argument won't get 
constrained after the `printf` call. I think such case was already discussed.

We should also demonstrate that unknown pointers (which doesn't known to be 
neither null, nor non-null) won't raise issues.

In the checker-logic, we have the `data_args_index` for each `printf`-like 
function.
Can you demonstrate that each is handled as expected?

Also have a test when the formatstring itself is null.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154838

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

Reply via email to