Mercurial > hg > CbC > CbC_gcc
comparison gcc/gimple-ssa-warn-restrict.c @ 132:d34655255c78
update gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 10:21:07 +0900 |
parents | 84e7813d76e9 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
130:e108057fa461 | 132:d34655255c78 |
---|---|
1 /* Pass to detect and issue warnings for violations of the restrict | |
2 qualifier. | |
3 Copyright (C) 2017-2018 Free Software Foundation, Inc. | |
4 Contributed by Martin Sebor <msebor@redhat.com>. | |
5 | |
6 This file is part of GCC. | |
7 | |
8 GCC is free software; you can redistribute it and/or modify it under | |
9 the terms of the GNU General Public License as published by the Free | |
10 Software Foundation; either version 3, or (at your option) any later | |
11 version. | |
12 | |
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with GCC; see the file COPYING3. If not see | |
20 <http://www.gnu.org/licenses/>. */ | |
21 | |
22 #include "config.h" | |
23 #include "system.h" | |
24 #include "coretypes.h" | |
25 #include "backend.h" | |
26 #include "tree.h" | |
27 #include "gimple.h" | |
28 #include "domwalk.h" | |
29 #include "tree-pass.h" | |
30 #include "builtins.h" | |
31 #include "ssa.h" | |
32 #include "gimple-pretty-print.h" | |
33 #include "gimple-ssa-warn-restrict.h" | |
34 #include "diagnostic-core.h" | |
35 #include "fold-const.h" | |
36 #include "gimple-iterator.h" | |
37 #include "tree-dfa.h" | |
38 #include "tree-ssa.h" | |
39 #include "params.h" | |
40 #include "tree-cfg.h" | |
41 #include "tree-object-size.h" | |
42 #include "calls.h" | |
43 #include "cfgloop.h" | |
44 #include "intl.h" | |
45 | |
46 namespace { | |
47 | |
48 const pass_data pass_data_wrestrict = { | |
49 GIMPLE_PASS, | |
50 "wrestrict", | |
51 OPTGROUP_NONE, | |
52 TV_NONE, | |
53 PROP_cfg, /* Properties_required. */ | |
54 0, /* properties_provided. */ | |
55 0, /* properties_destroyed. */ | |
56 0, /* properties_start */ | |
57 0, /* properties_finish */ | |
58 }; | |
59 | |
60 /* Pass to detect violations of strict aliasing requirements in calls | |
61 to built-in string and raw memory functions. */ | |
62 class pass_wrestrict : public gimple_opt_pass | |
63 { | |
64 public: | |
65 pass_wrestrict (gcc::context *ctxt) | |
66 : gimple_opt_pass (pass_data_wrestrict, ctxt) | |
67 { } | |
68 | |
69 opt_pass *clone () { return new pass_wrestrict (m_ctxt); } | |
70 | |
71 virtual bool gate (function *); | |
72 virtual unsigned int execute (function *); | |
73 }; | |
74 | |
75 bool | |
76 pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED) | |
77 { | |
78 return warn_array_bounds != 0 || warn_restrict != 0; | |
79 } | |
80 | |
81 /* Class to walk the basic blocks of a function in dominator order. */ | |
82 class wrestrict_dom_walker : public dom_walker | |
83 { | |
84 public: | |
85 wrestrict_dom_walker () : dom_walker (CDI_DOMINATORS) {} | |
86 | |
87 edge before_dom_children (basic_block) FINAL OVERRIDE; | |
88 bool handle_gimple_call (gimple_stmt_iterator *); | |
89 | |
90 private: | |
91 void check_call (gimple *); | |
92 }; | |
93 | |
94 edge | |
95 wrestrict_dom_walker::before_dom_children (basic_block bb) | |
96 { | |
97 /* Iterate over statements, looking for function calls. */ | |
98 for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); | |
99 gsi_next (&si)) | |
100 { | |
101 gimple *stmt = gsi_stmt (si); | |
102 if (!is_gimple_call (stmt)) | |
103 continue; | |
104 | |
105 check_call (stmt); | |
106 } | |
107 | |
108 return NULL; | |
109 } | |
110 | |
111 /* Execute the pass for function FUN, walking in dominator order. */ | |
112 | |
113 unsigned | |
114 pass_wrestrict::execute (function *fun) | |
115 { | |
116 calculate_dominance_info (CDI_DOMINATORS); | |
117 | |
118 wrestrict_dom_walker walker; | |
119 walker.walk (ENTRY_BLOCK_PTR_FOR_FN (fun)); | |
120 | |
121 return 0; | |
122 } | |
123 | |
124 /* Description of a memory reference by a built-in function. This | |
125 is similar to ao_ref but made especially suitable for -Wrestrict | |
126 and not for optimization. */ | |
127 struct builtin_memref | |
128 { | |
129 /* The original pointer argument to the built-in function. */ | |
130 tree ptr; | |
131 /* The referenced subobject or NULL if not available, and the base | |
132 object of the memory reference or NULL. */ | |
133 tree ref; | |
134 tree base; | |
135 | |
136 /* The size of the BASE object, PTRDIFF_MAX if indeterminate, | |
137 and negative until (possibly lazily) initialized. */ | |
138 offset_int basesize; | |
139 | |
140 /* The non-negative offset of the referenced subobject. Used to avoid | |
141 warnings for (apparently) possibly but not definitively overlapping | |
142 accesses to member arrays. Negative when unknown/invalid. */ | |
143 offset_int refoff; | |
144 | |
145 /* The offset range relative to the base. */ | |
146 offset_int offrange[2]; | |
147 /* The size range of the access to this reference. */ | |
148 offset_int sizrange[2]; | |
149 | |
150 /* True for "bounded" string functions like strncat, and strncpy | |
151 and their variants that specify either an exact or upper bound | |
152 on the size of the accesses they perform. For strncat both | |
153 the source and destination references are bounded. For strncpy | |
154 only the destination reference is. */ | |
155 bool strbounded_p; | |
156 | |
157 builtin_memref (tree, tree); | |
158 | |
159 tree offset_out_of_bounds (int, offset_int[2]) const; | |
160 | |
161 private: | |
162 | |
163 /* Ctor helper to set or extend OFFRANGE based on argument. */ | |
164 void extend_offset_range (tree); | |
165 | |
166 /* Ctor helper to determine BASE and OFFRANGE from argument. */ | |
167 void set_base_and_offset (tree); | |
168 }; | |
169 | |
170 /* Description of a memory access by a raw memory or string built-in | |
171 function involving a pair of builtin_memref's. */ | |
172 class builtin_access | |
173 { | |
174 public: | |
175 /* Destination and source memory reference. */ | |
176 builtin_memref* const dstref; | |
177 builtin_memref* const srcref; | |
178 /* The size range of the access. It's the greater of the accesses | |
179 to the two references. */ | |
180 HOST_WIDE_INT sizrange[2]; | |
181 | |
182 /* The minimum and maximum offset of an overlap of the access | |
183 (if it does, in fact, overlap), and the size of the overlap. */ | |
184 HOST_WIDE_INT ovloff[2]; | |
185 HOST_WIDE_INT ovlsiz[2]; | |
186 | |
187 /* True to consider valid only accesses to the smallest subobject | |
188 and false for raw memory functions. */ | |
189 bool strict () const | |
190 { | |
191 return detect_overlap != &builtin_access::generic_overlap; | |
192 } | |
193 | |
194 builtin_access (gimple *, builtin_memref &, builtin_memref &); | |
195 | |
196 /* Entry point to determine overlap. */ | |
197 bool overlap (); | |
198 | |
199 private: | |
200 /* Implementation functions used to determine overlap. */ | |
201 bool generic_overlap (); | |
202 bool strcat_overlap (); | |
203 bool strcpy_overlap (); | |
204 | |
205 bool no_overlap () | |
206 { | |
207 return false; | |
208 } | |
209 | |
210 offset_int overlap_size (const offset_int [2], const offset_int[2], | |
211 offset_int [2]); | |
212 | |
213 private: | |
214 /* Temporaries used to compute the final result. */ | |
215 offset_int dstoff[2]; | |
216 offset_int srcoff[2]; | |
217 offset_int dstsiz[2]; | |
218 offset_int srcsiz[2]; | |
219 | |
220 /* Pointer to a member function to call to determine overlap. */ | |
221 bool (builtin_access::*detect_overlap) (); | |
222 }; | |
223 | |
224 /* Initialize a memory reference representation from a pointer EXPR and | |
225 a size SIZE in bytes. If SIZE is NULL_TREE then the size is assumed | |
226 to be unknown. */ | |
227 | |
228 builtin_memref::builtin_memref (tree expr, tree size) | |
229 : ptr (expr), | |
230 ref (), | |
231 base (), | |
232 basesize (-1), | |
233 refoff (HOST_WIDE_INT_MIN), | |
234 offrange (), | |
235 sizrange (), | |
236 strbounded_p () | |
237 { | |
238 /* Unfortunately, wide_int default ctor is a no-op so array members | |
239 of the type must be set individually. */ | |
240 offrange[0] = offrange[1] = 0; | |
241 sizrange[0] = sizrange[1] = 0; | |
242 | |
243 const offset_int maxobjsize = tree_to_shwi (max_object_size ()); | |
244 | |
245 /* Find the BASE object or pointer referenced by EXPR and set | |
246 the offset range OFFRANGE in the process. */ | |
247 set_base_and_offset (expr); | |
248 | |
249 if (size) | |
250 { | |
251 tree range[2]; | |
252 /* Determine the size range, allowing for the result to be [0, 0] | |
253 for SIZE in the anti-range ~[0, N] where N >= PTRDIFF_MAX. */ | |
254 get_size_range (size, range, true); | |
255 sizrange[0] = wi::to_offset (range[0]); | |
256 sizrange[1] = wi::to_offset (range[1]); | |
257 /* get_size_range returns SIZE_MAX for the maximum size. | |
258 Constrain it to the real maximum of PTRDIFF_MAX. */ | |
259 if (sizrange[1] > maxobjsize) | |
260 sizrange[1] = maxobjsize; | |
261 } | |
262 else | |
263 sizrange[1] = maxobjsize; | |
264 | |
265 if (!DECL_P (base)) | |
266 return; | |
267 | |
268 /* If the offset could be in the range of the referenced object | |
269 constrain its bounds so neither exceeds those of the object. */ | |
270 if (offrange[0] < 0 && offrange[1] > 0) | |
271 offrange[0] = 0; | |
272 | |
273 offset_int maxoff = maxobjsize; | |
274 tree basetype = TREE_TYPE (base); | |
275 if (TREE_CODE (basetype) == ARRAY_TYPE | |
276 && ref | |
277 && array_at_struct_end_p (ref)) | |
278 ; /* Use the maximum possible offset for last member arrays. */ | |
279 else if (tree basesize = TYPE_SIZE_UNIT (basetype)) | |
280 if (TREE_CODE (basesize) == INTEGER_CST) | |
281 /* Size could be non-constant for a variable-length type such | |
282 as a struct with a VLA member (a GCC extension). */ | |
283 maxoff = wi::to_offset (basesize); | |
284 | |
285 if (offrange[0] >= 0) | |
286 { | |
287 if (offrange[1] < 0) | |
288 offrange[1] = offrange[0] <= maxoff ? maxoff : maxobjsize; | |
289 else if (offrange[0] <= maxoff && offrange[1] > maxoff) | |
290 offrange[1] = maxoff; | |
291 } | |
292 } | |
293 | |
294 /* Ctor helper to set or extend OFFRANGE based on the OFFSET argument. */ | |
295 | |
296 void | |
297 builtin_memref::extend_offset_range (tree offset) | |
298 { | |
299 const offset_int maxobjsize = tree_to_shwi (max_object_size ()); | |
300 | |
301 if (TREE_CODE (offset) == INTEGER_CST) | |
302 { | |
303 offset_int off = int_cst_value (offset); | |
304 if (off != 0) | |
305 { | |
306 offrange[0] += off; | |
307 offrange[1] += off; | |
308 } | |
309 return; | |
310 } | |
311 | |
312 if (TREE_CODE (offset) == SSA_NAME) | |
313 { | |
314 wide_int min, max; | |
315 value_range_kind rng = get_range_info (offset, &min, &max); | |
316 if (rng == VR_RANGE) | |
317 { | |
318 offrange[0] += offset_int::from (min, SIGNED); | |
319 offrange[1] += offset_int::from (max, SIGNED); | |
320 } | |
321 else if (rng == VR_ANTI_RANGE) | |
322 { | |
323 offrange[0] += offset_int::from (max + 1, SIGNED); | |
324 offrange[1] += offset_int::from (min - 1, SIGNED); | |
325 } | |
326 else | |
327 { | |
328 gimple *stmt = SSA_NAME_DEF_STMT (offset); | |
329 tree type; | |
330 if (is_gimple_assign (stmt) | |
331 && gimple_assign_rhs_code (stmt) == NOP_EXPR | |
332 && (type = TREE_TYPE (gimple_assign_rhs1 (stmt))) | |
333 && INTEGRAL_TYPE_P (type)) | |
334 { | |
335 /* Use the bounds of the type of the NOP_EXPR operand | |
336 even if it's signed. The result doesn't trigger | |
337 warnings but makes their output more readable. */ | |
338 offrange[0] += wi::to_offset (TYPE_MIN_VALUE (type)); | |
339 offrange[1] += wi::to_offset (TYPE_MAX_VALUE (type)); | |
340 } | |
341 else | |
342 offrange[1] += maxobjsize; | |
343 } | |
344 return; | |
345 } | |
346 | |
347 offrange[1] += maxobjsize; | |
348 } | |
349 | |
350 /* Determines the base object or pointer of the reference EXPR | |
351 and the offset range from the beginning of the base. */ | |
352 | |
353 void | |
354 builtin_memref::set_base_and_offset (tree expr) | |
355 { | |
356 const offset_int maxobjsize = tree_to_shwi (max_object_size ()); | |
357 | |
358 if (TREE_CODE (expr) == SSA_NAME) | |
359 { | |
360 /* Try to tease the offset out of the pointer. */ | |
361 gimple *stmt = SSA_NAME_DEF_STMT (expr); | |
362 if (!base | |
363 && gimple_assign_single_p (stmt) | |
364 && gimple_assign_rhs_code (stmt) == ADDR_EXPR) | |
365 expr = gimple_assign_rhs1 (stmt); | |
366 else if (is_gimple_assign (stmt)) | |
367 { | |
368 tree_code code = gimple_assign_rhs_code (stmt); | |
369 if (code == NOP_EXPR) | |
370 { | |
371 tree rhs = gimple_assign_rhs1 (stmt); | |
372 if (POINTER_TYPE_P (TREE_TYPE (rhs))) | |
373 expr = gimple_assign_rhs1 (stmt); | |
374 else | |
375 { | |
376 base = expr; | |
377 return; | |
378 } | |
379 } | |
380 else if (code == POINTER_PLUS_EXPR) | |
381 { | |
382 expr = gimple_assign_rhs1 (stmt); | |
383 | |
384 tree offset = gimple_assign_rhs2 (stmt); | |
385 extend_offset_range (offset); | |
386 } | |
387 else | |
388 { | |
389 base = expr; | |
390 return; | |
391 } | |
392 } | |
393 else | |
394 { | |
395 base = expr; | |
396 return; | |
397 } | |
398 } | |
399 | |
400 if (TREE_CODE (expr) == ADDR_EXPR) | |
401 expr = TREE_OPERAND (expr, 0); | |
402 | |
403 /* Stash the reference for offset validation. */ | |
404 ref = expr; | |
405 | |
406 poly_int64 bitsize, bitpos; | |
407 tree var_off; | |
408 machine_mode mode; | |
409 int sign, reverse, vol; | |
410 | |
411 /* Determine the base object or pointer of the reference and | |
412 the constant bit offset from the beginning of the base. | |
413 If the offset has a non-constant component, it will be in | |
414 VAR_OFF. MODE, SIGN, REVERSE, and VOL are write only and | |
415 unused here. */ | |
416 base = get_inner_reference (expr, &bitsize, &bitpos, &var_off, | |
417 &mode, &sign, &reverse, &vol); | |
418 | |
419 /* get_inner_reference is not expected to return null. */ | |
420 gcc_assert (base != NULL); | |
421 | |
422 poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT); | |
423 | |
424 /* Convert the poly_int64 offset to offset_int. The offset | |
425 should be constant but be prepared for it not to be just in | |
426 case. */ | |
427 offset_int cstoff; | |
428 if (bytepos.is_constant (&cstoff)) | |
429 { | |
430 offrange[0] += cstoff; | |
431 offrange[1] += cstoff; | |
432 | |
433 /* Besides the reference saved above, also stash the offset | |
434 for validation. */ | |
435 if (TREE_CODE (expr) == COMPONENT_REF) | |
436 refoff = cstoff; | |
437 } | |
438 else | |
439 offrange[1] += maxobjsize; | |
440 | |
441 if (var_off) | |
442 { | |
443 if (TREE_CODE (var_off) == INTEGER_CST) | |
444 { | |
445 cstoff = wi::to_offset (var_off); | |
446 offrange[0] += cstoff; | |
447 offrange[1] += cstoff; | |
448 } | |
449 else | |
450 offrange[1] += maxobjsize; | |
451 } | |
452 | |
453 if (TREE_CODE (base) == MEM_REF) | |
454 { | |
455 tree memrefoff = TREE_OPERAND (base, 1); | |
456 extend_offset_range (memrefoff); | |
457 base = TREE_OPERAND (base, 0); | |
458 } | |
459 | |
460 if (TREE_CODE (base) == SSA_NAME) | |
461 set_base_and_offset (base); | |
462 } | |
463 | |
464 /* Return error_mark_node if the signed offset exceeds the bounds | |
465 of the address space (PTRDIFF_MAX). Otherwise, return either | |
466 BASE or REF when the offset exceeds the bounds of the BASE or | |
467 REF object, and set OOBOFF to the past-the-end offset formed | |
468 by the reference, including its size. When STRICT is non-zero | |
469 use REF size, when available, otherwise use BASE size. When | |
470 STRICT is greater than 1, use the size of the last array member | |
471 as the bound, otherwise treat such a member as a flexible array | |
472 member. Return NULL when the offset is in bounds. */ | |
473 | |
474 tree | |
475 builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[2]) const | |
476 { | |
477 const offset_int maxobjsize = tree_to_shwi (max_object_size ()); | |
478 | |
479 /* A temporary, possibly adjusted, copy of the offset range. */ | |
480 offset_int offrng[2] = { offrange[0], offrange[1] }; | |
481 | |
482 if (DECL_P (base) && TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE) | |
483 { | |
484 /* Check for offset in an anti-range with a negative lower bound. | |
485 For such a range, consider only the non-negative subrange. */ | |
486 if (offrng[1] < offrng[0] && offrng[1] < 0) | |
487 offrng[1] = maxobjsize; | |
488 } | |
489 | |
490 /* Conservative offset of the last byte of the referenced object. */ | |
491 offset_int endoff; | |
492 | |
493 /* The bounds need not be ordered. Set HIB to use as the index | |
494 of the larger of the bounds and LOB as the opposite. */ | |
495 bool hib = wi::les_p (offrng[0], offrng[1]); | |
496 bool lob = !hib; | |
497 | |
498 if (basesize < 0) | |
499 { | |
500 endoff = offrng[lob] + sizrange[0]; | |
501 | |
502 /* For a reference through a pointer to an object of unknown size | |
503 all initial offsets are considered valid, positive as well as | |
504 negative, since the pointer itself can point past the beginning | |
505 of the object. However, the sum of the lower bound of the offset | |
506 and that of the size must be less than or equal than PTRDIFF_MAX. */ | |
507 if (endoff > maxobjsize) | |
508 return error_mark_node; | |
509 | |
510 return NULL_TREE; | |
511 } | |
512 | |
513 /* A reference to an object of known size must be within the bounds | |
514 of the base object. */ | |
515 if (offrng[hib] < 0 || offrng[lob] > basesize) | |
516 return base; | |
517 | |
518 /* The extent of the reference must also be within the bounds of | |
519 the base object (if known) or the maximum object size otherwise. */ | |
520 endoff = wi::smax (offrng[lob], 0) + sizrange[0]; | |
521 if (endoff > maxobjsize) | |
522 return error_mark_node; | |
523 | |
524 offset_int size = basesize; | |
525 tree obj = base; | |
526 | |
527 if (strict | |
528 && DECL_P (obj) | |
529 && ref | |
530 && refoff >= 0 | |
531 && TREE_CODE (ref) == COMPONENT_REF | |
532 && (strict > 1 | |
533 || !array_at_struct_end_p (ref))) | |
534 { | |
535 /* If the reference is to a member subobject, the offset must | |
536 be within the bounds of the subobject. */ | |
537 tree field = TREE_OPERAND (ref, 1); | |
538 tree type = TREE_TYPE (field); | |
539 if (tree sz = TYPE_SIZE_UNIT (type)) | |
540 if (TREE_CODE (sz) == INTEGER_CST) | |
541 { | |
542 size = refoff + wi::to_offset (sz); | |
543 obj = ref; | |
544 } | |
545 } | |
546 | |
547 if (endoff <= size) | |
548 return NULL_TREE; | |
549 | |
550 /* Set the out-of-bounds offset range to be one greater than | |
551 that delimited by the reference including its size. */ | |
552 ooboff[lob] = size + 1; | |
553 | |
554 if (endoff > ooboff[lob]) | |
555 ooboff[hib] = endoff; | |
556 else | |
557 ooboff[hib] = wi::smax (offrng[lob], 0) + sizrange[1]; | |
558 | |
559 return obj; | |
560 } | |
561 | |
562 /* Create an association between the memory references DST and SRC | |
563 for access by a call EXPR to a memory or string built-in funtion. */ | |
564 | |
565 builtin_access::builtin_access (gimple *call, builtin_memref &dst, | |
566 builtin_memref &src) | |
567 : dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (), | |
568 dstoff (), srcoff (), dstsiz (), srcsiz () | |
569 { | |
570 /* Zero out since the offset_int ctors invoked above are no-op. */ | |
571 dstoff[0] = dstoff[1] = 0; | |
572 srcoff[0] = srcoff[1] = 0; | |
573 dstsiz[0] = dstsiz[1] = 0; | |
574 srcsiz[0] = srcsiz[1] = 0; | |
575 | |
576 /* Object Size Type to use to determine the size of the destination | |
577 and source objects. Overridden below for raw memory functions. */ | |
578 int ostype = 1; | |
579 | |
580 /* True when the size of one reference depends on the offset of | |
581 itself or the other. */ | |
582 bool depends_p = true; | |
583 | |
584 /* True when the size of the destination reference DSTREF has been | |
585 determined from SRCREF and so needs to be adjusted by the latter's | |
586 offset. Only meaningful for bounded string functions like strncpy. */ | |
587 bool dstadjust_p = false; | |
588 | |
589 /* The size argument number (depends on the built-in). */ | |
590 unsigned sizeargno = 2; | |
591 | |
592 tree func = gimple_call_fndecl (call); | |
593 switch (DECL_FUNCTION_CODE (func)) | |
594 { | |
595 case BUILT_IN_MEMCPY: | |
596 case BUILT_IN_MEMCPY_CHK: | |
597 case BUILT_IN_MEMPCPY: | |
598 case BUILT_IN_MEMPCPY_CHK: | |
599 ostype = 0; | |
600 depends_p = false; | |
601 detect_overlap = &builtin_access::generic_overlap; | |
602 break; | |
603 | |
604 case BUILT_IN_MEMMOVE: | |
605 case BUILT_IN_MEMMOVE_CHK: | |
606 /* For memmove there is never any overlap to check for. */ | |
607 ostype = 0; | |
608 depends_p = false; | |
609 detect_overlap = &builtin_access::no_overlap; | |
610 break; | |
611 | |
612 case BUILT_IN_STPNCPY: | |
613 case BUILT_IN_STPNCPY_CHK: | |
614 case BUILT_IN_STRNCPY: | |
615 case BUILT_IN_STRNCPY_CHK: | |
616 dstref->strbounded_p = true; | |
617 detect_overlap = &builtin_access::strcpy_overlap; | |
618 break; | |
619 | |
620 case BUILT_IN_STPCPY: | |
621 case BUILT_IN_STPCPY_CHK: | |
622 case BUILT_IN_STRCPY: | |
623 case BUILT_IN_STRCPY_CHK: | |
624 detect_overlap = &builtin_access::strcpy_overlap; | |
625 break; | |
626 | |
627 case BUILT_IN_STRCAT: | |
628 case BUILT_IN_STRCAT_CHK: | |
629 detect_overlap = &builtin_access::strcat_overlap; | |
630 break; | |
631 | |
632 case BUILT_IN_STRNCAT: | |
633 case BUILT_IN_STRNCAT_CHK: | |
634 dstref->strbounded_p = true; | |
635 srcref->strbounded_p = true; | |
636 detect_overlap = &builtin_access::strcat_overlap; | |
637 break; | |
638 | |
639 default: | |
640 /* Handle other string functions here whose access may need | |
641 to be validated for in-bounds offsets and non-overlapping | |
642 copies. */ | |
643 return; | |
644 } | |
645 | |
646 const offset_int maxobjsize = tree_to_shwi (max_object_size ()); | |
647 | |
648 /* Try to determine the size of the base object. compute_objsize | |
649 expects a pointer so create one if BASE is a non-pointer object. */ | |
650 tree addr; | |
651 if (dst.basesize < 0) | |
652 { | |
653 addr = dst.base; | |
654 if (!POINTER_TYPE_P (TREE_TYPE (addr))) | |
655 addr = build1 (ADDR_EXPR, (TREE_TYPE (addr)), addr); | |
656 | |
657 if (tree dstsize = compute_objsize (addr, ostype)) | |
658 dst.basesize = wi::to_offset (dstsize); | |
659 else if (POINTER_TYPE_P (TREE_TYPE (addr))) | |
660 dst.basesize = HOST_WIDE_INT_MIN; | |
661 else | |
662 dst.basesize = maxobjsize; | |
663 } | |
664 | |
665 if (src.basesize < 0) | |
666 { | |
667 addr = src.base; | |
668 if (!POINTER_TYPE_P (TREE_TYPE (addr))) | |
669 addr = build1 (ADDR_EXPR, (TREE_TYPE (addr)), addr); | |
670 | |
671 if (tree srcsize = compute_objsize (addr, ostype)) | |
672 src.basesize = wi::to_offset (srcsize); | |
673 else if (POINTER_TYPE_P (TREE_TYPE (addr))) | |
674 src.basesize = HOST_WIDE_INT_MIN; | |
675 else | |
676 src.basesize = maxobjsize; | |
677 } | |
678 | |
679 /* If there is no dependency between the references or the base | |
680 objects of the two references aren't the same there's nothing | |
681 else to do. */ | |
682 if (depends_p && dstref->base != srcref->base) | |
683 return; | |
684 | |
685 /* ...otherwise, make adjustments for references to the same object | |
686 by string built-in functions to reflect the constraints imposed | |
687 by the function. */ | |
688 | |
689 /* For bounded string functions determine the range of the bound | |
690 on the access. For others, the range stays unbounded. */ | |
691 offset_int bounds[2] = { maxobjsize, maxobjsize }; | |
692 if (dstref->strbounded_p) | |
693 { | |
694 tree size = gimple_call_arg (call, sizeargno); | |
695 tree range[2]; | |
696 if (get_size_range (size, range, true)) | |
697 { | |
698 bounds[0] = wi::to_offset (range[0]); | |
699 bounds[1] = wi::to_offset (range[1]); | |
700 } | |
701 | |
702 /* If both references' size ranges are indeterminate use the last | |
703 (size) argument from the function call as a substitute. This | |
704 may only be necessary for strncpy (but not for memcpy where | |
705 the size range would have been already determined this way). */ | |
706 if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize | |
707 && srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize) | |
708 { | |
709 dstref->sizrange[0] = bounds[0]; | |
710 dstref->sizrange[1] = bounds[1]; | |
711 } | |
712 } | |
713 | |
714 /* The size range of one reference involving the same base object | |
715 can be determined from the size range of the other reference. | |
716 This makes it possible to compute accurate offsets for warnings | |
717 involving functions like strcpy where the length of just one of | |
718 the two arguments is known (determined by tree-ssa-strlen). */ | |
719 if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize) | |
720 { | |
721 /* When the destination size is unknown set it to the size of | |
722 the source. */ | |
723 dstref->sizrange[0] = srcref->sizrange[0]; | |
724 dstref->sizrange[1] = srcref->sizrange[1]; | |
725 } | |
726 else if (srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize) | |
727 { | |
728 /* When the source size is unknown set it to the size of | |
729 the destination. */ | |
730 srcref->sizrange[0] = dstref->sizrange[0]; | |
731 srcref->sizrange[1] = dstref->sizrange[1]; | |
732 | |
733 if (depends_p) | |
734 { | |
735 if (dstref->strbounded_p) | |
736 { | |
737 /* Read access by strncpy is bounded. */ | |
738 if (bounds[0] < srcref->sizrange[0]) | |
739 srcref->sizrange[0] = bounds[0]; | |
740 if (bounds[1] < srcref->sizrange[1]) | |
741 srcref->sizrange[1] = bounds[1]; | |
742 } | |
743 | |
744 /* For string functions, adjust the size range of the source | |
745 reference by the inverse boundaries of the offset (because | |
746 the higher the offset into the string the shorter its | |
747 length). */ | |
748 if (srcref->offrange[1] >= 0 | |
749 && srcref->offrange[1] < srcref->sizrange[0]) | |
750 srcref->sizrange[0] -= srcref->offrange[1]; | |
751 else | |
752 srcref->sizrange[0] = 0; | |
753 | |
754 if (srcref->offrange[0] > 0) | |
755 { | |
756 if (srcref->offrange[0] < srcref->sizrange[1]) | |
757 srcref->sizrange[1] -= srcref->offrange[0]; | |
758 else | |
759 srcref->sizrange[1] = 0; | |
760 } | |
761 | |
762 dstadjust_p = true; | |
763 } | |
764 } | |
765 | |
766 if (detect_overlap == &builtin_access::generic_overlap) | |
767 { | |
768 if (dstref->strbounded_p) | |
769 { | |
770 dstref->sizrange[0] = bounds[0]; | |
771 dstref->sizrange[1] = bounds[1]; | |
772 | |
773 if (dstref->sizrange[0] < srcref->sizrange[0]) | |
774 srcref->sizrange[0] = dstref->sizrange[0]; | |
775 | |
776 if (dstref->sizrange[1] < srcref->sizrange[1]) | |
777 srcref->sizrange[1] = dstref->sizrange[1]; | |
778 } | |
779 } | |
780 else if (detect_overlap == &builtin_access::strcpy_overlap) | |
781 { | |
782 if (!dstref->strbounded_p) | |
783 { | |
784 /* For strcpy, adjust the destination size range to match that | |
785 of the source computed above. */ | |
786 if (depends_p && dstadjust_p) | |
787 { | |
788 dstref->sizrange[0] = srcref->sizrange[0]; | |
789 dstref->sizrange[1] = srcref->sizrange[1]; | |
790 } | |
791 } | |
792 } | |
793 | |
794 if (dstref->strbounded_p) | |
795 { | |
796 /* For strncpy, adjust the destination size range to match that | |
797 of the source computed above. */ | |
798 dstref->sizrange[0] = bounds[0]; | |
799 dstref->sizrange[1] = bounds[1]; | |
800 | |
801 if (bounds[0] < srcref->sizrange[0]) | |
802 srcref->sizrange[0] = bounds[0]; | |
803 | |
804 if (bounds[1] < srcref->sizrange[1]) | |
805 srcref->sizrange[1] = bounds[1]; | |
806 } | |
807 } | |
808 | |
809 offset_int | |
810 builtin_access::overlap_size (const offset_int a[2], const offset_int b[2], | |
811 offset_int *off) | |
812 { | |
813 const offset_int *p = a; | |
814 const offset_int *q = b; | |
815 | |
816 /* Point P at the bigger of the two ranges and Q at the smaller. */ | |
817 if (wi::lts_p (a[1] - a[0], b[1] - b[0])) | |
818 { | |
819 p = b; | |
820 q = a; | |
821 } | |
822 | |
823 if (p[0] < q[0]) | |
824 { | |
825 if (p[1] < q[0]) | |
826 return 0; | |
827 | |
828 *off = q[0]; | |
829 return wi::smin (p[1], q[1]) - q[0]; | |
830 } | |
831 | |
832 if (q[1] < p[0]) | |
833 return 0; | |
834 | |
835 off[0] = p[0]; | |
836 return q[1] - p[0]; | |
837 } | |
838 | |
839 /* Return true if the bounded mempry (memcpy amd similar) or string function | |
840 access (strncpy and similar) ACS overlaps. */ | |
841 | |
842 bool | |
843 builtin_access::generic_overlap () | |
844 { | |
845 builtin_access &acs = *this; | |
846 const builtin_memref *dstref = acs.dstref; | |
847 const builtin_memref *srcref = acs.srcref; | |
848 | |
849 gcc_assert (dstref->base == srcref->base); | |
850 | |
851 const offset_int maxobjsize = tree_to_shwi (max_object_size ()); | |
852 | |
853 offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize; | |
854 gcc_assert (maxsize <= maxobjsize); | |
855 | |
856 /* Adjust the larger bounds of the offsets (which may be the first | |
857 element if the lower bound is larger than the upper bound) to | |
858 make them valid for the smallest access (if possible) but no smaller | |
859 than the smaller bounds. */ | |
860 gcc_assert (wi::les_p (acs.dstoff[0], acs.dstoff[1])); | |
861 | |
862 if (maxsize < acs.dstoff[1] + acs.dstsiz[0]) | |
863 acs.dstoff[1] = maxsize - acs.dstsiz[0]; | |
864 if (acs.dstoff[1] < acs.dstoff[0]) | |
865 acs.dstoff[1] = acs.dstoff[0]; | |
866 | |
867 gcc_assert (wi::les_p (acs.srcoff[0], acs.srcoff[1])); | |
868 | |
869 if (maxsize < acs.srcoff[1] + acs.srcsiz[0]) | |
870 acs.srcoff[1] = maxsize - acs.srcsiz[0]; | |
871 if (acs.srcoff[1] < acs.srcoff[0]) | |
872 acs.srcoff[1] = acs.srcoff[0]; | |
873 | |
874 /* Determine the minimum and maximum space for the access given | |
875 the offsets. */ | |
876 offset_int space[2]; | |
877 space[0] = wi::abs (acs.dstoff[0] - acs.srcoff[0]); | |
878 space[1] = space[0]; | |
879 | |
880 offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]); | |
881 if (acs.srcsiz[0] > 0) | |
882 { | |
883 if (d < space[0]) | |
884 space[0] = d; | |
885 | |
886 if (space[1] < d) | |
887 space[1] = d; | |
888 } | |
889 else | |
890 space[1] = acs.dstsiz[1]; | |
891 | |
892 d = wi::abs (acs.dstoff[1] - acs.srcoff[0]); | |
893 if (d < space[0]) | |
894 space[0] = d; | |
895 | |
896 if (space[1] < d) | |
897 space[1] = d; | |
898 | |
899 /* Treat raw memory functions both of whose references are bounded | |
900 as special and permit uncertain overlaps to go undetected. For | |
901 all kinds of constant offset and constant size accesses, if | |
902 overlap isn't certain it is not possible. */ | |
903 bool overlap_possible = space[0] < acs.dstsiz[1]; | |
904 if (!overlap_possible) | |
905 return false; | |
906 | |
907 bool overlap_certain = space[1] < acs.dstsiz[0]; | |
908 | |
909 /* True when the size of one reference depends on the offset of | |
910 the other. */ | |
911 bool depends_p = detect_overlap != &builtin_access::generic_overlap; | |
912 | |
913 if (!overlap_certain) | |
914 { | |
915 if (!dstref->strbounded_p && !depends_p) | |
916 /* Memcpy only considers certain overlap. */ | |
917 return false; | |
918 | |
919 /* There's no way to distinguish an access to the same member | |
920 of a structure from one to two distinct members of the same | |
921 structure. Give up to avoid excessive false positives. */ | |
922 tree basetype = TREE_TYPE (dstref->base); | |
923 | |
924 if (POINTER_TYPE_P (basetype)) | |
925 basetype = TREE_TYPE (basetype); | |
926 else | |
927 while (TREE_CODE (basetype) == ARRAY_TYPE) | |
928 basetype = TREE_TYPE (basetype); | |
929 | |
930 if (RECORD_OR_UNION_TYPE_P (basetype)) | |
931 return false; | |
932 } | |
933 | |
934 /* True for stpcpy and strcpy. */ | |
935 bool stxcpy_p = (!dstref->strbounded_p | |
936 && detect_overlap == &builtin_access::strcpy_overlap); | |
937 | |
938 if (dstref->refoff >= 0 | |
939 && srcref->refoff >= 0 | |
940 && dstref->refoff != srcref->refoff | |
941 && (stxcpy_p || dstref->strbounded_p || srcref->strbounded_p)) | |
942 return false; | |
943 | |
944 offset_int siz[2] = { maxobjsize + 1, 0 }; | |
945 | |
946 ovloff[0] = HOST_WIDE_INT_MAX; | |
947 ovloff[1] = HOST_WIDE_INT_MIN; | |
948 | |
949 /* Adjustment to the lower bound of the offset of the overlap to | |
950 account for a subset of unbounded string calls where the size | |
951 of the destination string depends on the length of the source | |
952 which in turn depends on the offset into it. */ | |
953 bool sub1; | |
954 | |
955 if (stxcpy_p) | |
956 { | |
957 sub1 = acs.dstoff[0] <= acs.srcoff[0]; | |
958 | |
959 /* Iterate over the extreme locations (on the horizontal axis formed | |
960 by their offsets) and sizes of two regions and find their smallest | |
961 and largest overlap and the corresponding offsets. */ | |
962 for (unsigned i = 0; i != 2; ++i) | |
963 { | |
964 const offset_int a[2] = { | |
965 acs.dstoff[i], acs.dstoff[i] + acs.dstsiz[!i] | |
966 }; | |
967 | |
968 const offset_int b[2] = { | |
969 acs.srcoff[i], acs.srcoff[i] + acs.srcsiz[!i] | |
970 }; | |
971 | |
972 offset_int off; | |
973 offset_int sz = overlap_size (a, b, &off); | |
974 if (sz < siz[0]) | |
975 siz[0] = sz; | |
976 | |
977 if (siz[1] <= sz) | |
978 siz[1] = sz; | |
979 | |
980 if (sz != 0) | |
981 { | |
982 if (wi::lts_p (off, ovloff[0])) | |
983 ovloff[0] = off.to_shwi (); | |
984 if (wi::lts_p (ovloff[1], off)) | |
985 ovloff[1] = off.to_shwi (); | |
986 } | |
987 } | |
988 } | |
989 else | |
990 { | |
991 sub1 = !depends_p; | |
992 | |
993 /* Iterate over the extreme locations (on the horizontal axis | |
994 formed by their offsets) and sizes of two regions and find | |
995 their smallest and largest overlap and the corresponding | |
996 offsets. */ | |
997 | |
998 for (unsigned io = 0; io != 2; ++io) | |
999 for (unsigned is = 0; is != 2; ++is) | |
1000 { | |
1001 const offset_int a[2] = { | |
1002 acs.dstoff[io], acs.dstoff[io] + acs.dstsiz[is] | |
1003 }; | |
1004 | |
1005 for (unsigned jo = 0; jo != 2; ++jo) | |
1006 for (unsigned js = 0; js != 2; ++js) | |
1007 { | |
1008 if (depends_p) | |
1009 { | |
1010 /* For st{p,r}ncpy the size of the source sequence | |
1011 depends on the offset into it. */ | |
1012 if (js) | |
1013 break; | |
1014 js = !jo; | |
1015 } | |
1016 | |
1017 const offset_int b[2] = { | |
1018 acs.srcoff[jo], acs.srcoff[jo] + acs.srcsiz[js] | |
1019 }; | |
1020 | |
1021 offset_int off; | |
1022 offset_int sz = overlap_size (a, b, &off); | |
1023 if (sz < siz[0]) | |
1024 siz[0] = sz; | |
1025 | |
1026 if (siz[1] <= sz) | |
1027 siz[1] = sz; | |
1028 | |
1029 if (sz != 0) | |
1030 { | |
1031 if (wi::lts_p (off, ovloff[0])) | |
1032 ovloff[0] = off.to_shwi (); | |
1033 if (wi::lts_p (ovloff[1], off)) | |
1034 ovloff[1] = off.to_shwi (); | |
1035 } | |
1036 } | |
1037 } | |
1038 } | |
1039 | |
1040 ovlsiz[0] = siz[0].to_shwi (); | |
1041 ovlsiz[1] = siz[1].to_shwi (); | |
1042 | |
1043 if (ovlsiz[0] == 0 && ovlsiz[1] > 1) | |
1044 ovloff[0] = ovloff[1] + ovlsiz[1] - 1 - sub1; | |
1045 | |
1046 return true; | |
1047 } | |
1048 | |
1049 /* Return true if the strcat-like access overlaps. */ | |
1050 | |
1051 bool | |
1052 builtin_access::strcat_overlap () | |
1053 { | |
1054 builtin_access &acs = *this; | |
1055 const builtin_memref *dstref = acs.dstref; | |
1056 const builtin_memref *srcref = acs.srcref; | |
1057 | |
1058 gcc_assert (dstref->base == srcref->base); | |
1059 | |
1060 const offset_int maxobjsize = tree_to_shwi (max_object_size ()); | |
1061 | |
1062 gcc_assert (dstref->base && dstref->base == srcref->base); | |
1063 | |
1064 /* Adjust for strcat-like accesses. */ | |
1065 | |
1066 /* As a special case for strcat, set the DSTREF offsets to the length | |
1067 of the source string since the function starts writing at the first | |
1068 nul, and set the size to 1 for the length of the nul. */ | |
1069 acs.dstoff[0] += acs.dstsiz[0]; | |
1070 acs.dstoff[1] += acs.dstsiz[1]; | |
1071 | |
1072 bool strfunc_unknown_args = acs.dstsiz[0] == 0 && acs.dstsiz[1] != 0; | |
1073 | |
1074 /* The lower bound is zero when the size is unknown because then | |
1075 overlap is not certain. */ | |
1076 acs.dstsiz[0] = strfunc_unknown_args ? 0 : 1; | |
1077 acs.dstsiz[1] = 1; | |
1078 | |
1079 offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize; | |
1080 gcc_assert (maxsize <= maxobjsize); | |
1081 | |
1082 /* For references to the same base object, determine if there's a pair | |
1083 of valid offsets into the two references such that access between | |
1084 them doesn't overlap. Adjust both upper bounds to be valid for | |
1085 the smaller size (i.e., at most MAXSIZE - SIZE). */ | |
1086 | |
1087 if (maxsize < acs.dstoff[1] + acs.dstsiz[0]) | |
1088 acs.dstoff[1] = maxsize - acs.dstsiz[0]; | |
1089 | |
1090 if (maxsize < acs.srcoff[1] + acs.srcsiz[0]) | |
1091 acs.srcoff[1] = maxsize - acs.srcsiz[0]; | |
1092 | |
1093 /* Check to see if there's enough space for both accesses without | |
1094 overlap. Determine the optimistic (maximum) amount of available | |
1095 space. */ | |
1096 offset_int space; | |
1097 if (acs.dstoff[0] <= acs.srcoff[0]) | |
1098 { | |
1099 if (acs.dstoff[1] < acs.srcoff[1]) | |
1100 space = acs.srcoff[1] + acs.srcsiz[0] - acs.dstoff[0]; | |
1101 else | |
1102 space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0]; | |
1103 } | |
1104 else | |
1105 space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0]; | |
1106 | |
1107 /* Overlap is certain if the distance between the farthest offsets | |
1108 of the opposite accesses is less than the sum of the lower bounds | |
1109 of the sizes of the two accesses. */ | |
1110 bool overlap_certain = space < acs.dstsiz[0] + acs.srcsiz[0]; | |
1111 | |
1112 /* For a constant-offset, constant size access, consider the largest | |
1113 distance between the offset bounds and the lower bound of the access | |
1114 size. If the overlap isn't certain return success. */ | |
1115 if (!overlap_certain | |
1116 && acs.dstoff[0] == acs.dstoff[1] | |
1117 && acs.srcoff[0] == acs.srcoff[1] | |
1118 && acs.dstsiz[0] == acs.dstsiz[1] | |
1119 && acs.srcsiz[0] == acs.srcsiz[1]) | |
1120 return false; | |
1121 | |
1122 /* Overlap is not certain but may be possible. */ | |
1123 | |
1124 offset_int access_min = acs.dstsiz[0] + acs.srcsiz[0]; | |
1125 | |
1126 /* Determine the conservative (minimum) amount of space. */ | |
1127 space = wi::abs (acs.dstoff[0] - acs.srcoff[0]); | |
1128 offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]); | |
1129 if (d < space) | |
1130 space = d; | |
1131 d = wi::abs (acs.dstoff[1] - acs.srcoff[0]); | |
1132 if (d < space) | |
1133 space = d; | |
1134 | |
1135 /* For a strict test (used for strcpy and similar with unknown or | |
1136 variable bounds or sizes), consider the smallest distance between | |
1137 the offset bounds and either the upper bound of the access size | |
1138 if known, or the lower bound otherwise. */ | |
1139 if (access_min <= space && (access_min != 0 || !strfunc_unknown_args)) | |
1140 return false; | |
1141 | |
1142 /* When strcat overlap is certain it is always a single byte: | |
1143 the terminating NUL, regardless of offsets and sizes. When | |
1144 overlap is only possible its range is [0, 1]. */ | |
1145 acs.ovlsiz[0] = dstref->sizrange[0] == dstref->sizrange[1] ? 1 : 0; | |
1146 acs.ovlsiz[1] = 1; | |
1147 | |
1148 offset_int endoff = dstref->offrange[0] + dstref->sizrange[0]; | |
1149 if (endoff <= srcref->offrange[0]) | |
1150 acs.ovloff[0] = wi::smin (maxobjsize, srcref->offrange[0]).to_shwi (); | |
1151 else | |
1152 acs.ovloff[0] = wi::smin (maxobjsize, endoff).to_shwi (); | |
1153 | |
1154 acs.sizrange[0] = wi::smax (wi::abs (endoff - srcref->offrange[0]) + 1, | |
1155 srcref->sizrange[0]).to_shwi (); | |
1156 if (dstref->offrange[0] == dstref->offrange[1]) | |
1157 { | |
1158 if (srcref->offrange[0] == srcref->offrange[1]) | |
1159 acs.ovloff[1] = acs.ovloff[0]; | |
1160 else | |
1161 acs.ovloff[1] | |
1162 = wi::smin (maxobjsize, | |
1163 srcref->offrange[1] + srcref->sizrange[1]).to_shwi (); | |
1164 } | |
1165 else | |
1166 acs.ovloff[1] | |
1167 = wi::smin (maxobjsize, | |
1168 dstref->offrange[1] + dstref->sizrange[1]).to_shwi (); | |
1169 | |
1170 if (acs.sizrange[0] == 0) | |
1171 acs.sizrange[0] = 1; | |
1172 acs.sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi (); | |
1173 return true; | |
1174 } | |
1175 | |
1176 /* Return true if the strcpy-like access overlaps. */ | |
1177 | |
1178 bool | |
1179 builtin_access::strcpy_overlap () | |
1180 { | |
1181 return generic_overlap (); | |
1182 } | |
1183 | |
1184 | |
1185 /* Return true if DSTREF and SRCREF describe accesses that either overlap | |
1186 one another or that, in order not to overlap, would imply that the size | |
1187 of the referenced object(s) exceeds the maximum size of an object. Set | |
1188 Otherwise, if DSTREF and SRCREF do not definitely overlap (even though | |
1189 they may overlap in a way that's not apparent from the available data), | |
1190 return false. */ | |
1191 | |
1192 bool | |
1193 builtin_access::overlap () | |
1194 { | |
1195 builtin_access &acs = *this; | |
1196 | |
1197 const offset_int maxobjsize = tree_to_shwi (max_object_size ()); | |
1198 | |
1199 acs.sizrange[0] = wi::smax (dstref->sizrange[0], | |
1200 srcref->sizrange[0]).to_shwi (); | |
1201 acs.sizrange[1] = wi::smax (dstref->sizrange[1], | |
1202 srcref->sizrange[1]).to_shwi (); | |
1203 | |
1204 /* Check to see if the two references refer to regions that are | |
1205 too large not to overlap in the address space (whose maximum | |
1206 size is PTRDIFF_MAX). */ | |
1207 offset_int size = dstref->sizrange[0] + srcref->sizrange[0]; | |
1208 if (maxobjsize < size) | |
1209 { | |
1210 acs.ovloff[0] = (maxobjsize - dstref->sizrange[0]).to_shwi (); | |
1211 acs.ovlsiz[0] = (size - maxobjsize).to_shwi (); | |
1212 return true; | |
1213 } | |
1214 | |
1215 /* If both base objects aren't known return the maximum possible | |
1216 offset that would make them not overlap. */ | |
1217 if (!dstref->base || !srcref->base) | |
1218 return false; | |
1219 | |
1220 /* Set the access offsets. */ | |
1221 acs.dstoff[0] = dstref->offrange[0]; | |
1222 acs.dstoff[1] = dstref->offrange[1]; | |
1223 | |
1224 /* If the base object is an array adjust the bounds of the offset | |
1225 to be non-negative and within the bounds of the array if possible. */ | |
1226 if (dstref->base | |
1227 && TREE_CODE (TREE_TYPE (dstref->base)) == ARRAY_TYPE) | |
1228 { | |
1229 if (acs.dstoff[0] < 0 && acs.dstoff[1] >= 0) | |
1230 acs.dstoff[0] = 0; | |
1231 | |
1232 if (acs.dstoff[1] < acs.dstoff[0]) | |
1233 { | |
1234 if (tree size = TYPE_SIZE_UNIT (TREE_TYPE (dstref->base))) | |
1235 acs.dstoff[1] = wi::umin (acs.dstoff[1], wi::to_offset (size)); | |
1236 else | |
1237 acs.dstoff[1] = wi::umin (acs.dstoff[1], maxobjsize); | |
1238 } | |
1239 } | |
1240 | |
1241 acs.srcoff[0] = srcref->offrange[0]; | |
1242 acs.srcoff[1] = srcref->offrange[1]; | |
1243 | |
1244 if (srcref->base | |
1245 && TREE_CODE (TREE_TYPE (srcref->base)) == ARRAY_TYPE) | |
1246 { | |
1247 if (acs.srcoff[0] < 0 && acs.srcoff[1] >= 0) | |
1248 acs.srcoff[0] = 0; | |
1249 | |
1250 if (tree size = TYPE_SIZE_UNIT (TREE_TYPE (srcref->base))) | |
1251 acs.srcoff[1] = wi::umin (acs.srcoff[1], wi::to_offset (size)); | |
1252 else if (acs.srcoff[1] < acs.srcoff[0]) | |
1253 acs.srcoff[1] = wi::umin (acs.srcoff[1], maxobjsize); | |
1254 } | |
1255 | |
1256 /* When the upper bound of the offset is less than the lower bound | |
1257 the former is the result of a negative offset being represented | |
1258 as a large positive value or vice versa. The resulting range is | |
1259 a union of two subranges: [MIN, UB] and [LB, MAX]. Since such | |
1260 a union is not representable using the current data structure | |
1261 replace it with the full range of offsets. */ | |
1262 if (acs.dstoff[1] < acs.dstoff[0]) | |
1263 { | |
1264 acs.dstoff[0] = -maxobjsize - 1; | |
1265 acs.dstoff[1] = maxobjsize; | |
1266 } | |
1267 | |
1268 /* Validate the offset and size of each reference on its own first. | |
1269 This is independent of whether or not the base objects are the | |
1270 same. Normally, this would have already been detected and | |
1271 diagnosed by -Warray-bounds, unless it has been disabled. */ | |
1272 offset_int maxoff = acs.dstoff[0] + dstref->sizrange[0]; | |
1273 if (maxobjsize < maxoff) | |
1274 { | |
1275 acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi (); | |
1276 acs.ovloff[0] = acs.dstoff[0].to_shwi () - acs.ovlsiz[0]; | |
1277 return true; | |
1278 } | |
1279 | |
1280 /* Repeat the same as above but for the source offsets. */ | |
1281 if (acs.srcoff[1] < acs.srcoff[0]) | |
1282 { | |
1283 acs.srcoff[0] = -maxobjsize - 1; | |
1284 acs.srcoff[1] = maxobjsize; | |
1285 } | |
1286 | |
1287 maxoff = acs.srcoff[0] + srcref->sizrange[0]; | |
1288 if (maxobjsize < maxoff) | |
1289 { | |
1290 acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi (); | |
1291 acs.ovlsiz[1] = (acs.srcoff[0] + srcref->sizrange[1] | |
1292 - maxobjsize).to_shwi (); | |
1293 acs.ovloff[0] = acs.srcoff[0].to_shwi () - acs.ovlsiz[0]; | |
1294 return true; | |
1295 } | |
1296 | |
1297 if (dstref->base != srcref->base) | |
1298 return false; | |
1299 | |
1300 acs.dstsiz[0] = dstref->sizrange[0]; | |
1301 acs.dstsiz[1] = dstref->sizrange[1]; | |
1302 | |
1303 acs.srcsiz[0] = srcref->sizrange[0]; | |
1304 acs.srcsiz[1] = srcref->sizrange[1]; | |
1305 | |
1306 /* Call the appropriate function to determine the overlap. */ | |
1307 if ((this->*detect_overlap) ()) | |
1308 { | |
1309 if (!sizrange[1]) | |
1310 { | |
1311 /* Unless the access size range has already been set, do so here. */ | |
1312 sizrange[0] = wi::smax (acs.dstsiz[0], srcref->sizrange[0]).to_shwi (); | |
1313 sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi (); | |
1314 } | |
1315 return true; | |
1316 } | |
1317 | |
1318 return false; | |
1319 } | |
1320 | |
1321 /* Attempt to detect and diagnose an overlapping copy in a call expression | |
1322 EXPR involving an an access ACS to a built-in memory or string function. | |
1323 Return true when one has been detected, false otherwise. */ | |
1324 | |
1325 static bool | |
1326 maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) | |
1327 { | |
1328 if (!acs.overlap ()) | |
1329 return false; | |
1330 | |
1331 /* For convenience. */ | |
1332 const builtin_memref &dstref = *acs.dstref; | |
1333 const builtin_memref &srcref = *acs.srcref; | |
1334 | |
1335 /* Determine the range of offsets and sizes of the overlap if it | |
1336 exists and issue diagnostics. */ | |
1337 HOST_WIDE_INT *ovloff = acs.ovloff; | |
1338 HOST_WIDE_INT *ovlsiz = acs.ovlsiz; | |
1339 HOST_WIDE_INT *sizrange = acs.sizrange; | |
1340 | |
1341 tree func = gimple_call_fndecl (call); | |
1342 | |
1343 /* To avoid a combinatorial explosion of diagnostics format the offsets | |
1344 or their ranges as strings and use them in the warning calls below. */ | |
1345 char offstr[3][64]; | |
1346 | |
1347 if (dstref.offrange[0] == dstref.offrange[1] | |
1348 || dstref.offrange[1] > HOST_WIDE_INT_MAX) | |
1349 sprintf (offstr[0], HOST_WIDE_INT_PRINT_DEC, | |
1350 dstref.offrange[0].to_shwi ()); | |
1351 else | |
1352 sprintf (offstr[0], | |
1353 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]", | |
1354 dstref.offrange[0].to_shwi (), | |
1355 dstref.offrange[1].to_shwi ()); | |
1356 | |
1357 if (srcref.offrange[0] == srcref.offrange[1] | |
1358 || srcref.offrange[1] > HOST_WIDE_INT_MAX) | |
1359 sprintf (offstr[1], | |
1360 HOST_WIDE_INT_PRINT_DEC, | |
1361 srcref.offrange[0].to_shwi ()); | |
1362 else | |
1363 sprintf (offstr[1], | |
1364 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]", | |
1365 srcref.offrange[0].to_shwi (), | |
1366 srcref.offrange[1].to_shwi ()); | |
1367 | |
1368 if (ovloff[0] == ovloff[1] || !ovloff[1]) | |
1369 sprintf (offstr[2], HOST_WIDE_INT_PRINT_DEC, ovloff[0]); | |
1370 else | |
1371 sprintf (offstr[2], | |
1372 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]", | |
1373 ovloff[0], ovloff[1]); | |
1374 | |
1375 const offset_int maxobjsize = tree_to_shwi (max_object_size ()); | |
1376 bool must_overlap = ovlsiz[0] > 0; | |
1377 | |
1378 if (ovlsiz[1] == 0) | |
1379 ovlsiz[1] = ovlsiz[0]; | |
1380 | |
1381 if (must_overlap) | |
1382 { | |
1383 /* Issue definitive "overlaps" diagnostic in this block. */ | |
1384 | |
1385 if (sizrange[0] == sizrange[1]) | |
1386 { | |
1387 if (ovlsiz[0] == ovlsiz[1]) | |
1388 warning_at (loc, OPT_Wrestrict, | |
1389 sizrange[0] == 1 | |
1390 ? (ovlsiz[0] == 1 | |
1391 ? G_("%G%qD accessing %wu byte at offsets %s " | |
1392 "and %s overlaps %wu byte at offset %s") | |
1393 : G_("%G%qD accessing %wu byte at offsets %s " | |
1394 "and %s overlaps %wu bytes at offset " | |
1395 "%s")) | |
1396 : (ovlsiz[0] == 1 | |
1397 ? G_("%G%qD accessing %wu bytes at offsets %s " | |
1398 "and %s overlaps %wu byte at offset %s") | |
1399 : G_("%G%qD accessing %wu bytes at offsets %s " | |
1400 "and %s overlaps %wu bytes at offset " | |
1401 "%s")), | |
1402 call, func, sizrange[0], | |
1403 offstr[0], offstr[1], ovlsiz[0], offstr[2]); | |
1404 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ()) | |
1405 warning_n (loc, OPT_Wrestrict, sizrange[0], | |
1406 "%G%qD accessing %wu byte at offsets %s " | |
1407 "and %s overlaps between %wu and %wu bytes " | |
1408 "at offset %s", | |
1409 "%G%qD accessing %wu bytes at offsets %s " | |
1410 "and %s overlaps between %wu and %wu bytes " | |
1411 "at offset %s", | |
1412 call, func, sizrange[0], offstr[0], offstr[1], | |
1413 ovlsiz[0], ovlsiz[1], offstr[2]); | |
1414 else | |
1415 warning_n (loc, OPT_Wrestrict, sizrange[0], | |
1416 "%G%qD accessing %wu byte at offsets %s and " | |
1417 "%s overlaps %wu or more bytes at offset %s", | |
1418 "%G%qD accessing %wu bytes at offsets %s and " | |
1419 "%s overlaps %wu or more bytes at offset %s", | |
1420 call, func, sizrange[0], | |
1421 offstr[0], offstr[1], ovlsiz[0], offstr[2]); | |
1422 return true; | |
1423 } | |
1424 | |
1425 if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ()) | |
1426 { | |
1427 if (ovlsiz[0] == ovlsiz[1]) | |
1428 warning_n (loc, OPT_Wrestrict, ovlsiz[0], | |
1429 "%G%qD accessing between %wu and %wu bytes " | |
1430 "at offsets %s and %s overlaps %wu byte at " | |
1431 "offset %s", | |
1432 "%G%qD accessing between %wu and %wu bytes " | |
1433 "at offsets %s and %s overlaps %wu bytes " | |
1434 "at offset %s", | |
1435 call, func, sizrange[0], sizrange[1], | |
1436 offstr[0], offstr[1], ovlsiz[0], offstr[2]); | |
1437 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ()) | |
1438 warning_at (loc, OPT_Wrestrict, | |
1439 "%G%qD accessing between %wu and %wu bytes at " | |
1440 "offsets %s and %s overlaps between %wu and %wu " | |
1441 "bytes at offset %s", | |
1442 call, func, sizrange[0], sizrange[1], | |
1443 offstr[0], offstr[1], ovlsiz[0], ovlsiz[1], | |
1444 offstr[2]); | |
1445 else | |
1446 warning_at (loc, OPT_Wrestrict, | |
1447 "%G%qD accessing between %wu and %wu bytes at " | |
1448 "offsets %s and %s overlaps %wu or more bytes " | |
1449 "at offset %s", | |
1450 call, func, sizrange[0], sizrange[1], | |
1451 offstr[0], offstr[1], ovlsiz[0], offstr[2]); | |
1452 return true; | |
1453 } | |
1454 | |
1455 if (ovlsiz[0] != ovlsiz[1]) | |
1456 ovlsiz[1] = maxobjsize.to_shwi (); | |
1457 | |
1458 if (ovlsiz[0] == ovlsiz[1]) | |
1459 warning_n (loc, OPT_Wrestrict, ovlsiz[0], | |
1460 "%G%qD accessing %wu or more bytes at offsets " | |
1461 "%s and %s overlaps %wu byte at offset %s", | |
1462 "%G%qD accessing %wu or more bytes at offsets " | |
1463 "%s and %s overlaps %wu bytes at offset %s", | |
1464 call, func, sizrange[0], offstr[0], offstr[1], | |
1465 ovlsiz[0], offstr[2]); | |
1466 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ()) | |
1467 warning_at (loc, OPT_Wrestrict, | |
1468 "%G%qD accessing %wu or more bytes at offsets %s " | |
1469 "and %s overlaps between %wu and %wu bytes " | |
1470 "at offset %s", | |
1471 call, func, sizrange[0], offstr[0], offstr[1], | |
1472 ovlsiz[0], ovlsiz[1], offstr[2]); | |
1473 else | |
1474 warning_at (loc, OPT_Wrestrict, | |
1475 "%G%qD accessing %wu or more bytes at offsets %s " | |
1476 "and %s overlaps %wu or more bytes at offset %s", | |
1477 call, func, sizrange[0], offstr[0], offstr[1], | |
1478 ovlsiz[0], offstr[2]); | |
1479 return true; | |
1480 } | |
1481 | |
1482 /* Use more concise wording when one of the offsets is unbounded | |
1483 to avoid confusing the user with large and mostly meaningless | |
1484 numbers. */ | |
1485 bool open_range; | |
1486 if (DECL_P (dstref.base) && TREE_CODE (TREE_TYPE (dstref.base)) == ARRAY_TYPE) | |
1487 open_range = ((dstref.offrange[0] == 0 | |
1488 && dstref.offrange[1] == maxobjsize) | |
1489 || (srcref.offrange[0] == 0 | |
1490 && srcref.offrange[1] == maxobjsize)); | |
1491 else | |
1492 open_range = ((dstref.offrange[0] == -maxobjsize - 1 | |
1493 && dstref.offrange[1] == maxobjsize) | |
1494 || (srcref.offrange[0] == -maxobjsize - 1 | |
1495 && srcref.offrange[1] == maxobjsize)); | |
1496 | |
1497 if (sizrange[0] == sizrange[1] || sizrange[1] == 1) | |
1498 { | |
1499 if (ovlsiz[1] == 1) | |
1500 { | |
1501 if (open_range) | |
1502 warning_n (loc, OPT_Wrestrict, sizrange[1], | |
1503 "%G%qD accessing %wu byte may overlap " | |
1504 "%wu byte", | |
1505 "%G%qD accessing %wu bytes may overlap " | |
1506 "%wu byte", | |
1507 call, func, sizrange[1], ovlsiz[1]); | |
1508 else | |
1509 warning_n (loc, OPT_Wrestrict, sizrange[1], | |
1510 "%G%qD accessing %wu byte at offsets %s " | |
1511 "and %s may overlap %wu byte at offset %s", | |
1512 "%G%qD accessing %wu bytes at offsets %s " | |
1513 "and %s may overlap %wu byte at offset %s", | |
1514 call, func, sizrange[1], offstr[0], offstr[1], | |
1515 ovlsiz[1], offstr[2]); | |
1516 return true; | |
1517 } | |
1518 | |
1519 if (open_range) | |
1520 warning_n (loc, OPT_Wrestrict, sizrange[1], | |
1521 "%G%qD accessing %wu byte may overlap " | |
1522 "up to %wu bytes", | |
1523 "%G%qD accessing %wu bytes may overlap " | |
1524 "up to %wu bytes", | |
1525 call, func, sizrange[1], ovlsiz[1]); | |
1526 else | |
1527 warning_n (loc, OPT_Wrestrict, sizrange[1], | |
1528 "%G%qD accessing %wu byte at offsets %s and " | |
1529 "%s may overlap up to %wu bytes at offset %s", | |
1530 "%G%qD accessing %wu bytes at offsets %s and " | |
1531 "%s may overlap up to %wu bytes at offset %s", | |
1532 call, func, sizrange[1], offstr[0], offstr[1], | |
1533 ovlsiz[1], offstr[2]); | |
1534 return true; | |
1535 } | |
1536 | |
1537 if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ()) | |
1538 { | |
1539 if (open_range) | |
1540 warning_n (loc, OPT_Wrestrict, ovlsiz[1], | |
1541 "%G%qD accessing between %wu and %wu bytes " | |
1542 "may overlap %wu byte", | |
1543 "%G%qD accessing between %wu and %wu bytes " | |
1544 "may overlap up to %wu bytes", | |
1545 call, func, sizrange[0], sizrange[1], ovlsiz[1]); | |
1546 else | |
1547 warning_n (loc, OPT_Wrestrict, ovlsiz[1], | |
1548 "%G%qD accessing between %wu and %wu bytes " | |
1549 "at offsets %s and %s may overlap %wu byte " | |
1550 "at offset %s", | |
1551 "%G%qD accessing between %wu and %wu bytes " | |
1552 "at offsets %s and %s may overlap up to %wu " | |
1553 "bytes at offset %s", | |
1554 call, func, sizrange[0], sizrange[1], | |
1555 offstr[0], offstr[1], ovlsiz[1], offstr[2]); | |
1556 return true; | |
1557 } | |
1558 | |
1559 warning_n (loc, OPT_Wrestrict, ovlsiz[1], | |
1560 "%G%qD accessing %wu or more bytes at offsets %s " | |
1561 "and %s may overlap %wu byte at offset %s", | |
1562 "%G%qD accessing %wu or more bytes at offsets %s " | |
1563 "and %s may overlap up to %wu bytes at offset %s", | |
1564 call, func, sizrange[0], offstr[0], offstr[1], | |
1565 ovlsiz[1], offstr[2]); | |
1566 | |
1567 return true; | |
1568 } | |
1569 | |
1570 /* Validate REF offsets in an EXPRession passed as an argument to a CALL | |
1571 to a built-in function FUNC to make sure they are within the bounds | |
1572 of the referenced object if its size is known, or PTRDIFF_MAX otherwise. | |
1573 Both initial values of the offsets and their final value computed by | |
1574 the function by incrementing the initial value by the size are | |
1575 validated. Return true if the offsets are not valid and a diagnostic | |
1576 has been issued. */ | |
1577 | |
1578 static bool | |
1579 maybe_diag_offset_bounds (location_t loc, gimple *call, tree func, int strict, | |
1580 tree expr, const builtin_memref &ref) | |
1581 { | |
1582 if (!warn_array_bounds) | |
1583 return false; | |
1584 | |
1585 offset_int ooboff[] = { ref.offrange[0], ref.offrange[1] }; | |
1586 tree oobref = ref.offset_out_of_bounds (strict, ooboff); | |
1587 if (!oobref) | |
1588 return false; | |
1589 | |
1590 if (EXPR_HAS_LOCATION (expr)) | |
1591 loc = EXPR_LOCATION (expr); | |
1592 | |
1593 loc = expansion_point_location_if_in_system_header (loc); | |
1594 | |
1595 char rangestr[2][64]; | |
1596 if (ooboff[0] == ooboff[1] | |
1597 || (ooboff[0] != ref.offrange[0] | |
1598 && ooboff[0].to_shwi () >= ooboff[1].to_shwi ())) | |
1599 sprintf (rangestr[0], "%lli", (long long) ooboff[0].to_shwi ()); | |
1600 else | |
1601 sprintf (rangestr[0], "[%lli, %lli]", | |
1602 (long long) ooboff[0].to_shwi (), | |
1603 (long long) ooboff[1].to_shwi ()); | |
1604 | |
1605 bool warned = false; | |
1606 | |
1607 if (oobref == error_mark_node) | |
1608 { | |
1609 if (ref.sizrange[0] == ref.sizrange[1]) | |
1610 sprintf (rangestr[1], "%lli", (long long) ref.sizrange[0].to_shwi ()); | |
1611 else | |
1612 sprintf (rangestr[1], "[%lli, %lli]", | |
1613 (long long) ref.sizrange[0].to_shwi (), | |
1614 (long long) ref.sizrange[1].to_shwi ()); | |
1615 | |
1616 tree type; | |
1617 | |
1618 if (DECL_P (ref.base) | |
1619 && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE) | |
1620 { | |
1621 auto_diagnostic_group d; | |
1622 if (warning_at (loc, OPT_Warray_bounds, | |
1623 "%G%qD pointer overflow between offset %s " | |
1624 "and size %s accessing array %qD with type %qT", | |
1625 call, func, rangestr[0], rangestr[1], ref.base, type)) | |
1626 { | |
1627 inform (DECL_SOURCE_LOCATION (ref.base), | |
1628 "array %qD declared here", ref.base); | |
1629 warned = true; | |
1630 } | |
1631 else | |
1632 warned = warning_at (loc, OPT_Warray_bounds, | |
1633 "%G%qD pointer overflow between offset %s " | |
1634 "and size %s", | |
1635 call, func, rangestr[0], rangestr[1]); | |
1636 } | |
1637 else | |
1638 warned = warning_at (loc, OPT_Warray_bounds, | |
1639 "%G%qD pointer overflow between offset %s " | |
1640 "and size %s", | |
1641 call, func, rangestr[0], rangestr[1]); | |
1642 } | |
1643 else if (oobref == ref.base) | |
1644 { | |
1645 const offset_int maxobjsize = tree_to_shwi (max_object_size ()); | |
1646 | |
1647 /* True when the offset formed by an access to the reference | |
1648 is out of bounds, rather than the initial offset wich is | |
1649 in bounds. This implies access past the end. */ | |
1650 bool form = ooboff[0] != ref.offrange[0]; | |
1651 | |
1652 if (DECL_P (ref.base)) | |
1653 { | |
1654 auto_diagnostic_group d; | |
1655 if ((ref.basesize < maxobjsize | |
1656 && warning_at (loc, OPT_Warray_bounds, | |
1657 form | |
1658 ? G_("%G%qD forming offset %s is out of " | |
1659 "the bounds [0, %wu] of object %qD with " | |
1660 "type %qT") | |
1661 : G_("%G%qD offset %s is out of the bounds " | |
1662 "[0, %wu] of object %qD with type %qT"), | |
1663 call, func, rangestr[0], ref.basesize.to_uhwi (), | |
1664 ref.base, TREE_TYPE (ref.base))) | |
1665 || warning_at (loc, OPT_Warray_bounds, | |
1666 form | |
1667 ? G_("%G%qD forming offset %s is out of " | |
1668 "the bounds of object %qD with type %qT") | |
1669 : G_("%G%qD offset %s is out of the bounds " | |
1670 "of object %qD with type %qT"), | |
1671 call, func, rangestr[0], | |
1672 ref.base, TREE_TYPE (ref.base))) | |
1673 { | |
1674 inform (DECL_SOURCE_LOCATION (ref.base), | |
1675 "%qD declared here", ref.base); | |
1676 warned = true; | |
1677 } | |
1678 } | |
1679 else if (ref.basesize < maxobjsize) | |
1680 warned = warning_at (loc, OPT_Warray_bounds, | |
1681 form | |
1682 ? G_("%G%qD forming offset %s is out " | |
1683 "of the bounds [0, %wu]") | |
1684 : G_("%G%qD offset %s is out " | |
1685 "of the bounds [0, %wu]"), | |
1686 call, func, rangestr[0], ref.basesize.to_uhwi ()); | |
1687 else | |
1688 warned = warning_at (loc, OPT_Warray_bounds, | |
1689 form | |
1690 ? G_("%G%qD forming offset %s is out of bounds") | |
1691 : G_("%G%qD offset %s is out of bounds"), | |
1692 call, func, rangestr[0]); | |
1693 } | |
1694 else if (TREE_CODE (ref.ref) == MEM_REF) | |
1695 { | |
1696 tree type = TREE_TYPE (TREE_OPERAND (ref.ref, 0)); | |
1697 if (POINTER_TYPE_P (type)) | |
1698 type = TREE_TYPE (type); | |
1699 type = TYPE_MAIN_VARIANT (type); | |
1700 | |
1701 warned = warning_at (loc, OPT_Warray_bounds, | |
1702 "%G%qD offset %s from the object at %qE is out " | |
1703 "of the bounds of %qT", | |
1704 call, func, rangestr[0], ref.base, type); | |
1705 } | |
1706 else | |
1707 { | |
1708 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref)); | |
1709 | |
1710 warned = warning_at (loc, OPT_Warray_bounds, | |
1711 "%G%qD offset %s from the object at %qE is out " | |
1712 "of the bounds of referenced subobject %qD with " | |
1713 "type %qT at offset %wu", | |
1714 call, func, rangestr[0], ref.base, | |
1715 TREE_OPERAND (ref.ref, 1), type, | |
1716 ref.refoff.to_uhwi ()); | |
1717 } | |
1718 | |
1719 return warned; | |
1720 } | |
1721 | |
1722 /* Check a CALL statement for restrict-violations and issue warnings | |
1723 if/when appropriate. */ | |
1724 | |
1725 void | |
1726 wrestrict_dom_walker::check_call (gimple *call) | |
1727 { | |
1728 /* Avoid checking the call if it has already been diagnosed for | |
1729 some reason. */ | |
1730 if (gimple_no_warning_p (call)) | |
1731 return; | |
1732 | |
1733 tree func = gimple_call_fndecl (call); | |
1734 if (!func || !fndecl_built_in_p (func, BUILT_IN_NORMAL)) | |
1735 return; | |
1736 | |
1737 /* Argument number to extract from the call (depends on the built-in | |
1738 and its kind). */ | |
1739 unsigned dst_idx = -1; | |
1740 unsigned src_idx = -1; | |
1741 unsigned bnd_idx = -1; | |
1742 | |
1743 /* Is this CALL to a string function (as opposed to one to a raw | |
1744 memory function). */ | |
1745 bool strfun = true; | |
1746 | |
1747 switch (DECL_FUNCTION_CODE (func)) | |
1748 { | |
1749 case BUILT_IN_MEMCPY: | |
1750 case BUILT_IN_MEMCPY_CHK: | |
1751 case BUILT_IN_MEMPCPY: | |
1752 case BUILT_IN_MEMPCPY_CHK: | |
1753 case BUILT_IN_MEMMOVE: | |
1754 case BUILT_IN_MEMMOVE_CHK: | |
1755 strfun = false; | |
1756 /* Fall through. */ | |
1757 | |
1758 case BUILT_IN_STPNCPY: | |
1759 case BUILT_IN_STPNCPY_CHK: | |
1760 case BUILT_IN_STRNCAT: | |
1761 case BUILT_IN_STRNCAT_CHK: | |
1762 case BUILT_IN_STRNCPY: | |
1763 case BUILT_IN_STRNCPY_CHK: | |
1764 dst_idx = 0; | |
1765 src_idx = 1; | |
1766 bnd_idx = 2; | |
1767 break; | |
1768 | |
1769 case BUILT_IN_STPCPY: | |
1770 case BUILT_IN_STPCPY_CHK: | |
1771 case BUILT_IN_STRCPY: | |
1772 case BUILT_IN_STRCPY_CHK: | |
1773 case BUILT_IN_STRCAT: | |
1774 case BUILT_IN_STRCAT_CHK: | |
1775 dst_idx = 0; | |
1776 src_idx = 1; | |
1777 break; | |
1778 | |
1779 default: | |
1780 /* Handle other string functions here whose access may need | |
1781 to be validated for in-bounds offsets and non-overlapping | |
1782 copies. */ | |
1783 return; | |
1784 } | |
1785 | |
1786 unsigned nargs = gimple_call_num_args (call); | |
1787 | |
1788 tree dst = dst_idx < nargs ? gimple_call_arg (call, dst_idx) : NULL_TREE; | |
1789 tree src = src_idx < nargs ? gimple_call_arg (call, src_idx) : NULL_TREE; | |
1790 tree dstwr = bnd_idx < nargs ? gimple_call_arg (call, bnd_idx) : NULL_TREE; | |
1791 | |
1792 /* For string functions with an unspecified or unknown bound, | |
1793 assume the size of the access is one. */ | |
1794 if (!dstwr && strfun) | |
1795 dstwr = size_one_node; | |
1796 | |
1797 /* DST and SRC can be null for a call with an insufficient number | |
1798 of arguments to a built-in function declared without a protype. */ | |
1799 if (!dst || !src) | |
1800 return; | |
1801 | |
1802 /* DST, SRC, or DSTWR can also have the wrong type in a call to | |
1803 a function declared without a prototype. Avoid checking such | |
1804 invalid calls. */ | |
1805 if (TREE_CODE (TREE_TYPE (dst)) != POINTER_TYPE | |
1806 || TREE_CODE (TREE_TYPE (src)) != POINTER_TYPE | |
1807 || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr)))) | |
1808 return; | |
1809 | |
1810 if (check_bounds_or_overlap (call, dst, src, dstwr, NULL_TREE)) | |
1811 return; | |
1812 | |
1813 /* Avoid diagnosing the call again. */ | |
1814 gimple_set_no_warning (call, true); | |
1815 } | |
1816 | |
1817 } /* anonymous namespace */ | |
1818 | |
1819 /* Attempt to detect and diagnose invalid offset bounds and (except for | |
1820 memmove) overlapping copy in a call expression EXPR from SRC to DST | |
1821 and DSTSIZE and SRCSIZE bytes, respectively. Both DSTSIZE and | |
1822 SRCSIZE may be NULL. Return false when one or the other has been | |
1823 detected and diagnosed, true otherwise. */ | |
1824 | |
1825 bool | |
1826 check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize, | |
1827 tree srcsize, bool bounds_only /* = false */) | |
1828 { | |
1829 location_t loc = gimple_nonartificial_location (call); | |
1830 loc = expansion_point_location_if_in_system_header (loc); | |
1831 | |
1832 tree func = gimple_call_fndecl (call); | |
1833 | |
1834 builtin_memref dstref (dst, dstsize); | |
1835 builtin_memref srcref (src, srcsize); | |
1836 | |
1837 builtin_access acs (call, dstref, srcref); | |
1838 | |
1839 /* Set STRICT to the value of the -Warray-bounds=N argument for | |
1840 string functions or when N > 1. */ | |
1841 int strict = (acs.strict () || warn_array_bounds > 1 ? warn_array_bounds : 0); | |
1842 | |
1843 /* Validate offsets first to make sure they are within the bounds | |
1844 of the destination object if its size is known, or PTRDIFF_MAX | |
1845 otherwise. */ | |
1846 if (maybe_diag_offset_bounds (loc, call, func, strict, dst, dstref) | |
1847 || maybe_diag_offset_bounds (loc, call, func, strict, src, srcref)) | |
1848 { | |
1849 gimple_set_no_warning (call, true); | |
1850 return false; | |
1851 } | |
1852 | |
1853 bool check_overlap | |
1854 = (warn_restrict | |
1855 && (bounds_only | |
1856 || (DECL_FUNCTION_CODE (func) != BUILT_IN_MEMMOVE | |
1857 && DECL_FUNCTION_CODE (func) != BUILT_IN_MEMMOVE_CHK))); | |
1858 | |
1859 if (!check_overlap) | |
1860 return true; | |
1861 | |
1862 if (operand_equal_p (dst, src, 0)) | |
1863 { | |
1864 /* Issue -Wrestrict unless the pointers are null (those do | |
1865 not point to objects and so do not indicate an overlap; | |
1866 such calls could be the result of sanitization and jump | |
1867 threading). */ | |
1868 if (!integer_zerop (dst) && !gimple_no_warning_p (call)) | |
1869 { | |
1870 warning_at (loc, OPT_Wrestrict, | |
1871 "%G%qD source argument is the same as destination", | |
1872 call, func); | |
1873 gimple_set_no_warning (call, true); | |
1874 return false; | |
1875 } | |
1876 | |
1877 return true; | |
1878 } | |
1879 | |
1880 /* Return false when overlap has been detected. */ | |
1881 if (maybe_diag_overlap (loc, call, acs)) | |
1882 { | |
1883 gimple_set_no_warning (call, true); | |
1884 return false; | |
1885 } | |
1886 | |
1887 return true; | |
1888 } | |
1889 | |
1890 gimple_opt_pass * | |
1891 make_pass_warn_restrict (gcc::context *ctxt) | |
1892 { | |
1893 return new pass_wrestrict (ctxt); | |
1894 } |