llvm-project/clang/test/Analysis/kmalloc-linux.c
David Tarditi 8138d85f63
[analyzer] Update the undefined assignment checker diagnostics to not use the term 'garbage' (#126596)
A clang user pointed out that messages for the static analyzer undefined
assignment checker use the term ‘garbage’, which might have a negative
connotation to some users. This change updates the messages to use the
term ‘uninitialized’. This is the usual reason why a value is undefined
in the static analyzer and describes the logical error that a programmer
should take action to fix.

Out-of-bounds reads can also produce undefined values in the static
analyzer. The right long-term design is to have to the array bounds
checker cover out-of-bounds reads, so we do not cover that case in the
updated messages. The recent improvements to the array bounds checker
make it a candidate to add to the core set of checkers.

rdar://133418644
2025-02-26 13:57:33 +01:00

138 lines
2.8 KiB
C

// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux %s -verify \
// RUN: -Wno-incompatible-library-redeclaration \
// RUN: -analyzer-checker=core \
// RUN: -analyzer-checker=unix.Malloc
#define __GFP_ZERO 0x8000
#define NULL ((void *)0)
typedef __typeof(sizeof(int)) size_t;
void *kmalloc(size_t, int);
void kfree(void *);
struct test {
};
void foo(struct test *);
void test_zeroed(void) {
struct test **list, *t;
int i;
list = kmalloc(sizeof(*list) * 10, __GFP_ZERO);
if (list == NULL)
return;
for (i = 0; i < 10; i++) {
t = list[i];
foo(t);
}
kfree(list); // no-warning
}
void test_nonzero(void) {
struct test **list, *t;
int i;
list = kmalloc(sizeof(*list) * 10, 0);
if (list == NULL)
return;
for (i = 0; i < 10; i++) {
t = list[i]; // expected-warning{{uninitialized}}
foo(t);
}
kfree(list);
}
void test_indeterminate(int flags) {
struct test **list, *t;
int i;
list = kmalloc(sizeof(*list) * 10, flags);
if (list == NULL)
return;
for (i = 0; i < 10; i++) {
t = list[i]; // expected-warning{{uninitialized}}
foo(t);
}
kfree(list);
}
typedef unsigned long long uint64_t;
struct malloc_type;
// 3 parameter malloc:
// https://www.freebsd.org/cgi/man.cgi?query=malloc&sektion=9
void *malloc(unsigned long size, struct malloc_type *mtp, int flags);
void test_3arg_malloc(struct malloc_type *mtp) {
struct test **list, *t;
int i;
list = malloc(sizeof(*list) * 10, mtp, __GFP_ZERO);
if (list == NULL)
return;
for (i = 0; i < 10; i++) {
t = list[i];
foo(t);
}
kfree(list); // no-warning
}
void test_3arg_malloc_nonzero(struct malloc_type *mtp) {
struct test **list, *t;
int i;
list = malloc(sizeof(*list) * 10, mtp, 0);
if (list == NULL)
return;
for (i = 0; i < 10; i++) {
t = list[i]; // expected-warning{{uninitialized}}
foo(t);
}
kfree(list);
}
void test_3arg_malloc_indeterminate(struct malloc_type *mtp, int flags) {
struct test **list, *t;
int i;
list = malloc(sizeof(*list) * 10, mtp, flags);
if (list == NULL)
return;
for (i = 0; i < 10; i++) {
t = list[i]; // expected-warning{{uninitialized}}
foo(t);
}
kfree(list);
}
void test_3arg_malloc_leak(struct malloc_type *mtp, int flags) {
struct test **list;
list = malloc(sizeof(*list) * 10, mtp, flags);
if (list == NULL)
return;
} // expected-warning{{Potential leak of memory pointed to by 'list'}}
// kmalloc can return a constant value defined in ZERO_SIZE_PTR
// if a block of size 0 is requested
#define ZERO_SIZE_PTR ((void *)16)
void test_kfree_ZERO_SIZE_PTR(void) {
void *ptr = ZERO_SIZE_PTR;
kfree(ptr); // no warning about freeing this value
}
void test_kfree_other_constant_value(void) {
void *ptr = (void *)1;
kfree(ptr); // expected-warning{{Argument to 'kfree()' is a constant address (1)}}
}