diff options
author | Martin Sebor <msebor@redhat.com> | 2019-11-22 17:14:17 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2019-11-22 10:14:17 -0700 |
commit | 54aa6b58fe2fe73bbe67e0485777e0c410a18673 (patch) | |
tree | 11281ae8b5d5a5f2a57ffc60d7d8cfe951a953d8 /gcc/builtins.c | |
parent | b5338fb359ea3480d6ed37bbc52fe2df49b82fb9 (diff) |
PR middle-end/83859 - attributes to associate pointer arguments and sizes
gcc/ChangeLog:
PR middle-end/83859
* attribs.h (struct attr_access): New.
* attribs.c (decl_attributes): Add an informational note.
* builtins.c (check_access): Make extern. Consistently set no-warning
after issuing a warning. Handle calls through function pointers. Set
no-warning.
* builtins.h (check_access): Declare.
* calls.c (rdwr_access_hash): New type.
(rdwr_map): Same.
(init_attr_rdwr_indices): New function.
(maybe_warn_rdwr_sizes): Same.
(initialize_argument_information): Call init_attr_rdwr_indices.
Call maybe_warn_rdwr_sizes.
(get_size_range): Avoid null argument.
* doc/extend.texi (attribute access): Document new attribute.
gcc/c-family/ChangeLog:
PR middle-end/83859
* c-attribs.c (handle_access_attribute): New function.
(c_common_attribute_table): Add new attribute.
(get_argument_type): New function.
(append_access_attrs): New function.
(get_nonnull_operand): Rename...
(get_attribute_operand): ...to this.
* c-common.c (get_nonnull_operand): Rename...
(get_attribute_operand): ...to this.
gcc/testsuite/ChangeLog:
PR middle-end/83859
* c-c++-common/attr-nonstring-8.c: Adjust text of expected warning.
* gcc.dg/Wstringop-overflow-23.c: New test.
* gcc.dg/Wstringop-overflow-24.c: New test.
* gcc.dg/attr-access-read-only.c: New test.
* gcc.dg/attr-access-read-write.c: New test.
* gcc.dg/attr-access-read-write-2.c: New test.
* gcc.dg/attr-access-write-only.c: New test.
From-SVN: r278624
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 215 |
1 files changed, 154 insertions, 61 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index f8cd4b44fa8..8296d846171 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3340,7 +3340,7 @@ determine_block_size (tree len, rtx len_rtx, If the call is successfully verified as safe return true, otherwise return false. */ -static bool +bool check_access (tree exp, tree, tree, tree dstwrite, tree maxread, tree srcstr, tree dstsize) { @@ -3436,16 +3436,26 @@ check_access (tree exp, tree, tree, tree dstwrite, bool warned; if (range[0] == range[1]) - warned = warning_at (loc, opt, - "%K%qD specified size %E " - "exceeds maximum object size %E", - exp, func, range[0], maxobjsize); + warned = (func + ? warning_at (loc, opt, + "%K%qD specified size %E " + "exceeds maximum object size %E", + exp, func, range[0], maxobjsize) + : warning_at (loc, opt, + "%Kspecified size %E " + "exceeds maximum object size %E", + exp, range[0], maxobjsize)); else - warned = warning_at (loc, opt, - "%K%qD specified size between %E and %E " - "exceeds maximum object size %E", - exp, func, - range[0], range[1], maxobjsize); + warned = (func + ? warning_at (loc, opt, + "%K%qD specified size between %E and %E " + "exceeds maximum object size %E", + exp, func, + range[0], range[1], maxobjsize) + : warning_at (loc, opt, + "%Kspecified size between %E and %E " + "exceeds maximum object size %E", + exp, range[0], range[1], maxobjsize)); if (warned) TREE_NO_WARNING (exp) = true; @@ -3474,37 +3484,69 @@ check_access (tree exp, tree, tree, tree dstwrite, location_t loc = tree_nonartificial_location (exp); loc = expansion_point_location_if_in_system_header (loc); + bool warned = false; if (dstwrite == slen && at_least_one) { /* This is a call to strcpy with a destination of 0 size and a source of unknown length. The call will write at least one byte past the end of the destination. */ - warning_at (loc, opt, - "%K%qD writing %E or more bytes into a region " - "of size %E overflows the destination", - exp, func, range[0], dstsize); + warned = (func + ? warning_at (loc, opt, + "%K%qD writing %E or more bytes into " + "a region of size %E overflows " + "the destination", + exp, func, range[0], dstsize) + : warning_at (loc, opt, + "%Kwriting %E or more bytes into " + "a region of size %E overflows " + "the destination", + exp, range[0], dstsize)); } else if (tree_int_cst_equal (range[0], range[1])) - warning_n (loc, opt, tree_to_uhwi (range[0]), - "%K%qD writing %E byte into a region " - "of size %E overflows the destination", - "%K%qD writing %E bytes into a region " - "of size %E overflows the destination", - exp, func, range[0], dstsize); + warned = (func + ? warning_n (loc, opt, tree_to_uhwi (range[0]), + "%K%qD writing %E byte into a region " + "of size %E overflows the destination", + "%K%qD writing %E bytes into a region " + "of size %E overflows the destination", + exp, func, range[0], dstsize) + : warning_n (loc, opt, tree_to_uhwi (range[0]), + "%Kwriting %E byte into a region " + "of size %E overflows the destination", + "%Kwriting %E bytes into a region " + "of size %E overflows the destination", + exp, range[0], dstsize)); else if (tree_int_cst_sign_bit (range[1])) { /* Avoid printing the upper bound if it's invalid. */ - warning_at (loc, opt, - "%K%qD writing %E or more bytes into a region " - "of size %E overflows the destination", - exp, func, range[0], dstsize); + warned = (func + ? warning_at (loc, opt, + "%K%qD writing %E or more bytes into " + "a region of size %E overflows " + "the destination", + exp, func, range[0], dstsize) + : warning_at (loc, opt, + "%Kwriting %E or more bytes into " + "a region of size %E overflows " + "the destination", + exp, range[0], dstsize)); } else - warning_at (loc, opt, - "%K%qD writing between %E and %E bytes into " - "a region of size %E overflows the destination", - exp, func, range[0], range[1], - dstsize); + warned = (func + ? warning_at (loc, opt, + "%K%qD writing between %E and %E bytes " + "into a region of size %E overflows " + "the destination", + exp, func, range[0], range[1], + dstsize) + : warning_at (loc, opt, + "%Kwriting between %E and %E bytes " + "into a region of size %E overflows " + "the destination", + exp, range[0], range[1], + dstsize)); + if (warned) + TREE_NO_WARNING (exp) = true; /* Return error when an overflow has been detected. */ return false; @@ -3527,21 +3569,36 @@ check_access (tree exp, tree, tree, tree dstwrite, if (TREE_NO_WARNING (exp)) return false; + bool warned = false; + /* Warn about crazy big sizes first since that's more likely to be meaningful than saying that the bound is greater than the object size if both are big. */ if (range[0] == range[1]) - warning_at (loc, opt, - "%K%qD specified bound %E " - "exceeds maximum object size %E", - exp, func, - range[0], maxobjsize); + warned = (func + ? warning_at (loc, opt, + "%K%qD specified bound %E " + "exceeds maximum object size %E", + exp, func, range[0], maxobjsize) + : warning_at (loc, opt, + "%Kspecified bound %E " + "exceeds maximum object size %E", + exp, range[0], maxobjsize)); else - warning_at (loc, opt, - "%K%qD specified bound between %E and %E " - "exceeds maximum object size %E", - exp, func, - range[0], range[1], maxobjsize); + warned = (func + ? warning_at (loc, opt, + "%K%qD specified bound between " + "%E and %E exceeds maximum object " + "size %E", + exp, func, + range[0], range[1], maxobjsize) + : warning_at (loc, opt, + "%Kspecified bound between " + "%E and %E exceeds maximum object " + "size %E", + exp, range[0], range[1], maxobjsize)); + if (warned) + TREE_NO_WARNING (exp) = true; return false; } @@ -3551,18 +3608,34 @@ check_access (tree exp, tree, tree, tree dstwrite, if (TREE_NO_WARNING (exp)) return false; + bool warned = false; + if (tree_int_cst_equal (range[0], range[1])) - warning_at (loc, opt, - "%K%qD specified bound %E " - "exceeds destination size %E", - exp, func, - range[0], dstsize); + warned = (func + ? warning_at (loc, opt, + "%K%qD specified bound %E " + "exceeds destination size %E", + exp, func, + range[0], dstsize) + : warning_at (loc, opt, + "%Kspecified bound %E " + "exceeds destination size %E", + exp, range[0], dstsize)); else - warning_at (loc, opt, - "%K%qD specified bound between %E and %E " - "exceeds destination size %E", - exp, func, - range[0], range[1], dstsize); + warned = (func + ? warning_at (loc, opt, + "%K%qD specified bound between %E " + "and %E exceeds destination size %E", + exp, func, + range[0], range[1], dstsize) + : warning_at (loc, opt, + "%Kspecified bound between %E " + "and %E exceeds destination size %E", + exp, + range[0], range[1], dstsize)); + if (warned) + TREE_NO_WARNING (exp) = true; + return false; } } @@ -3577,26 +3650,46 @@ check_access (tree exp, tree, tree, tree dstwrite, if (TREE_NO_WARNING (exp)) return false; + bool warned = false; location_t loc = tree_nonartificial_location (exp); + loc = expansion_point_location_if_in_system_header (loc); if (tree_int_cst_equal (range[0], range[1])) - warning_n (loc, opt, tree_to_uhwi (range[0]), - "%K%qD reading %E byte from a region of size %E", - "%K%qD reading %E bytes from a region of size %E", - exp, func, range[0], slen); + warned = (func + ? warning_n (loc, opt, tree_to_uhwi (range[0]), + "%K%qD reading %E byte from a region of size %E", + "%K%qD reading %E bytes from a region of size %E", + exp, func, range[0], slen) + : warning_n (loc, opt, tree_to_uhwi (range[0]), + "%Kreading %E byte from a region of size %E", + "%Kreading %E bytes from a region of size %E", + exp, range[0], slen)); else if (tree_int_cst_sign_bit (range[1])) { /* Avoid printing the upper bound if it's invalid. */ - warning_at (loc, opt, - "%K%qD reading %E or more bytes from a region " - "of size %E", - exp, func, range[0], slen); + warned = (func + ? warning_at (loc, opt, + "%K%qD reading %E or more bytes from a region " + "of size %E", + exp, func, range[0], slen) + : warning_at (loc, opt, + "%Kreading %E or more bytes from a region " + "of size %E", + exp, range[0], slen)); } else - warning_at (loc, opt, - "%K%qD reading between %E and %E bytes from a region " - "of size %E", - exp, func, range[0], range[1], slen); + warned = (func + ? warning_at (loc, opt, + "%K%qD reading between %E and %E bytes from " + "a region of size %E", + exp, func, range[0], range[1], slen) + : warning_at (loc, opt, + "%Kreading between %E and %E bytes from " + "a region of size %E", + exp, range[0], range[1], slen)); + if (warned) + TREE_NO_WARNING (exp) = true; + return false; } |