Skip to content

Commit

Permalink
[clang][analyzer] Move 'alpha.core.PointerSub' checker into 'security…
Browse files Browse the repository at this point in the history
….PointerSub' (#107596)
  • Loading branch information
balazske authored Sep 30, 2024
1 parent a87640c commit 0d384fe
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 55 deletions.
86 changes: 43 additions & 43 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1544,6 +1544,49 @@ Warn on ``mmap()`` calls with both writable and executable access.
// code
}
.. _security-PointerSub:
security.PointerSub (C)
"""""""""""""""""""""""
Check for pointer subtractions on two pointers pointing to different memory
chunks. According to the C standard §6.5.6 only subtraction of pointers that
point into (or one past the end) the same array object is valid (for this
purpose non-array variables are like arrays of size 1). This checker only
searches for different memory objects at subtraction, but does not check if the
array index is correct. Furthermore, only cases are reported where
stack-allocated objects are involved (no warnings on pointers to memory
allocated by `malloc`).
.. code-block:: c
void test() {
int a, b, c[10], d[10];
int x = &c[3] - &c[1];
x = &d[4] - &c[1]; // warn: 'c' and 'd' are different arrays
x = (&a + 1) - &a;
x = &b - &a; // warn: 'a' and 'b' are different variables
}
struct S {
int x[10];
int y[10];
};
void test1() {
struct S a[10];
struct S b;
int d = &a[4] - &a[6];
d = &a[0].x[3] - &a[0].x[1];
d = a[0].y - a[0].x; // warn: 'S.b' and 'S.a' are different objects
d = (char *)&b.y - (char *)&b.x; // warn: different members of the same object
d = (char *)&b.y - (char *)&b; // warn: object of type S is not the same array as a member of it
}
There may be existing applications that use code like above for calculating
offsets of members in a structure, using pointer subtractions. This is still
undefined behavior according to the standard and code like this can be replaced
with the `offsetof` macro.
.. _security-putenv-stack-array:
security.PutenvStackArray (C)
Expand Down Expand Up @@ -2761,49 +2804,6 @@ Check for pointer arithmetic on locations other than array elements.
p = &x + 1; // warn
}
.. _alpha-core-PointerSub:
alpha.core.PointerSub (C)
"""""""""""""""""""""""""
Check for pointer subtractions on two pointers pointing to different memory
chunks. According to the C standard §6.5.6 only subtraction of pointers that
point into (or one past the end) the same array object is valid (for this
purpose non-array variables are like arrays of size 1). This checker only
searches for different memory objects at subtraction, but does not check if the
array index is correct. Furthermore, only cases are reported where
stack-allocated objects are involved (no warnings on pointers to memory
allocated by `malloc`).
.. code-block:: c
void test() {
int a, b, c[10], d[10];
int x = &c[3] - &c[1];
x = &d[4] - &c[1]; // warn: 'c' and 'd' are different arrays
x = (&a + 1) - &a;
x = &b - &a; // warn: 'a' and 'b' are different variables
}
struct S {
int x[10];
int y[10];
};
void test1() {
struct S a[10];
struct S b;
int d = &a[4] - &a[6];
d = &a[0].x[3] - &a[0].x[1];
d = a[0].y - a[0].x; // warn: 'S.b' and 'S.a' are different objects
d = (char *)&b.y - (char *)&b.x; // warn: different members of the same object
d = (char *)&b.y - (char *)&b; // warn: object of type S is not the same array as a member of it
}
There may be existing applications that use code like above for calculating
offsets of members in a structure, using pointer subtractions. This is still
undefined behavior according to the standard and code like this can be replaced
with the `offsetof` macro.
.. _alpha-core-StackAddressAsyncEscape:
alpha.core.StackAddressAsyncEscape (ObjC)
Expand Down
10 changes: 5 additions & 5 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -290,11 +290,6 @@ def PointerArithChecker : Checker<"PointerArithm">,
"elements">,
Documentation<HasDocumentation>;

def PointerSubChecker : Checker<"PointerSub">,
HelpText<"Check for pointer subtractions on two pointers pointing to "
"different memory chunks">,
Documentation<HasDocumentation>;

def TestAfterDivZeroChecker : Checker<"TestAfterDivZero">,
HelpText<"Check for division by variable that is later compared against 0. "
"Either the comparison is useless or there is division by zero.">,
Expand Down Expand Up @@ -1003,6 +998,11 @@ def MmapWriteExecChecker : Checker<"MmapWriteExec">,
HelpText<"Warn on mmap() calls with both writable and executable access">,
Documentation<HasDocumentation>;

def PointerSubChecker : Checker<"PointerSub">,
HelpText<"Check for pointer subtractions on two pointers pointing to "
"different memory chunks">,
Documentation<HasDocumentation>;

def PutenvStackArray : Checker<"PutenvStackArray">,
HelpText<"Finds calls to the function 'putenv' which pass a pointer to "
"an automatic (stack-allocated) array as the argument.">,
Expand Down
6 changes: 1 addition & 5 deletions clang/test/Analysis/casts.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ void locAsIntegerCasts(void *p) {
}

void multiDimensionalArrayPointerCasts(void) {
static int x[10][10]; // expected-note2{{Array at the right-hand side of subtraction}}
static int x[10][10];
int *y1 = &(x[3][5]);
char *z = ((char *) y1) + 2;
int *y2 = (int *)(z - 2);
Expand All @@ -138,9 +138,7 @@ void multiDimensionalArrayPointerCasts(void) {
clang_analyzer_eval(y1 == y2); // expected-warning{{TRUE}}

// FIXME: should be FALSE (i.e. equal pointers).
// FIXME: pointer subtraction warning might be incorrect
clang_analyzer_eval(y1 - y2); // expected-warning{{UNKNOWN}}
// expected-warning@-1{{Subtraction of two pointers that do not point into the same array is undefined behavior}}
// FIXME: should be TRUE (i.e. same symbol).
clang_analyzer_eval(*y1 == *y2); // expected-warning{{UNKNOWN}}

Expand All @@ -149,9 +147,7 @@ void multiDimensionalArrayPointerCasts(void) {
clang_analyzer_eval(y1 == y3); // expected-warning{{TRUE}}

// FIXME: should be FALSE (i.e. equal pointers).
// FIXME: pointer subtraction warning might be incorrect
clang_analyzer_eval(y1 - y3); // expected-warning{{UNKNOWN}}
// expected-warning@-1{{Subtraction of two pointers that do not point into the same array is undefined behavior}}
// FIXME: should be TRUE (i.e. same symbol).
clang_analyzer_eval(*y1 == *y3); // expected-warning{{UNKNOWN}}

Expand Down
2 changes: 1 addition & 1 deletion clang/test/Analysis/pointer-sub-notes.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.PointerSub -analyzer-output=text -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=security.PointerSub -analyzer-output=text -verify %s

void different_1() {
int a[3]; // expected-note{{Array at the left-hand side of subtraction}}
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Analysis/pointer-sub.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.PointerSub -analyzer-output=text-minimal -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=security.PointerSub -analyzer-output=text-minimal -verify %s

void f1(void) {
int x, y, z[10];
Expand Down

0 comments on commit 0d384fe

Please sign in to comment.