[PATCH] Adjust tree-ssa-strlen.c for irange API.
Martin Sebor
msebor@gmail.com
Wed Aug 5 00:11:48 GMT 2020
On 8/4/20 3:23 PM, Aldy Hernandez wrote:
>
>
> On 8/4/20 9:34 PM, Martin Sebor wrote:
>> On 8/4/20 5:33 AM, Aldy Hernandez via Gcc-patches wrote:
>>> This patch adapts the strlen pass to use the irange API.
>>>
>>> I wasn't able to remove the one annoying use of VR_ANTI_RANGE, because
>>> I'm not sure what to do. Perhaps Martin can shed some light. The
>>> current code has:
>>>
>>> else if (rng == VR_ANTI_RANGE)
>>> {
>>> wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE
>>> (ptrdiff_type_node));
>>> if (wi::ltu_p (cntrange[1], maxobjsize))
>>> {
>>> cntrange[0] = cntrange[1] + 1;
>>> cntrange[1] = maxobjsize;
>>>
>>> Suppose we have ~[10,20], won't the above set cntrange[] to [21,MAX]?
>>> Won't
>>> this ignore the 0..9 that is part of the range? What should we do here?
>>
>> cntrange is the range of the strncpy (and strncat) bound. It does
>> ignore the lower subrange but I think that's intentional because
>> the lower the bound the more likely the truncation, so it serves
>> to minimize false positives.
>>
>> I didn't see any tests fail with the anti-range block disabled but
>> with some effort I was able to come up with one:
>>
>> char a[7];
>>
>> void f (int n)
>> {
>> if (n > 3)
>> n = 0;
>>
>> strncpy (a, "12345678", n); // -Wstringop-truncation
>> }
>>
>> The warning disappears when the anti-range handling is removed so
>> unless that's causing headaches for the new API I think we want to
>> keep it (and add the test case :)
>
> Hi Martin.
>
> Thanks for taking the time to respond.
>
> On the strlen1 dump I see that the 3rd argument to strncpy above is:
>
> long unsigned int ~[4, 18446744071562067967]
>
> which is a fancy way of saying:
>
> long unsigned int [0,3][18446744071562067967,+INF]
>
> The second sub-range is basically [INT_MIN,+INF] for the original int N,
> which makes sense because N could be negative on the way in.
>
> I don't understand the warning though:
>
> a.c:8:5: warning: ‘__builtin_strncpy’ output truncated copying between 0
> and 3 bytes from a
> string of length 8 [-Wstringop-truncation]
> 8 | __builtin_strncpy (a, "12345678", n); //
> -Wstringop-truncation
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> The range of the bound to strncpy can certainly be [0,3], but it can
> also be [1844...,+INF] which shouldn't warn.
strncpy(d, s, n) zeroes out the destination after it copies s, up
to n - strlen (s). It's been a while and -Wstringop-truncation
certainly has its quirks (to put it nicely) but I think this one
is a feature.
>
> In a world without anti-ranges, we'd see the 2 sub-ranges above. How
> would you suggest handling it? We could nuke out the uppermost
> sub-range, but what if the range is [0,3][10,20]? Perhaps remove from
> some arbitrary number on up? Say...[0xf.....,+INF]? This seems like a
> hack, but perhaps is what's needed???
The second subrange in [0, 3][10, 20] is out of bounds for char[7]
and the first one truncates so either we issue -Wstringop-truncation
or if not, -Wstringop-overflow.
A better example might be [0, 3][5, 7] with "1234" as the source.
Only one of these ranges truncates so a warning would probably not
be called for. Only warn when there's no range that doesn't lead
to truncation.
It will get more interesting if/when the length of the source string
is also in a discontiguous range. My head is already starting to hurt.
Martin
>
> It doesn't seem like the above source should warn. Am I missing something?
>
> Thanks.
> Aldy
>
More information about the Gcc-patches
mailing list