1 /* Test to exercise that -Warray-bounds warnings for memory and string 2 functions are issued even when they are declared in system headers 3 (i.e., not just when they are explicitly declared in the source 4 file.) 5 Also verify that the warnings are issued even for calls where the 6 source of the excessive array bound is in a different function than 7 the call. 8 { dg-do compile } 9 { dg-options "-O2 -Warray-bounds -Wno-stringop-overflow -fno-tree-vrp" } */ 10 11 #if __has_include (<stddef.h>) 12 # include <stddef.h> 13 #else 14 /* For cross-compilers. */ 15 typedef __PTRDIFF_TYPE__ ptrdiff_t; 16 typedef __SIZE_TYPE__ size_t; 17 #endif 18 19 #if __has_include (<string.h>) 20 # include <string.h> 21 # undef memcpy 22 # undef strcat 23 # undef strcpy 24 # undef strncpy 25 #else 26 extern void* memcpy (void*, const void*, size_t); 27 extern char* strcat (char*, const char*); 28 extern char* strcpy (char*, const char*); 29 extern char* strncpy (char*, const char*, size_t); 30 #endif 31 32 33 #define MAX (__SIZE_MAX__ / 2) 34 35 void sink (void*); 36 37 struct __attribute__ ((packed)) Array 38 { 39 char a13[13]; 40 char a15[15]; 41 char a17[17]; 42 }; 43 44 /* Exercise memcpy out-of-bounds offsets with an array of known size. */ 45 46 static void 47 wrap_memcpy_src_xsize (char *d, const char *s, ptrdiff_t i, size_t n) 48 { 49 memcpy (d, s + i, n); /* { dg-warning "offset 46 is out of the bounds \\\[0, 45] of object .ar. with type .(struct )?Array." "memcpy" } */ 50 } 51 52 void call_memcpy_src_xsize (char *d, size_t n) 53 { 54 struct Array ar; 55 sink (&ar); 56 wrap_memcpy_src_xsize (d, ar.a13, 46, n); 57 sink (&ar); 58 } 59 60 /* Exercise memcpy out-of-bounds offsets with an array of unknown size. */ 61 62 static void 63 wrap_memcpy_src_diff_max (char *d, const char *s, ptrdiff_t i, size_t n) 64 { 65 memcpy (d, s + i, n); /* { dg-warning "pointer overflow between offset \[0-9\]+ and size 3" "memcpy" } */ 66 } 67 68 void call_memcpy_src_diff_max (char *d, const char *s, size_t n) 69 { 70 wrap_memcpy_src_diff_max (d, s, MAX, 3); 71 } 72 73 static void 74 wrap_memcpy_dst_xsize (char *d, const char *s, ptrdiff_t i, size_t n) 75 { 76 memcpy (d + i, s, n); /* { dg-warning "offset 47 is out of the bounds \\\[0, 45] of object .ar1. with type .(struct )?Array." "memcpy" } */ 77 } 78 79 void call_memcpy_dst_xsize (const char *s, size_t n) 80 { 81 struct Array ar1; /* { dg-message ".ar1. declared here" } */ 82 sink (&ar1); 83 wrap_memcpy_dst_xsize (ar1.a15, s, 34, n); 84 sink (&ar1); 85 } 86 87 static void 88 wrap_memcpy_dst_diff_max (char *d, const char *s, ptrdiff_t i, size_t n) 89 { 90 memcpy (d + i, s, n); /* { dg-warning "offset -?\[0-9\]+ is out of the bounds \\\[0, 45] of object .ar2. with type .(struct )?Array." "memcpy" } */ 91 } 92 93 void call_memcpy_dst_diff_max (const char *s, size_t n) 94 { 95 struct Array ar2; /* { dg-message ".ar2. declared here" } */ 96 sink (&ar2); 97 wrap_memcpy_dst_diff_max (ar2.a15, s, MAX, n); 98 sink (&ar2); 99 } 100 101 102 static void wrap_strcat_src_xsize (char *d, const char *s, ptrdiff_t i) 103 { 104 strcat (d, s + i); /* { dg-warning "offset 46 is out of the bounds \\\[0, 45] of object .ar3. with type .(struct )?Array." "strcat" } */ 105 } 106 107 void call_strcat_src_xsize (char *d) 108 { 109 struct Array ar3; /* { dg-message ".ar3. declared here" } */ 110 sink (&ar3); 111 wrap_strcat_src_xsize (d, ar3.a15, 15 + 17 + 1); 112 sink (&ar3); 113 } 114 115 static void wrap_strcat_dst_xsize (char *d, const char *s, ptrdiff_t i) 116 { 117 strcat (d + i, s); /* { dg-warning "offset 47 is out of the bounds \\\[0, 45] of object .ar4. with type .(struct )?Array." "strcat" } */ 118 } 119 120 void call_strcat_dst_xsize (const char *s) 121 { 122 struct Array ar4; /* { dg-message ".ar4. declared here" } */ 123 sink (&ar4); 124 wrap_strcat_dst_xsize (ar4.a15, s, 15 + 17 + 2); 125 sink (&ar4); 126 } 127 128 129 static void wrap_strcpy_src_xsize (char *d, const char *s, ptrdiff_t i) 130 { 131 strcpy (d, s + i); /* { dg-warning "offset 48 is out of the bounds \\\[0, 45] of object .ar5. with type .(struct )?Array." "strcpy" } */ 132 } 133 134 void call_strcpy_src_xsize (char *d) 135 { 136 struct Array ar5; /* { dg-message ".ar5. declared here" } */ 137 sink (&ar5); 138 wrap_strcpy_src_xsize (d, ar5.a15, 15 + 17 + 3); 139 sink (&ar5); 140 } 141 142 static void wrap_strcpy_dst_xsize (char *d, const char *s, ptrdiff_t i) 143 { 144 strcpy (d + i, s); /* { dg-warning "offset 49 is out of the bounds \\\[0, 45] of object .ar6. with type .(struct )?Array." "strcpy" } */ 145 } 146 147 void call_strcpy_dst_xsize (const char *s) 148 { 149 struct Array ar6; /* { dg-message ".ar6. declared here" } */ 150 sink (&ar6); 151 wrap_strcpy_dst_xsize (ar6.a15, s, 15 + 17 + 4); 152 sink (&ar6); 153 } 154 155 156 /* Exercise strncpy out-of-bounds offsets with an array of known size. */ 157 158 static void 159 wrap_strncpy_src_xsize (char *d, const char *s, ptrdiff_t i, size_t n) 160 { 161 strncpy (d, s + i, n); /* { dg-warning "offset 46 is out of the bounds \\\[0, 45] of object .ar7. with type '(struct )?Array." "strncpy" } */ 162 } 163 164 void call_strncpy_src_xsize (char *d, size_t n) 165 { 166 struct Array ar7; /* { dg-message ".ar7. declared here" } */ 167 sink (&ar7); 168 wrap_strncpy_src_xsize (d, ar7.a17, 17 + 1, n); 169 sink (&ar7); 170 } 171 172 /* Exercise strncpy out-of-bounds offsets with an array of unknown size. */ 173 174 static void 175 wrap_strncpy_src_diff_max_m1 (char *d, const char *s, ptrdiff_t i, size_t n) 176 { 177 /* Unlike in the similar call to memcpy(), there is no pointer 178 overflow here because the size N is not added to the source 179 offset MAX - 1 (only 1 is for the access to its first element, 180 which is tested below). */ 181 strncpy (d, s + i, n); 182 } 183 184 void call_strncpy_src_diff_max_m1 (char *d, const char *s, size_t n) 185 { 186 wrap_strncpy_src_diff_max_m1 (d, s, MAX - 1, 3); 187 } 188 189 static void 190 wrap_strncpy_src_diff_max (char *d, const char *s, ptrdiff_t i, size_t n) 191 { 192 strncpy (d, s + i, n); /* { dg-warning "pointer overflow between offset \[0-9\]+ and size \\\[1, 0]" } */ 193 } 194 195 void call_strncpy_src_diff_max (char *d, const char *s, size_t n) 196 { 197 wrap_strncpy_src_diff_max (d, s, MAX, 3); 198 } 199 200 static void 201 wrap_strncpy_dst_xsize (char *d, const char *s, ptrdiff_t i, size_t n) 202 { 203 strncpy (d + i, s, n); /* { dg-warning "offset 47 is out of the bounds \\\[0, 45] of object .ar8. with type .(struct )?Array." "strncpy" } */ 204 } 205 206 void call_strncpy_dst_xsize (const char *s, size_t n) 207 { 208 struct Array ar8; /* { dg-message ".ar8. declared here" } */ 209 sink (&ar8); 210 wrap_strncpy_dst_xsize (ar8.a17, s, 17 + 2, n); 211 sink (&ar8); 212 } 213 214 static void 215 wrap_strncpy_dst_diff_max (char *d, const char *s, ptrdiff_t i, size_t n) 216 { 217 strncpy (d + i, s, n); /* { dg-warning "offset -\[0-9\]+ is out of the bounds \\\[0, 45] of object .ar9. with type .(struct )?Array." "strncpy" } */ 218 } 219 220 void call_strncpy_dst_diff_max (const char *s, size_t n) 221 { 222 struct Array ar9; /* { dg-message ".ar9. declared here" "strncpy" } */ 223 sink (&ar9); 224 wrap_strncpy_dst_diff_max (ar9.a17, s, MAX, n); 225 sink (&ar9); 226 } 227 228 static void 229 wrap_strncpy_dstarray_diff_neg (char *d, const char *s, ptrdiff_t i, size_t n) 230 { 231 strncpy (d + i, s, n); /* { dg-warning "offset -\[0-9\]+ is out of the bounds \\\[0, 90] of object .ar10. with type .(struct )?Array ?\\\[2]." "strncpy" } */ 232 } 233 234 void call_strncpy_dstarray_diff_neg (const char *s, size_t n) 235 { 236 struct Array ar10[2]; /* { dg-message ".ar10. declared here" } */ 237 sink (&ar10); 238 239 int off = (char*)ar10[1].a17 - (char*)ar10 + 1; 240 wrap_strncpy_dstarray_diff_neg (ar10[1].a17, s, -off, n); 241 242 sink (&ar10); 243 } 244