Make printf safe

Paul Backus snarwin at gmail.com
Mon Jul 15 19:56:29 UTC 2024


On Monday, 15 July 2024 at 18:36:07 UTC, Walter Bright wrote:
> On 7/14/2024 7:06 AM, Timon Gehr wrote:
>> On 7/13/24 22:39, Walter Bright wrote:
>>> I propose that the compiler rewrite:
>>>
>>> ```
>>> char[] name;
>>> printf("name = %s\n", name);
>>> ```
>>> into:
>>> ```
>>> printf("name = %.*s\n", cast(int)name.length, name.ptr);
>>> ```
>>> (and mark any other use of %.*s as unsafe)
>> 
>> This part is actually not memory safe.
>
> How is it not safe?

C23, section 7.23.6.1 ("The fprintf function"), paragraph 5:

> As noted previously, a field width, or precision, or both, may 
> be indicated
> by an asterisk. In this case, an int argument supplies the 
> field width or
> precision. [...] A negative precision argument is taken as if 
> the precision
> were omitted.

So, if the length overflows a 32-bit int, it will be ignored, and 
printf will read until it finds a zero byte.

I suppose we could have the compiler insert a bounds check, in 
addition to all of the other rewrites, but at this point, it 
feels like we're not really calling printf at all; we're calling 
some other formatted-output function that's stolen printf's 
identity.


More information about the dip.ideas mailing list