[PATCH 3/4] enhance overflow and truncation detection in strncpy and strncat (PR 81117)
Richard Biener
richard.guenther@gmail.com
Thu Aug 10 07:39:00 GMT 2017
On August 10, 2017 7:26:33 AM GMT+02:00, Jeff Law <law@redhat.com> wrote:
>On 08/06/2017 02:07 PM, Martin Sebor wrote:
>> Part 3 of the series contains the meat of the patch: the new
>> -Wstringop-truncation option, and enhancements to -Wstringop-
>> overflow, and -Wpointer-sizeof-memaccess to detect misuses of
>> strncpy and strncat.
>>
>> Martin
>>
>> gcc-81117-3.diff
>>
>>
>> PR c/81117 - Improve buffer overflow checking in strncpy
>>
>> gcc/ChangeLog:
>>
>> PR c/81117
>> * builtins.c (compute_objsize): Handle arrays that
>> compute_builtin_object_size likes to fail for. Make extern.
>> * builtins.h (compute_objsize): Declare.
>> (check_strncpy_sizes): New function.
>> (expand_builtin_strncpy): Call check_strncpy_sizes.
>> * gimple-fold.c (gimple_fold_builtin_strncpy): Implement
>> -Wstringop-truncation.
>> (gimple_fold_builtin_strncat): Same.
>> * gimple.c (gimple_build_call_from_tree): Set call location.
>> * tree-ssa-strlen.c (strlen_to_stridx): New global variable.
>> (maybe_diag_bound_equal_length, is_strlen_related_p): New functions.
>> (handle_builtin_stxncpy, handle_builtin_strncat): Same.
>> (handle_builtin_strlen): Use strlen_to_stridx.
>> (strlen_optimize_stmt): Handle flavors of strncat, strncpy, and
>> stpncpy.
>> Use strlen_to_stridx.
>> (pass_strlen::execute): Release strlen_to_stridx.
>> * doc/invoke.texi (-Wsizeof-pointer-memaccess): Document
>enhancement.
>> (-Wstringop-truncation): Document new option.
>>
>> gcc/c-family/ChangeLog:
>>
>> PR c/81117
>> * c-warn.c (sizeof_pointer_memaccess_warning): Handle arrays.
>> * c.opt (-Wstriingop-truncation): New option.
>>
>> gcc/testsuite/ChangeLog:
>>
>> PR c/81117
>> * c-c++-common/Wsizeof-pointer-memaccess3.c: New test.
>> * c-c++-common/Wstringop-overflow.c: Same.
>> * c-c++-common/Wstringop-truncation.c: Same.
>> * c-c++-common/Wsizeof-pointer-memaccess2.c: Adjust.
>> * c-c++-common/attr-nonstring-2.c: New test.
>> * g++.dg/torture/Wsizeof-pointer-memaccess1.C: Adjust.
>> * g++.dg/torture/Wsizeof-pointer-memaccess2.C: Same.
>> * gcc.dg/torture/pr63554.c: Same.
>> * gcc.dg/Walloca-1.c: Disable macro tracking.
>>
>> diff --git a/gcc/builtins.c b/gcc/builtins.c
>> index 016f68d..1aa9e22 100644
>> --- a/gcc/builtins.c
>> +++ b/gcc/builtins.c
>[ ... ]
>> +
>> + if (TREE_CODE (type) == ARRAY_TYPE)
>> + {
>> + /* Return the constant size unless it's zero (that's a
>zero-length
>> + array likely at the end of a struct). */
>> + tree size = TYPE_SIZE_UNIT (type);
>> + if (size && TREE_CODE (size) == INTEGER_CST
>> + && !integer_zerop (size))
>> + return size;
>> + }
>Q. Do we have a canonical test for the trailing array idiom?
Array_at_struct_end_p
In some
>contexts isn't it size 1? ISTM This test needs slight improvement.
>Ideally we'd use some canonical test for detect the trailing array
>idiom
>rather than open-coding it here. You might look at the array index
>warnings in tree-vrp.c to see if it's got a canonical test you can call
>or factor and use.
>
>
>
>
>> @@ -3883,6 +3920,30 @@ expand_builtin_strncat (tree exp, rtx)
>> return NULL_RTX;
>> }
>>
>> +/* Helper to check the sizes of sequences and the destination of
>calls
>> + to __builtin_strncpy (DST, SRC, LEN) and __builtin___strncpy_chk.
>> + Returns true on success (no overflow warning), false otherwise.
>*/
>> +
>> +static bool
>> +check_strncpy_sizes (tree exp, tree dst, tree src, tree len)
>> +{
>> + tree dstsize = compute_objsize (dst, warn_stringop_overflow - 1);
>> +
>> + if (!check_sizes (OPT_Wstringop_overflow_,
>> + exp, len, /*maxlen=*/NULL_TREE, src, dstsize))
>> + return false;
>> +
>> + if (!dstsize || TREE_CODE (len) != INTEGER_CST)
>> + return true;
>> +
>> + if (tree_int_cst_lt (dstsize, len))
>> + warning_at (EXPR_LOCATION (exp), OPT_Wstringop_truncation,
>> + "%K%qD specified bound %E exceeds destination size %E",
>> + exp, get_callee_fndecl (exp), len, dstsize);
>> +
>> + return true;
>So in the case where you issue the warning, what should the return
>value
>be? According to the comment it should be false. It looks like you
>got
>the wrong return value for the tree_int_cst_lt (dstsize, len) test.
>
>
>
>
>
>>
>> return false;
>> diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
>> index b0563fe..ac6503f 100644
>> --- a/gcc/tree-ssa-strlen.c
>> +++ b/gcc/tree-ssa-strlen.c
>
>> +
>> +/* A helper of handle_builtin_stxncpy. Check to see if the
>specified
>> + bound is a) equal to the size of the destination DST and if so,
>b)
>> + if it's immediately followed by DST[LEN - 1] = '\0'. If a) holds
>> + and b) does not, warn. Otherwise, do nothing. Return true if
>> + diagnostic has been issued.
>> +
>> + The purpose is to diagnose calls to strncpy and stpncpy that do
>> + not nul-terminate the copy while allowing for the idiom where
>> + such a call is immediately followed by setting the last element
>> + to nul, as in:
>> + char a[32];
>> + strncpy (a, s, sizeof a);
>> + a[sizeof a - 1] = '\0';
>> +*/
>So using gsi_next to find the next statement could make the heuristic
>fail to find the a[sizeof a - 1] = '\0'; statement when debugging is
>enabled.
>
>gsi_next_nondebug would be better as it would skip over any debug
>insns.
>
>What might be even better would be to use the immediate uses of the
>memory tag. For your case there should be only one immediate use and
>it
>should point to the statement which NUL terminates the destination. Or
>maybe that would be worse in that you only want to allow this exception
>when the statements are consecutive.
>
>
>> +
>> + /* Look for dst[i] = '\0'; after the stxncpy() call and if found
>> + avoid the truncation warning. */
>> + gsi_next (&gsi);
>> + gimple *next_stmt = gsi_stmt (gsi);
>Here's the gsi_next I'm referring to.
>
>
>> + else
>> + {
>> + /* The source length is uknown. Try to determine the
>destination
>s/uknown/unknown/
>
>
>
>> /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
>> If strlen of the second argument is known and length of the third
>argument
>> is that plus one, strlen of the first argument is the same after
>this
>> @@ -2512,6 +2789,19 @@ strlen_optimize_stmt (gimple_stmt_iterator
>*gsi)
>You still need to rename strlen_optimize_stmt since after your changes
>it does both optimizations and warnings.
>
>I think we're going to need one more iteration on this patch within the
>kit. I'm glazing over a bit tonight.
>
>jeff
More information about the Gcc-patches
mailing list