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.
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. > > Martin > > PS The only problem I see is that GCC will call the library > function in this case, which we know is undefined and will > unavoidably read past the end of the argument and (if it > doesn't crash due to misalignment) return some indeterminate > value. That's worse than any other outcome (such as folding > the call into a constant or trapping) and can easily be > prevented. But that's a separate discussion. Right. So let's please defer it. We don't need to expand this discussion further, it's tangled enough already. jeff