[committed] libstdc++: Replace operator>>(istream&, char*) [LWG 2499]
Jonathan Wakely
jwakely@redhat.com
Thu Aug 6 10:40:48 GMT 2020
On 06/08/20 12:12 +0200, Jakub Jelinek wrote:
>On Wed, Aug 05, 2020 at 04:31:08PM -0600, Martin Sebor via Gcc-patches wrote:
>> I've always found the second argument to __builtin_object_size
>> confusing for types above 1. I don't see anything wrong in
>> the diff but I believe the most useful results are with type 1
>> for string functions and type 0 for raw memory functions like
>> memcpy (that's what _FORTIFY_SOURCE uses for the two sets of
>> functions). In type 2 when the result is zero it means one of
>> two things: either the size of the array couldn't be determined
>> or it really is zero. That's less than helpful in cases like:
>>
>> char a[8];
>> strcpy (a + 8, s);
>>
>> where it prevents detecting the buffer overflow.
>
>I don't know what is confusing about it.
Personally I find the docs very confusing.
"The second bit determines if maximum or minimum of remaining bytes is
computed. "
OK, so is it maximum when the bit is set of maximum when the bit is
clear?
To answer that question I have to go back to the middle of the
previous paragraph and carefully parse it.
"the returned number is the maximum of remaining byte counts in those
objects if type & 2 is 0 and minimum if nonzero."
This part talks about "if type & 2 is 0" and "nonzero", could we be
consistent and talk about a bit being clear/set, or use bitwise
operator notation, but not flip between the two? And use zero/nonzero
rather than 0/nonzero?
The inconsistency in presentation increases the mental load of parsing
it. I'll propose a patch for those docs when I get time.
>With the 0/1 arguments bos returns an upper bound for the object size
>(and the don't know value is the maximum in that case, i.e. (size_t)-1),
>while with 2/3 arguments bos returns an lower bound for the object size
>(and thus the don't know value is the minimum value, i.e. 0).
>The 2/3 modes are obviously not something you want to use in strcpy etc.
>implementation, in those cases you want to abort the program only when
>it is guaranteed to be invalid, i.e. when it will certainly overflow
>the available size in any case, while with the 2/3 modes it would abort already
>if there is a possibility the object might not be big enough.
For my case I'm not aborting, I'm deciding whether to use the result
from __builtin_object_size or just assume the array is as large as the
entire address space (which is the old behaviour).
I think Martin's right that I should use 0. Technically I could
probably use 1, because for struct S { char buf1[2]; char buf2[2]; };
it would be undefined to write 4 bytes into it, but it "worked" with
previous versions and so I'm choosing to let it keep "working". This
doesn't need to be 100% safe, because the API has been replaced by a
safer one for C++20 anyway.
>One can e.g. use both modes to check if the object is known to have exactly
>a particular size, when
>__builtin_object_size (ptr, 0) == __builtin_object_size (ptr, 2)
>and the bos returns say 25, then you know it is exactly 25 bytes.
>E.g. if one has:
> ptr = flag ? malloc (32) : malloc (64);
> x[0] = __builtin_object_size (ptr, 0);
> x[1] = __builtin_object_size (ptr, 2);
>then x[0] will be 64 as the maximum and x[1] to 32 as the minimum (of course
>unless flag can be folded to constant, then both would be the same depending
>on to which constant it is folded).
>
> Jakub
More information about the Libstdc++
mailing list