-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Open
Labels
Description
#115917 introduced a regression with the following code:
typedef struct { int error; } Status;
Status getError();
int global;
Status get(int **outptr) {
Status e = getError();
if (e.error != 0) return e; // field error is assumed to be non 0
*outptr = &global; // therefore this is not executed
return e;
}
int func() {
int *ptr = 0;
if (get(&ptr).error == 0) // field error is assumed to be 0
return *ptr; // therefore this is a null deref
return 0;
}
https://godbolt.org/z/seaaeMrTd
Another example with another Checker:
typedef struct {
int v;
} STATUS;
STATUS STATUS_OK = {0};
void use(const char* x);
STATUS get_two(const char** ret);
static STATUS get_one(const char** ret) {
STATUS status;
const char* s;
status = get_two(&s);
if (status.v != 0) {
return status;
}
*ret = s;
return STATUS_OK;
}
int main() {
STATUS status;
const char* s;
status = get_one(&s);
if (status.v == 0) {
use(s); // FP
}
}
https://godbolt.org/z/8x5Ghh95b
FYI The godbolt links show the difference between trunk and v19. I've done the bisection locally down to 4610e5c.
This issue impact many projects that have struct to represent error codes. I've often seen them wrapped with macros, such as in the Samba project. https://github.com/samba-team/samba/blob/7b5cc7d37f11347a606a4a9fe7f44ae43193318d/libcli/util/werror.h#L66