| /* Verify the handling of anti-ranges/multi-ranges by allocation functions |
| and subsequent accesses. |
| { dg-do compile } |
| { dg-options "-O2" } */ |
| |
| typedef __SIZE_TYPE__ size_t; |
| |
| void* malloc (size_t); |
| void bzero (void*, size_t); |
| void* memset (void*, int, size_t); |
| |
| |
| /* Exercise size_t (via malloc and memset) and unsigned/signed int. */ |
| |
| __attribute__ ((alloc_size (1))) void* |
| alloc_int (int); |
| |
| __attribute__ ((access (write_only, 1, 2))) void |
| access_int (void*, int); |
| |
| __attribute__ ((alloc_size (1))) void* |
| alloc_uint (unsigned); |
| |
| __attribute__ ((access (write_only, 1, 2))) void |
| access_uint (void*, unsigned); |
| |
| |
| void* nowarn_malloc_memset_same_anti_range (size_t n) |
| { |
| /* Set N to the anti-range ~[3, 3]. */ |
| if (n == 3) |
| n = 4; |
| void *p = malloc (n); |
| |
| /* Verify there is no warning for an access to N bytes at P. |
| This means the warning has to assume the value of N in the call |
| to alloc() is in the larger subrange [4, UINT_MAX], while in |
| the call to access() in [0, 3]. */ |
| return memset (p, 0, n); |
| } |
| |
| /* Same as above but with two valid ranges. */ |
| |
| void* nowarn_malloc_memset_anti_range (size_t n1, size_t n2) |
| { |
| /* Set N1 to the anti-range ~[3, 3]. */ |
| if (n1 == 3) |
| n1 = 4; |
| void *p = malloc (n1); |
| |
| /* Set N2 to the anti-range ~[7, 7]. */ |
| if (n2 == 7) |
| n2 = 8; |
| |
| return memset (p, 0, n2); |
| } |
| |
| |
| void nowarn_alloc_access_same_anti_range_int (int n) |
| { |
| /* Set N to the anti-range ~[3, 3]. */ |
| if (n == 3) |
| n = 4; |
| void *p = alloc_int (n); |
| |
| /* Verify there is no warning for an access to N bytes at P. |
| This means the warning has to assume the value of N in the call |
| to alloc() is in the larger subrange [4, UINT_MAX], while in |
| the call to access() in [0, 3]. */ |
| access_int (p, n); |
| } |
| |
| /* Same as above but with two valid ranges. */ |
| |
| void nowarn_alloc_access_anti_range_int (int n1, int n2) |
| { |
| /* Set N1 to the anti-range ~[3, 3]. */ |
| if (n1 == 3) |
| n1 = 4; |
| void *p = alloc_int (n1); |
| |
| /* Set N2 to the anti-range ~[7, 7]. */ |
| if (n2 == 7) |
| n2 = 8; |
| |
| access_int (p, n2); |
| } |
| |
| |
| void nowarn_alloc_access_same_anti_range_uint (unsigned n) |
| { |
| /* Set N to the anti-range ~[3, 3]. */ |
| if (n == 3) |
| n = 4; |
| void *p = alloc_uint (n); |
| |
| /* Verify there is no warning for an access to N bytes at P. |
| This means the warning has to assume the value of N in the call |
| to alloc() is in the larger subrange [4, UINT_MAX], while in |
| the call to access() in [0, 3]. */ |
| access_uint (p, n); |
| } |
| |
| /* Same as above but with two valid ranges. */ |
| |
| void nowarn_alloc_access_anti_range_uint (unsigned n1, unsigned n2) |
| { |
| /* Set N1 to the anti-range ~[3, 3]. */ |
| if (n1 == 3) |
| n1 = 4; |
| void *p = alloc_uint (n1); |
| |
| /* Set N2 to the anti-range ~[7, 7]. */ |
| if (n2 == 7) |
| n2 = 8; |
| |
| access_uint (p, n2); |
| } |
| |
| |
| void* nowarn_malloc_anti_range_memset_range (size_t n1, size_t n2) |
| { |
| /* Set N1 to the anti-range ~[3, 3]. */ |
| if (n1 == 3) |
| n1 = 4; |
| void *p = malloc (n1); |
| |
| /* Set N2 to the range [5, MAX]. */ |
| if (n2 < 5) |
| n2 = 5; |
| return memset (p, 0, n2); |
| } |
| |
| void* nowarn_malloc_range_bzero_anti_range (size_t n1, size_t n2) |
| { |
| /* Set N1 to the anti-range ~[3, 3]. */ |
| if (n1 > 4) |
| n1 = 4; |
| void *p = malloc (n1); |
| |
| /* Set N2 to the range [5, MAX]. */ |
| if (n2 <= 3 || 5 <= n2) |
| n2 = 4; |
| bzero (p, n2); |
| return p; |
| } |