[PING 2] [PATCH 3/4] enhance overflow and truncation detection in strncpy and strncat (PR 81117)
Martin Sebor
msebor@gmail.com
Tue Aug 29 05:07:00 GMT 2017
Ping #2: https://gcc.gnu.org/ml/gcc-patches/2017-08/msg00912.html
On 08/23/2017 01:46 PM, Martin Sebor wrote:
> Ping: https://gcc.gnu.org/ml/gcc-patches/2017-08/msg00912.html
>
> Jeff, is this version good to commit or are there any other
> changes you'd like to see?
>
> Martin
>
> On 08/14/2017 04:40 PM, Martin Sebor wrote:
>> On 08/10/2017 01:29 PM, Martin Sebor wrote:
>>>>> 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? 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.
>>>
>>> You're right, there is an API for this (array_at_struct_end_p,
>>> as Richard pointed out). I didn't want to use it because it
>>> treats any array at the end of a struct as a flexible array
>>> member, but simple tests show that that's what -Wstringop-
>>> overflow does now, and it wasn't my intention to tighten up
>>> the checking under this change. It surprises me that no tests
>>> exposed this. Let me relax the check and think about proposing
>>> to tighten it up separately.
>>
>> Done in the attached patch. (I opened bug 81849 for the enhancement
>> to have -Wstringop-overflow diagnose overflows when writing to member
>> arrays bigger than 1 element even if they're last).
>>
>> (I've left the handling for zero size in place because GCC allows
>> global arrays to be declared to have zero elements.)
>>
>>>
>>>>> @@ -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.
>>>
>>> Corrected. The return value is unused by the only caller so
>>> there is no test to exercise it.
>>
>> Done in the attached patch.
>>
>>>>> +/* 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.
>>>
>>> Thanks. I'll have to remember this.
>>
>> I went with this simple approach for now since it worked for GDB.
>> If it turns out that there are important instances of this idiom
>> that rely on intervening statements the warning can be relaxed.
>>
>>>> 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.
>>
>>>>> /* 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'm not sure I understand why. It's a pre-existing function that
>>> just dispatches to the built-in handlers. We don't rename function
>>> callers each time we improve error/warning detection in some
>>> function they call (case in point: all the expanders in builtins.c)
>>> Why do it here? And what would be a suitable name? All that comes
>>> to my mind is awkward variations on strlen_optimize_stmt_and_warn.
>>
>> I've left the function name as is. If you feel strongly that
>> it needs to be renamed let me know.
>>
>> Martin
>
More information about the Gcc-patches
mailing list