On 08/21/2018 09:56 AM, Jeff Law wrote:
On 08/21/2018 09:37 AM, Martin Sebor wrote:
On 08/21/2018 05:50 AM, Joseph Myers wrote:
On Tue, 21 Aug 2018, Martin Sebor wrote:

I still believe it would be simpler, more robust, and safe
to pass in a flag to either count bytes (the default, for
all callers except sprintf %ls), or elements of the string
type (for sprintf %ls).

But the correct thing to count for sprintf %ls is elements of the type
expected by sprintf %ls.  That may not be the type of the string constant
(and as this is in variable arguments, there isn't any implicit
conversion
to const wchar_t * like you would get with a function prototype - I'm not
sure if anything ensures this code is only reached, regardless of
language, if the argument does actually (after any casts present in the
source code) point to the correct wchar_t type).

Sure, but the only valid argument to %ls is wchar_t*.  Passing
it something else is undefined.

The only caller interested in the element count is %ls and
the only case where the function could return a result that
might be different from that of C wcslen() with the same
(invalid) argument is the undefined:

  snprintf (0, 0, "%ls", "1234");

In this case, c_strlen() would return 4 which GCC's snprintf
turns into [0, 24], and calls the libc snprintf which will
then proceed to read past the end of the narrow string and
return some bogus value (if it doesn't crash).

So I don't see a problem here(*).
I think we should be counting wchar_ts in this case.   If someone passes
something other than a wchar_t as the argument for a %ls, then the code
is in error.

Sure, counting wchar_t's would be fine too.  But it doesn't
do that either -- it fails.

At issue is we need a way for the sprintf code to indicate to c_strlen
the size of a wchar_t argument.  Between Joseph's suggestions and my own
poking around I think we can do that.  I just have to fight aix long
enough to be able to do some testing.


In any event, my main concern isn't whether the function take
a flag or an element size as an argument.  What I believe it
needs to do is count bytes when requested even when the array
is a wide string.
Umm, that's precisely what it does.  If you ask it to count bytes, it'll
count bytes.  You can request to count 16bit wchat_t and a 32bit wchar_t
objects.  So I'm not sure why we're still arguing over this.

No, that's not what the function does.

It fails when the request doesn't match the type of the array
element: i.e, it fails when passed a wchar_t array and ELTSIZE
== 1.  This is because of the following test:

  /* Determine the size of the string element.  */
if (eltsize != tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (src)))))
    return NULL_TREE;

This prevents diagnosing the interesting cases that we have been
discussing here (missing nuls and the type mismatches).

Martin

Reply via email to