Skip to content

Commit 8dcff10

Browse files
authored
[clang][analyzer] Improve documentation of StreamChecker (NFC). (#83858)
1 parent 23ca8e6 commit 8dcff10

File tree

1 file changed

+52
-14
lines changed

1 file changed

+52
-14
lines changed

clang/docs/analyzer/checkers.rst

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3120,44 +3120,82 @@ Check for misuses of stream APIs. Check for misuses of stream APIs: ``fopen, fcl
31203120
31213121
alpha.unix.Stream (C)
31223122
"""""""""""""""""""""
3123-
Check stream handling functions: ``fopen, tmpfile, fclose, fread, fwrite, fseek, ftell, rewind, fgetpos,``
3124-
``fsetpos, clearerr, feof, ferror, fileno``.
3123+
Check C stream handling functions:
3124+
``fopen, fdopen, freopen, tmpfile, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, fprintf, fscanf, ungetc, getdelim, getline, fseek, fseeko, ftell, ftello, fflush, rewind, fgetpos, fsetpos, clearerr, feof, ferror, fileno``.
3125+
3126+
The checker maintains information about the C stream objects (``FILE *``) and
3127+
can detect error conditions related to use of streams. The following conditions
3128+
are detected:
3129+
3130+
* The ``FILE *`` pointer passed to the function is NULL (the single exception is
3131+
``fflush`` where NULL is allowed).
3132+
* Use of stream after close.
3133+
* Opened stream is not closed.
3134+
* Read from a stream after end-of-file. (This is not a fatal error but reported
3135+
by the checker. Stream remains in EOF state and the read operation fails.)
3136+
* Use of stream when the file position is indeterminate after a previous failed
3137+
operation. Some functions (like ``ferror``, ``clearerr``, ``fseek``) are
3138+
allowed in this state.
3139+
* Invalid 3rd ("``whence``") argument to ``fseek``.
3140+
3141+
The checker does not track the correspondence between integer file descriptors
3142+
and ``FILE *`` pointers. Operations on standard streams like ``stdin`` are not
3143+
treated specially and are therefore often not recognized (because these streams
3144+
are usually not opened explicitly by the program, and are global variables).
31253145
31263146
.. code-block:: c
31273147
3128-
void test() {
3148+
void test1() {
31293149
FILE *p = fopen("foo", "r");
31303150
} // warn: opened file is never closed
31313151
3132-
void test() {
3152+
void test2() {
31333153
FILE *p = fopen("foo", "r");
31343154
fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL
31353155
fclose(p);
31363156
}
31373157
3138-
void test() {
3158+
void test3() {
31393159
FILE *p = fopen("foo", "r");
3160+
if (p) {
3161+
fseek(p, 1, 3); // warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR
3162+
fclose(p);
3163+
}
3164+
}
31403165
3141-
if (p)
3142-
fseek(p, 1, 3);
3143-
// warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR
3166+
void test4() {
3167+
FILE *p = fopen("foo", "r");
3168+
if (!p)
3169+
return;
31443170
31453171
fclose(p);
3172+
fclose(p); // warn: stream already closed
31463173
}
31473174
3148-
void test() {
3175+
void test5() {
31493176
FILE *p = fopen("foo", "r");
3177+
if (!p)
3178+
return;
3179+
3180+
fgetc(p);
3181+
if (!ferror(p))
3182+
fgetc(p); // warn: possible read after end-of-file
3183+
31503184
fclose(p);
3151-
fclose(p); // warn: already closed
31523185
}
31533186
3154-
void test() {
3155-
FILE *p = tmpfile();
3156-
ftell(p); // warn: stream pointer might be NULL
3187+
void test6() {
3188+
FILE *p = fopen("foo", "r");
3189+
if (!p)
3190+
return;
3191+
3192+
fgetc(p);
3193+
if (!feof(p))
3194+
fgetc(p); // warn: file position may be indeterminate after I/O error
3195+
31573196
fclose(p);
31583197
}
31593198
3160-
31613199
.. _alpha-unix-cstring-BufferOverlap:
31623200
31633201
alpha.unix.cstring.BufferOverlap (C)

0 commit comments

Comments
 (0)