| Issue |
60926
|
| Summary |
-fsanitize=bounds missing bounds provided by __builtin_dynamic_object_size()
|
| Labels |
new issue
|
| Assignees |
isanbard
|
| Reporter |
kees
|
While `-fsanitize-bounds` is able to perform run-time bounds checking on fixed-size arrays (i.e. when `__builtin_object_size(x, 1)` does not return `SIZE_MAX`), it does not perform bounds checking when `__builtin_dynamic_object_size(x, 1)` is available.
For example, the attached program produces no bounds-checker warnings for the "dynamic size" case:
```
/* Build with -Wall -O2 -fstrict-flex-arrays=3 -fsanitize=bounds -fstrict-flex-arrays=3 */
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define noinline __attribute__((__noinline__))
volatile int zero = 0; /* used to stop optimizer from seeing constant expressions. */
#define report_size(p) do { \
const size_t bdos = __builtin_dynamic_object_size(p, 1); \
\
if (__builtin_constant_p(bdos)) { \
if (bdos == SIZE_MAX) { \
printf("\n" #p " has unknowable size\n"); \
} else { \
printf("\n" #p " has a fixed size: %zu (%zu elements of size %zu)\n", bdos, \
bdos / sizeof(*(p)), sizeof(*(p))); \
} \
} else { \
printf("\n" #p " has a dynamic size: %zu (%zu elements of size %zu)\n", bdos, \
bdos / sizeof(*(p)), sizeof(*(p))); \
} \
} while (0)
#define report_assignment(p, index, expect) \
printf(#p "[%d] assignment: %d (should be %s)\n", index, (p)[index] = 0xFF, expect)
#define MAX_INDEX 16
struct fixed {
unsigned long flags;
size_t foo;
int array[MAX_INDEX];
};
/* should emit "fixed" */
static void noinline do_fixed(struct fixed *p, int index)
{
report_size(p->array);
report_assignment(p->array, 0, "ok");
report_assignment(p->array, index, "failure");
}
struct flex {
unsigned long flags;
size_t foo;
int array[];
};
/* should emit "dynamic" */
static void noinline do_dynamic(unsigned char count, int index)
{
/* malloc() is marked with __attribute__((alloc_size(1))) */
struct flex *p = malloc(sizeof(*p) + (zero + count) * sizeof(*p->array));
report_size(p->array);
report_assignment(p->array, 0, "ok");
report_assignment(p->array, index, "failure");
free(p);
}
/* should emit "unknowable" */
static void noinline do_unknown(struct flex *p, int index)
{
report_size(p->array);
report_assignment(p->array, 0, "ignored");
report_assignment(p->array, index, "ignored");
}
int main(int argc, char *argv[])
{
int a;
struct fixed f;
int b;
struct flex *p;
int index = MAX_INDEX + zero;
a = b = argc; /* wrap "f" with an extra int to catch overflow writes */
do_fixed(&f, index + a - b);
do_dynamic(index, index);
p = malloc(100);
do_unknown(p, index);
free(p);
return 0;
}
```
```
$ gcc -Wall -O2 -fstrict-flex-arrays=3 -fsanitize=bounds -fstrict-flex-arrays=3 -o bounds bounds.c
$ ./bounds
p->array has a fixed size: 64 (16 elements of size 4)
p->array[0] assignment: 255 (should be ok)
bounds.c:43:5: runtime error: index 16 out of bounds for type 'int[16]'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior bounds.c:43:5 in
p->array[16] assignment: 255 (should be failure)
p->array has a dynamic size: 64 (16 elements of size 4)
p->array[0] assignment: 255 (should be ok)
p->array[16] assignment: 255 (should be failure)
p->array has unknowable size
p->array[0] assignment: 255 (should be ignored)
p->array[16] assignment: 255 (should be ignored)
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs