[clang] [clang][analyzer] Add checker 'alpha.core.FixedAddressDereference' (PR #127191)

Balázs Kéri via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 17 02:29:25 PST 2025


================
@@ -1,7 +1,163 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify %s
-// expected-no-diagnostics
 
-void foo(void) {
+extern void __assert_fail (__const char *__assertion, __const char *__file,
+    unsigned int __line, __const char *__function)
+     __attribute__ ((__noreturn__));
+
+#define assert(expr) \
+  ((expr)  ? (void)(0)  : __assert_fail (#expr, __FILE__, __LINE__, __func__))
+
+typedef unsigned long uintptr_t;
+
+void f0(void) {
   int *p = (int*) 0x10000; // Should not crash here.
-  *p = 3;
+  *p = 3; // expected-warning{{Dereference of a fixed address}}
+}
+
+void f1(int *p) {
+  if (p != (int *)-1)
+    *p = 1;
+  else
+    *p = 0; // expected-warning{{Dereference of a fixed address}}
+}
+
+struct f2_struct {
+  int x;
+};
+
+int f2(struct f2_struct* p) {
+
+  if (p != (struct f2_struct *)1)
+    p->x = 1;
+
+  return p->x++; // expected-warning{{Access to field 'x' results in a dereference of a fixed address (loaded from variable 'p')}}
+}
+
+int f3_1(char* x) {
+  int i = 2;
+
+  if (x != (char *)1)
+    return x[i - 1];
+
+  return x[i+1]; // expected-warning{{Array access (from variable 'x') results in a dereference of a fixed address}}
+}
+
+int f3_2(char* x) {
+  int i = 2;
+
+  if (x != (char *)1)
+    return x[i - 1];
+
+  return x[i+1]++; // expected-warning{{Array access (from variable 'x') results in a dereference of a fixed address}}
+}
+
+int f4_1(int *p) {
+  uintptr_t x = (uintptr_t) p;
+
+  if (x != (uintptr_t)1)
+    return 1;
+
+  int *q = (int*) x;
+  return *q; // expected-warning{{Dereference of a fixed address (loaded from variable 'q')}}
+}
+
+int f4_2(void) {
+  short array[2];
+  uintptr_t x = (uintptr_t)array;
+  short *p = (short *)x;
+
+  // The following branch should be infeasible.
+  if (!(p == &array[0])) {
+    p = (short *)1;
+    *p = 1; // no-warning
+  }
+
+  if (p != (short *)1) {
+    *p = 5; // no-warning
+    p = (short *)1; // expected-warning {{Using a fixed address is not portable}}
+  }
+  else return 1;
+
+  *p += 10; // expected-warning{{Dereference of a fixed}}
+  return 0;
+}
+
+int f5(void) {
+  char *s = "hello world";
+  return s[0]; // no-warning
+}
+
+void f6(int *p, int *q) {
+  if (p != (int *)1)
+    if (p == (int *)1)
+      *p = 1; // no-warning
+
+  if (q == (int *)1)
+    if (q != (int *)1)
+      *q = 1; // no-warning
+}
+
+int* qux(int);
+
+int f7_1(unsigned len) {
+  assert (len != 0);
+  int *p = (int *)1;
+  unsigned i;
+
+  for (i = 0; i < len; ++i)
+   p = qux(i);
+
+  return *p++; // no-warning
+}
+
+int f7_2(unsigned len) {
+  assert (len > 0);  // note use of '>'
+  int *p = (int *)1;
+  unsigned i;
+
+  for (i = 0; i < len; ++i)
+   p = qux(i);
+
+  return *p++; // no-warning
+}
+
+struct f8_s {
+  int x;
+  int y[2];
+};
+
+void f8(struct f8_s *s, int coin) {
+  if (s != (struct f8_s *)7)
+    return;
+
+  if (coin)
+    s->x = 5; // expected-warning{{Access to field 'x' results in a dereference of a fixed address (loaded from variable 's')}}
+  else
+    s->y[1] = 6; // expected-warning{{Array access (via field 'y') results in a dereference of a fixed address}}
+}
+
+void f9() {
+  int (*p_function) (char, char) = (int (*)(char, char))0x04040; // FIXME: warn at this initialization
+  p_function = (int (*)(char, char))0x04080; // expected-warning {{Using a fixed address is not portable}}
+  // FIXME: there should be a warning from calling the function pointer with fixed address
+  int x = (*p_function) ('x', 'y');
+}
+
+#define AS_ATTRIBUTE volatile __attribute__((address_space(256)))
----------------
balazske wrote:

I copied the tests **from null-deref-ps.c**, probably even there the target is not set correctly (for this purpose), is `-triple x86_64-pc-linux-gnu` better option?

https://github.com/llvm/llvm-project/pull/127191


More information about the cfe-commits mailing list