Skip to content

Commit 4dfa021

Browse files
authored
[clang][analyzer] Bring checker 'alpha.unix.cstring.NotNullTerminated' out of alpha (#113899)
1 parent 204d715 commit 4dfa021

File tree

8 files changed

+50
-30
lines changed

8 files changed

+50
-30
lines changed

clang/docs/analyzer/checkers.rst

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,6 +1899,29 @@ Check the size argument passed into C string functions for common erroneous patt
18991899
// warn: potential buffer overflow
19001900
}
19011901
1902+
.. _unix-cstring-NotNullTerminated:
1903+
1904+
unix.cstring.NotNullTerminated (C)
1905+
""""""""""""""""""""""""""""""""""
1906+
Check for arguments which are not null-terminated strings;
1907+
applies to the ``strlen``, ``strcpy``, ``strcat``, ``strcmp`` family of functions.
1908+
1909+
Only very fundamental cases are detected where the passed memory block is
1910+
absolutely different from a null-terminated string. This checker does not
1911+
find if a memory buffer is passed where the terminating zero character
1912+
is missing.
1913+
1914+
.. code-block:: c
1915+
1916+
void test1() {
1917+
int l = strlen((char *)&test1); // warn
1918+
}
1919+
1920+
void test2() {
1921+
label:
1922+
int l = strlen((char *)&&label); // warn
1923+
}
1924+
19021925
.. _unix-cstring-NullArg:
19031926
19041927
unix.cstring.NullArg (C)
@@ -3367,29 +3390,6 @@ Checks for overlap in two buffer arguments. Applies to: ``memcpy, mempcpy, wmem
33673390
memcpy(a + 2, a + 1, 8); // warn
33683391
}
33693392
3370-
.. _alpha-unix-cstring-NotNullTerminated:
3371-
3372-
alpha.unix.cstring.NotNullTerminated (C)
3373-
""""""""""""""""""""""""""""""""""""""""
3374-
Check for arguments which are not null-terminated strings;
3375-
applies to the ``strlen``, ``strcpy``, ``strcat``, ``strcmp`` family of functions.
3376-
3377-
Only very fundamental cases are detected where the passed memory block is
3378-
absolutely different from a null-terminated string. This checker does not
3379-
find if a memory buffer is passed where the terminating zero character
3380-
is missing.
3381-
3382-
.. code-block:: c
3383-
3384-
void test1() {
3385-
int l = strlen((char *)&test); // warn
3386-
}
3387-
3388-
void test2() {
3389-
label:
3390-
int l = strlen((char *)&&label); // warn
3391-
}
3392-
33933393
.. _alpha-unix-cstring-OutOfBounds:
33943394
33953395
alpha.unix.cstring.OutOfBounds (C)

clang/include/clang/StaticAnalyzer/Checkers/Checkers.td

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,12 @@ def CStringModeling : Checker<"CStringModeling">,
457457
Documentation<NotDocumented>,
458458
Hidden;
459459

460+
def CStringNotNullTerm : Checker<"NotNullTerminated">,
461+
HelpText<"Check for arguments passed to C string functions which are not "
462+
"null-terminated strings">,
463+
Dependencies<[CStringModeling]>,
464+
Documentation<HasDocumentation>;
465+
460466
def CStringNullArg : Checker<"NullArg">,
461467
HelpText<"Check for null pointers being passed as arguments to C string "
462468
"functions">,
@@ -483,11 +489,6 @@ def CStringBufferOverlap : Checker<"BufferOverlap">,
483489
Dependencies<[CStringModeling]>,
484490
Documentation<HasDocumentation>;
485491

486-
def CStringNotNullTerm : Checker<"NotNullTerminated">,
487-
HelpText<"Check for arguments which are not null-terminating strings">,
488-
Dependencies<[CStringModeling]>,
489-
Documentation<HasDocumentation>;
490-
491492
def CStringUninitializedRead : Checker<"UninitializedRead">,
492493
HelpText<"Checks if the string manipulation function would read uninitialized bytes">,
493494
Dependencies<[CStringModeling]>,

clang/test/Analysis/analyzer-enabled-checkers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
// CHECK-NEXT: unix.StdCLibraryFunctions
5454
// CHECK-NEXT: unix.Vfork
5555
// CHECK-NEXT: unix.cstring.BadSizeArg
56+
// CHECK-NEXT: unix.cstring.NotNullTerminated
5657
// CHECK-NEXT: unix.cstring.NullArg
5758

5859
int main() {

clang/test/Analysis/bstring.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
33
// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
44
// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
5-
// RUN: %clang_analyze_cc1 -DSUPPRESS_OUT_OF_BOUND -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring.BufferOverlap,alpha.unix.cstring.NotNullTerminated,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
5+
// RUN: %clang_analyze_cc1 -DSUPPRESS_OUT_OF_BOUND -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring.BufferOverlap,unix.cstring.NotNullTerminated,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
66

77
#include "Inputs/system-header-simulator-cxx.h"
88
#include "Inputs/system-header-simulator-for-malloc.h"

clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
// CHECK-NEXT: unix.StdCLibraryFunctions
6262
// CHECK-NEXT: unix.Vfork
6363
// CHECK-NEXT: unix.cstring.BadSizeArg
64+
// CHECK-NEXT: unix.cstring.NotNullTerminated
6465
// CHECK-NEXT: unix.cstring.NullArg
6566

6667
int main() {

clang/test/Analysis/string.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
// RUN: -analyzer-checker=unix.cstring \
3939
// RUN: -analyzer-checker=unix.Malloc \
4040
// RUN: -analyzer-checker=alpha.unix.cstring.BufferOverlap \
41-
// RUN: -analyzer-checker=alpha.unix.cstring.NotNullTerminated \
41+
// RUN: -analyzer-checker=unix.cstring.NotNullTerminated \
4242
// RUN: -analyzer-checker=debug.ExprInspection \
4343
// RUN: -analyzer-config eagerly-assume=false
4444

clang/test/Analysis/string.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,10 @@ struct TestNotNullTerm {
5353
strlen((char *)&x); // expected-warning{{Argument to string length function is not a null-terminated string}}
5454
}
5555
};
56+
57+
void test_notcstring_tempobject() {
58+
// FIXME: This warning from cstring.NotNullTerminated is a false positive.
59+
// Handling of similar cases is not perfect in other cstring checkers.
60+
// The fix would be a larger change in CStringChecker and affect multiple checkers.
61+
strlen((char[]){'a', 0}); // expected-warning{{Argument to string length function is a C++ temp object of type char[2], which is not a null-terminated string}}
62+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_analyze_cc1 -verify %s -Wno-null-dereference \
2+
// RUN: -analyzer-checker=core \
3+
// RUN: -analyzer-checker=unix.cstring.NotNullTerminated \
4+
// RUN: -analyzer-checker=debug.ExprInspection
5+
6+
char *strcpy(char *restrict s1, const char *restrict s2);
7+
8+
void strcpy_fn(char *x) {
9+
strcpy(x, (char*)&strcpy_fn); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
10+
}

0 commit comments

Comments
 (0)