diff options
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 126 |
1 files changed, 90 insertions, 36 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index f7bb87e..667d36c 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3310,6 +3310,90 @@ determine_block_size (tree len, rtx len_rtx, GET_MODE_MASK (GET_MODE (len_rtx))); } +/* For an expression EXP issue an access warning controlled by option OPT + with access to a region SLEN bytes in size in the RANGE of sizes. */ + +static bool +warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2], + tree slen, bool access) +{ + bool warned = false; + + if (access) + { + if (tree_int_cst_equal (range[0], range[1])) + 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. */ + 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 + 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)); + + return warned; + } + + if (tree_int_cst_equal (range[0], range[1])) + warned = (func + ? warning_n (loc, opt, tree_to_uhwi (range[0]), + "%K%qD epecting %E byte in a region of size %E", + "%K%qD expecting %E bytes in a region of size %E", + exp, func, range[0], slen) + : warning_n (loc, opt, tree_to_uhwi (range[0]), + "%Kexpecting %E byte in a region of size %E", + "%Kexpecting %E bytes in 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. */ + warned = (func + ? warning_at (loc, opt, + "%K%qD expecting %E or more bytes in a region " + "of size %E", + exp, func, range[0], slen) + : warning_at (loc, opt, + "%Kexpecting %E or more bytes in a region " + "of size %E", + exp, range[0], slen)); + } + else + warned = (func + ? warning_at (loc, opt, + "%K%qD expecting between %E and %E bytes in " + "a region of size %E", + exp, func, range[0], range[1], slen) + : warning_at (loc, opt, + "%Kexpectting between %E and %E bytes in " + "a region of size %E", + exp, range[0], range[1], slen)); + return warned; +} + /* Try to verify that the sizes and lengths of the arguments to a string manipulation function given by EXP are within valid bounds and that the operation does not lead to buffer overflow or read past the end. @@ -3336,12 +3420,16 @@ determine_block_size (tree len, rtx len_rtx, When DSTWRITE is null LEN is checked to verify that it doesn't exceed SIZE_MAX. + ACCESS is true for accesses, false for simple size checks in calls + to functions that neither read from nor write to the region. + If the call is successfully verified as safe return true, otherwise return false. */ bool check_access (tree exp, tree, tree, tree dstwrite, - tree maxread, tree srcstr, tree dstsize) + tree maxread, tree srcstr, tree dstsize, + bool access /* = true */) { int opt = OPT_Wstringop_overflow_; @@ -3649,44 +3737,10 @@ 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])) - 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. */ - 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 - 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) + if (warn_for_access (loc, func, exp, opt, range, slen, access)) TREE_NO_WARNING (exp) = true; return false; |