135 Commits

Author SHA1 Message Date
Balazs Benics
2e3c7dbbcb
[analyzer] Note last "fclose" call from "ensureStreamOpened" (#109112)
Patch by Arseniy Zaostrovnykh!
2024-09-18 12:22:02 +02:00
Balazs Benics
2e30f8d114
[analyzer] Fix StreamChecker crash in fread modeling (#108393)
In #93408
69bc159142
I refined how invalidation is done for `fread`. It can crash, if the
"size" or "count" parameters of "fread" is a perfectly constrained
negative value. In such cases, when it will try to allocate a
SmallVector with a negative size, which will cause a crash.

To mitigate this issue, let's just guard against negative values.

CPP-3247
2024-09-12 17:06:52 +02:00
Kristóf Umann
8370ba4d15
[analyzer][NFC] Eliminate a dyn_cast (#100719)
Response to the catch in this comment:
07f6daf2cf (r1692084074)
2024-08-05 13:25:31 +02:00
Balazs Benics
13d39cb6f7
[analyzer] Fix crash of StreamChecker when eval calling 'fopen' (#100990)
Actually, on the failure branch of `fopen`, the resulting pointer could
alias with `stdout` iff `stdout` is already known to be null.
We crashed in this case as the implementation assumed that the
state-split for creating the success and failure branches both should be
viable; thus dereferenced both of those states - leading to the crash.

To fix this, let's just only add this no-alias property for the success
path, and that's it :)

Fixes #100901
2024-07-29 14:15:02 +02:00
Balazs Benics
b60fec27fd
[analyzer] Assume the result of 'fopen' can't alias with 'std{in,out,err}' (#100085)
'fopen' should return a new FILE handle, thus we should assume it can't
alias with commonly used FILE handles, such as with 'stdin', 'stdout' or
'stderr'.

This problem appears in code that handles either some input/output file
with stdin or stdout, as the business logic is basically the same no
matter the stream being used.
However, one would should only close the stream if it was opened via
'fopen'. Consequently, such code usually has a condition like `if (f &&
f != stdout)` to guard the `fclose()` call.

This patch brings this assumption, thus eliminates FPs for not taking
the guarded branch.

CPP-5306
2024-07-23 13:22:58 +02:00
Balazs Benics
2e81f7db1f
[analyzer] Fix crash in Stream checker when using void pointers (#97199)
We can get zero type size (thus div by zero crash) if the region is for a 'void*' pointer.
In this patch, let's just override the void type with a char type to avoid the crash.

Fixes
https://github.com/llvm/llvm-project/pull/93408#issuecomment-2189766510
2024-07-01 17:33:44 +02:00
Kristóf Umann
fc4b09d161
[analyzer] Add an ownership change visitor to StreamChecker (#94957)
This is very similar to https://reviews.llvm.org/D105553, in fact, I
barely made any changes from MallocChecker's ownership visitor to this
one.

The new visitor emits a diagnostic note for function where a change in
stream ownership was expected (for example, it had a fclose() call), but
the ownership remained unchanged. This is similar to messages regarding
ordinary values ("Returning without writing to x").
2024-06-24 16:34:36 +02:00
NAKAMURA Takumi
43bd7ae65a StreamChecker.cpp: Use isa<> (for #93408) [-Wunused-but-set-variable] 2024-06-14 12:18:41 +09:00
Balazs Benics
69bc159142
[analyzer] Refine invalidation caused by fread (#93408)
This change enables more accurate modeling of the write effects of
`fread`. In particular, instead of invalidating the whole buffer, in a
best-effort basis, we would try to invalidate the actually accesses
elements of the buffer. This preserves the previous value of the buffer
of the unaffected slots. As a result, diagnose more uninitialized buffer
uses for example.

Currently, this refined invalidation only triggers for `fread` if and
only if the `count` parameter and the buffer pointer's index component
are concrete or perfectly-constrained symbols.
Additionally, if the `fread` would read more than 64 elements, the whole
buffer is invalidated as before. This is to have safeguards against
performance issues.

Refer to the comments of the assertions in the following example to see
the changes in the diagnostics:

```c++
void demo() {
  FILE *fp = fopen("/home/test", "rb+");
  if (!fp) return;
  int buffer[10]; // uninitialized
  int read_items = fread(buffer+1, sizeof(int), 5, fp);
  if (5 == read_items) {
    int v1 = buffer[1]; // Unknown value but not garbage.
    clang_analyzer_isTainted(v1); // expected-warning {{YES}} <-- Would be "NO" without this patch.
    clang_analyzer_dump(v1); // expected-warning {{conj_}} <-- Not a "derived" symbol, so it's directly invalidated now.
    int v0 = buffer[0]; // expected-warning {{Assigned value is garbage or undefined}} <-- Had no report here before.
    (void)(v1 + v0);
  } else {
    // If 'fread' had an error.
    int v0 = buffer[0]; // expected-warning {{Assigned value is garbage or undefined}} <-- Had no report here before.
    (void)v0;
  }
  fclose(fp);
}
```

CPP-3247, CPP-3802

Co-authored by Marco Borgeaud (marco-antognini-sonarsource)
2024-06-13 16:13:22 +02:00
Kazu Hirata
deffae5da1
[clang] Use StringRef::operator== instead of StringRef::equals (NFC) (#91844)
I'm planning to remove StringRef::equals in favor of
StringRef::operator==.

- StringRef::operator==/!= outnumber StringRef::equals by a factor of
  24 under clang/ in terms of their usage.

- The elimination of StringRef::equals brings StringRef closer to
  std::string_view, which has operator== but not equals.

- S == "foo" is more readable than S.equals("foo"), especially for
  !Long.Expression.equals("str") vs Long.Expression != "str".
2024-05-11 11:38:52 -07:00
Donát Nagy
6d64f8e1fe
[analyzer] Use explicit call description mode in more checkers (#90974)
This commit explicitly specifies the matching mode (C library function,
any non-method function, or C++ method) for the `CallDescription`s
constructed in various checkers.

Some code was simplified to use `CallDescriptionSet`s instead of
individual `CallDescription`s.

This change won't cause major functional changes, but isn't NFC because
it ensures that e.g. call descriptions for a non-method function won't
accidentally match a method that has the same name.

Separate commits have already performed this change in other checkers:
- easy cases: e2f1cbae45f81f3cd9a4d3c2bcf69a094eb060fa
- MallocChecker: d6d84b5d1448e4f2e24b467a0abcf42fe9d543e9
- iterator checkers: 06eedffe0d2782922e63cc25cb927f4acdaf7b30
- InvalidPtr checker: 024281d4d26344f9613b9115ea1fcbdbdba23235

... and follow-up commits will handle the remaining checkers.

My goal is to ensure that the call description mode is always explicitly
specified and eliminate (or strongly restrict) the vague "may be either
a method or a simple function" mode that's the current default.
2024-05-07 13:48:02 +02:00
Mike Rice
cd3e71fb7a
[NFC][clang][analyzer] Initialize pointer field in StreamOperationEvaluator (#89837)
Add an initializer for StreamSym, which is a pointer. The pointers in
this class are set in the Init function, but all should be initialized
in the constructor to avoid confusion and static verifier hits.
2024-04-24 08:31:45 -07:00
NagyDonat
fe3b20d5ab
[analyzer] Use CDM::CLibrary instead of isGlobalCFunction() (#88267)
This commit updates several checkers to use call descriptions with the
matching mode `CDM::CLibrary` instead of checking
`Call.isGlobalCFunction()` after performing the match. This resolves
several TODOs in various checkers.

Note that both matching with `CDM::CLibrary` and calling
`isGlobalCFunction` leads to `CheckerContext::isCLibraryFunction()`
checks (so this change is close to being NFC), but if it is used via the
matching mode then the checker can automatically recognize the builtin
variants of the matched functions.

I'll also make similar changes in GenericTaintChecker, but that checker
has separate and inconsistent rules for handling the normal and the
builtin variant of several functions (e.g. `memcpy` and
`__builtin_memcpy`), so I'll put those changes into a separate commit.
2024-04-11 10:44:35 +02:00
Balázs Kéri
c2067c1f47
[clang][analyzer] Add "pedantic" mode to StreamChecker. (#87322)
The checker may create failure branches for all stream write operations
only if the new option "pedantic" is set to true.
Result of the write operations is often not checked in typical code. If
failure branches are created the checker will warn for unchecked write
operations and generate a lot of "false positives" (these are valid
warnings but the programmer does not care about this problem).
2024-04-08 12:19:03 +02:00
Balázs Kéri
93c387df90
[clang][analyzer] Change modeling of fseek in StreamChecker. (#86919)
Until now function `fseek` returned nonzero on error, this is changed to
-1 only. And it does not produce EOF error any more.
This complies better with the POSIX standard.
2024-04-02 08:55:20 +02:00
Alejandro Álvarez Ayllón
730ca47a0c [clang][analyzer] Model getline/getdelim preconditions and evaluation (#83027)
According to POSIX 2018.

1. lineptr, n and stream can not be NULL.
2. If *n is non-zero, *lineptr must point to a region of at least *n
   bytes, or be a NULL pointer.

Additionally, if *lineptr is not NULL, *n must not be undefined.
2024-03-22 11:50:34 +01:00
Balázs Kéri
d72b7f9133
[clang][analyzer] Fix StreamChecker ftell and fgetpos at indeterminate file position. (#84191)
These functions should not be allowed if the file position is
indeterminate (they return the file position).
This condition is now checked, and tests are improved to check it.
2024-03-08 08:56:10 +01:00
Alejandro Álvarez Ayllón
239312e49b
Reapply "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, vfprintf" (#83281)
`va_list` is a platform-specific type. On some, it is a struct instead
of a pointer to a struct, so `lookupFn` was ignoring calls to `vfprintf`
and `vfscanf`.

`stream.c` now runs in four different platforms to make sure the logic
works across targets.
2024-03-06 12:10:07 +01:00
Balázs Kéri
012b697e7c
[clang][analyzer] Add StreamChecker note tags for "indeterminate stream position". (#83288)
If a stream operation fails the position can become "indeterminate".
This may cause warning from the checker at a later operation. The new
note tag shows the place where the position becomes "indeterminate",
this is where a failure occurred.
2024-03-01 08:21:57 +01:00
Balazs Benics
570bc5d291 Revert "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, vfprintf (#82476)"
This reverts commit ffe7049b543adb9739261d28a60d4a47a00aa2e0.

This commit breaks on e.g. arm:
Example:
https://lab.llvm.org/buildbot/#/builders/245/builds/21177/steps/5/logs/FAIL__Clang__stream_c

```
******************** TEST 'Clang :: Analysis/stream.c' FAILED ********************
Exit Code: 1
Command Output (stderr):
--
RUN: at line 1: /home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/clang -cc1 -internal-isystem /home/tcwg-buildbot/worker/clang-armv8-quick/stage1/lib/clang/19/include -nostdsysteminc -analyze -analyzer-constraints=range -setup-static-analyzer -analyzer-checker=core,alpha.unix.Stream,debug.ExprInspection -verify /home/tcwg-buildbot/worker/clang-armv8-quick/llvm/clang/test/Analysis/stream.c
+ /home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/clang -cc1 -internal-isystem /home/tcwg-buildbot/worker/clang-armv8-quick/stage1/lib/clang/19/include -nostdsysteminc -analyze -analyzer-constraints=range -setup-static-analyzer -analyzer-checker=core,alpha.unix.Stream,debug.ExprInspection -verify /home/tcwg-buildbot/worker/clang-armv8-quick/llvm/clang/test/Analysis/stream.c
error: 'expected-warning' diagnostics expected but not seen:
  File /home/tcwg-buildbot/worker/clang-armv8-quick/llvm/clang/test/Analysis/stream.c Line 147: Stream pointer might be NULL
  File /home/tcwg-buildbot/worker/clang-armv8-quick/llvm/clang/test/Analysis/stream.c Line 153: Stream pointer might be NULL
error: 'expected-warning' diagnostics seen but not expected:
  File /home/tcwg-buildbot/worker/clang-armv8-quick/llvm/clang/test/Analysis/stream.c Line 148: Stream pointer might be NULL [alpha.unix.Stream]
  File /home/tcwg-buildbot/worker/clang-armv8-quick/llvm/clang/test/Analysis/stream.c Line 154: Stream pointer might be NULL [alpha.unix.Stream]
4 errors generated.
--
********************
```
2024-02-28 14:10:22 +01:00
Alejandro Álvarez Ayllón
ffe7049b54
[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, vfprintf (#82476)
Model `getc` and `putc` as equivalent to `fgetc` and `fputc` respectively.

Model `vfscanf` and `vfprintf` as `fscanf` and `fprintf`, except that
`vfscanf` can not invalidate the parameters due to the indirection via a
`va_list`. Nevertheless, we can still track EOF and errors as for `fscanf`.
2024-02-28 12:22:57 +01:00
Balázs Kéri
5ca877591e
[clang][analyzer] Fix argument invalidations in StreamChecker. (#79470)
Specific arguments passed to stream handling functions are changed by
the function, this means these should be invalidated ("escaped") by the
analyzer. This change adds the argument invalidation (in specific cases)
to the checker.
2024-02-23 09:35:38 +01:00
Balázs Kéri
1246b64faa
[clang][analyzer] Change modeling of 'fileno' in checkers. (#81842)
Function 'fileno' fails only if invalid pointer is passed, this is a
case that is often ignored in source code. The failure case leads to
many "false positive" reports when `fileno` returns -1 and this is not
checked in the program. Because this, the function is now assumed
to not fail (this is assumption that the passed file pointer is correct).
The change affects `StdCLibraryFunctionsChecker` and
`StreamChecker`.
2024-02-21 09:18:01 +01:00
Balázs Kéri
3be9132898
[clang][analyzer] Simplify code of StreamChecker - part 2 (NFC). (#82228)
Continuation of commit 42b5037, apply changes to the remaining
functions.
Code for function `fflush` was not changed, because it is more special
compared to the others.
2024-02-20 10:57:30 +01:00
Balázs Kéri
42b5037cc4
[clang][analyzer] Simplify code of StreamChecker (NFC). (#79312)
A class is added that contains common functions and data members that are used in many of the "eval" functions. This results in shorter "eval" functions and less code repetition.
2024-02-16 08:48:52 +01:00
Jie Fu
45c84f8011 [clang][analyzer] Remove unused variable in StreamChecker.cpp (NFC)
llvm-project/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp:1125:17:
 error: unused variable 'ASTC' [-Werror,-Wunused-variable]
 1125 |     ASTContext &ASTC = C.getASTContext();
      |                 ^~~~
1 error generated.
2024-01-23 09:24:22 +08:00
Ben Shi
ea75542db9
[clang][analyzer] Support 'getdelim' and 'getline' in StreamChecker (#78693) 2024-01-23 09:19:38 +08:00
Balázs Kéri
0845514d1a
[clang][analyzer] Add function 'fscanf' to StreamChecker. (#78180) 2024-01-22 09:58:09 +01:00
Balázs Kéri
8550e8845c
[clang][analyzer] Add function 'fprintf' to StreamChecker. (#77613)
[clang][analyzer] Add function 'fprintf' to StreamChecker.
2024-01-12 17:00:14 +01:00
Ben Shi
19081f4a50
[clang][analyzer] Support 'tello' and 'fseeko' in the StreamChecker (#77580) 2024-01-11 18:48:31 +08:00
Balázs Kéri
8f78dd4b92
[clang][analyzer] Add function 'ungetc' to StreamChecker. (#77331)
`StdLibraryFunctionsChecker` is updated too with `ungetc`.
2024-01-10 09:09:51 +01:00
Ben Shi
18c0f59b3e
[clang][analyzer] Support 'fdopen' in the StreamChecker (#76776) 2024-01-04 15:52:52 +08:00
Ben Shi
73948ec6b2
[clang][analyzer] Support fflush in the StreamChecker (#74296) 2023-12-21 17:57:06 +08:00
Ben Shi
4699789249
[clang][analyzer][NFC] Supplement comments in evalFtell of StreamChecker (#74291) 2023-12-06 10:26:30 +08:00
Ben Shi
47df664c7a
[clang][analyzer] Support fgets in the SteamChecker (#73638) 2023-11-29 19:20:49 +08:00
Ben Shi
95a47bca5e
[clang][analyzer] Support fputs in the StreamChecker (#73335) 2023-11-28 20:14:51 +08:00
Ben Shi
53578e5c85
[clang][analyzer] Support fgetc in StreamChecker (#72627) 2023-11-23 23:11:19 +08:00
Ben Shi
917a550f4d
[clang][Analyzer][NFC] Use condition type for comparison in several checkers (#72358) 2023-11-16 07:37:33 +08:00
Ben Shi
d5af076a99
[clang][analyzer] Support fputc in StreamChecker (#71518) 2023-11-16 07:36:57 +08:00
Ben Shi
1b45fe5c83
[clang][analyzer][NFC] Remove redundant code in StreamChecker (#71394) 2023-11-07 19:14:05 +08:00
Ben Shi
32521bb37c
[clang][analyzer] Restrict 'fopen' & 'tmpfile' modeling to POSIX versions in StreamChecker (#70540)
'tmpfile' has only one form that it has no argument.
2023-11-02 17:10:56 +08:00
Ben Shi
e98f3bfff2
[clang][analyzer]][NFC] Simplify method 'ensureStreamNonNull' of StreamChecker (#70927)
The passed in parameter 'State' is always identical to 'C.getState()'.
2023-11-02 14:41:33 +08:00
Ben Shi
00b7979946
[clang][analyzer][NFC] Combine similar methods of StreamChecker (#70170)
Methods StreamChecker::preFread and StreamChecker::preFwrite are quite
similar, so they can be combined to StreamChecker::preFreadFwrite.
2023-10-25 22:00:02 +08:00
Ben Shi
f9906508bc
[analyzer][NFC] Substitute operator() with lambda in StreamChecker 2023-10-21 16:29:14 +02:00
Balázs Kéri
2eefd19613 [clang][analyzer] No end-of-file when seek to file begin.
If `fseek` is used with 0 position and SEEK_SET it sets the position
to the start of the file. This should not cause FEOF (end of file) error.
The case of an empty file is not handled for simplification.
It is not exactly defined in what cases `fseek` produces the different
error states. Normally feof should not happen at all because it is
possible to set the position after the end of file, but previous tests
showed that still feof (and any other error cases) can happen.

Reviewed By: donat.nagy

Differential Revision: https://reviews.llvm.org/D153363
2023-06-30 10:29:49 +02:00
Manna, Soumi
982a87ab74 [CLANG] Fix potential null pointer dereference bugs
This patch uses castAs instead of getAs which will assert if the type doesn't match and adds nullptr check if needed.

Also this patch improves the codes and passes I.getData() instead of doing a lookup in dumpVarDefinitionName()
since we're iterating over the same map in LocalVariableMap::dumpContex().

Reviewed By: aaron.ballman, aaronpuchert

Differential Revision: https://reviews.llvm.org/D153033
2023-06-22 12:58:38 -07:00
Balázs Kéri
2c60f9c8a4 [clang][analyzer] Add report of NULL stream to StreamChecker.
The report of NULL stream was removed in commit 570bf97.
The old reason is not actual any more because the checker dependencies are changed.
It is not good to eliminate a failure state (where the stream is NULL) without
generating a bug report because other checkers are not able to find it later.
The checker did this with the NULL stream pointer, and because this checker
runs now before other checkers that can detect NULL pointers, the null pointer
bug was not found at all.

Reviewed By: steakhal

Differential Revision: https://reviews.llvm.org/D152169
2023-06-06 11:51:33 +02:00
Kazu Hirata
6ad0788c33 [clang] Use std::optional instead of llvm::Optional (NFC)
This patch replaces (llvm::|)Optional< with std::optional<.  I'll post
a separate patch to remove #include "llvm/ADT/Optional.h".

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2023-01-14 12:31:01 -08:00
Kazu Hirata
a1580d7b59 [clang] Add #include <optional> (NFC)
This patch adds #include <optional> to those files containing
llvm::Optional<...> or Optional<...>.

I'll post a separate patch to actually replace llvm::Optional with
std::optional.

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2023-01-14 11:07:21 -08:00
Balázs Kéri
570bf972f5 [clang][analyzer] Remove report of null stream from StreamChecker.
The case of NULL stream passed to stream functions was reported by StreamChecker.
The same condition is checked already by StdLibraryFunctionsChecker and it is
enough to check at one place. The StreamChecker stops now analysis if a passed NULL
stream is encountered but generates no report.
This change removes a dependency between StdCLibraryFunctionArgs checker and
StreamChecker. There is now no more specific message reported by StreamChecker,
the previous weak-dependency is not needed. And StreamChecker can be used
without StdCLibraryFunctions checker or its ModelPOSIX option.

Reviewed By: Szelethus

Differential Revision: https://reviews.llvm.org/D137790
2023-01-09 09:49:08 +01:00