Thread overview | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 13 Make printf safe | ||||
---|---|---|---|---|
| ||||
The idea is printf is already largely safe: ``` printf("number = %d\n", 3); ``` is perfectly safe. Unsafe problems: 1. if the arguments and their types do not match the format string. D already checks for that, so we're good there. 2. if a pointer is passed to %s: ``` char* name; printf("name = %s\n", name); ``` That's unsafe. We normally fix this with: ``` char[] name; printf("name = %.*s\n", cast(int)name.length, name.ptr); ``` Which is safe, because we know how printf() works. 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) We can go further, and realize that since we already check the format string against the arguments, we can rewrite the format string to match the arguments: ``` printf("number = %s\n", 3); ``` becomes: ``` printf("number = %d\n", 3); ``` which makes it much simpler to use printf. I can never remember which format is for size_t, for example. The one format specification (I forgot which one) which assigns a int value through a pointer, can simply be marked as unsafe. Of course, this only applies if the format string is a literal, not a variable. Since dmd already scans and checks the format string against the argument list, most of the work for this proposal is already done. |
July 13 Re: Make printf safe | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Saturday, 13 July 2024 at 20:39:32 UTC, Walter Bright wrote:
> printf
I basically never use the old c printf syntax and Im pretty sure thats true of 95% of people here, as far as I know theres one usecase for printf and thats picking float significant digits.
Printing in a template lang with a pretty solid print api norm(as far as I know everyone on board with toString) have far better methods then the c norms. Templates and a lib level decisions should be the way forward; now if you want to make those better(such as handling the float digit overloads) this would be a point of interest for me
Off the top of my head, you should*nt* verify c formated strings at all, those cryptic letters are form a very long dead era; if your changing the api but want to make it follow to old way, drop everything but '%' scanning i.e. `printf("hello %, today is %.\n","bob",days.monday);`
|
July 14 Re: Make printf safe | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Saturday, 13 July 2024 at 20:39:32 UTC, Walter Bright wrote:
> The idea is printf is already largely safe:
This is trivially achievable with IES. Do not waste time on making the compiler have some special case here.
-Steve
|
July 13 Re: Make printf safe | ||||
---|---|---|---|---|
| ||||
Posted in reply to monkyyy | I understand the desire to use modern write(). But there is a place for a lightweight way to do formatted writing. 1. If you're just linking with the stdc library, there is no write(). 2. printf is probably the most debugged and optimized piece of code that has ever existed. Borland C recoded it in hand-optimized assembler, which was a brilliant move as its fast printf covered for a lot of weakness in its poor code generator 3. write() won't work until pretty much everything in the compiler works. With printf, I can get hello world to work needing only a minimally functional compiler 4. can't use Phobos in dmd's source code, because if a working Phobos was required, it becomes much much harder to bootstrap it 5. most any use of write() causes a rather large pile of template bloat to be inserted into the object file. This makes life difficult when trying to isolate a bug. Currently, dmd's checking of the arguments against the format string has already eliminated a large chunk of the problems with printf. It enabled the removal of dozens of bugs in the dmd code base. A big win! My proposal is pretty lightweight, the heavy lifting was already done with the argument checking. It enables @safe use of printf, and removes the temptation to rely on char* strings instead of char[] strings. |
July 14 Re: Make printf safe | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | While this does seem to be useful, there is an issue for adoption with dmd. It'll fool you into thinking it works with the latest compiler when bootstrapping, and silently cause broken programs in older ones. Steven is right, interpolated string wrapper around printf would be a better option. |
July 14 Re: Make printf safe | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | 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. In general, I guess provided we can get it right, extending the `pragma(printf)` checks in `@safe` code is indeed an improvement to the language, though I think not a lot of people need this. You should probably have to mark the `printf` prototype as `@trusted` for this to work though. (There are `pragma(printf)` functions that still have a `@system` interface even when there is nothing wrong with the format string and arguments, e.g. `sprintf`.) For everyone who is not aware, here's D's existing `printf` support: https://dlang.org/spec/pragma.html#printf Probably `pragma(scanf)` would need to get similar treatment. |
July 15 Re: Make printf safe | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 7/13/2024 6:10 PM, Steven Schveighoffer wrote:
> This is trivially achievable with IES.
What is IES?
|
July 16 Re: Make printf safe | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 16/07/2024 6:25 AM, Walter Bright wrote: > On 7/13/2024 6:10 PM, Steven Schveighoffer wrote: >> This is trivially achievable with IES. > > What is IES? https://dlang.org/spec/istring.html |
July 15 Re: Make printf safe | ||||
---|---|---|---|---|
| ||||
Posted in reply to Richard (Rikki) Andrew Cattermole | On 7/13/2024 11:39 PM, Richard (Rikki) Andrew Cattermole wrote: > It'll fool you into thinking it works with the latest compiler when bootstrapping, and silently cause broken programs in older ones. It won't be silent, as printf argument checking has been around for many years in dmd. > Steven is right, interpolated string wrapper around printf would be a better option. That's more work. |
July 15 Re: Make printf safe | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | 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? > In general, I guess provided we can get it right, extending the `pragma(printf)` checks in `@safe` code is indeed an improvement to the language, though I think not a lot of people need this. *I* need it :-) It's an enabling feature, in that it enables me to much more fully transition dmd away from using 0 terminated strings. > You should probably have to mark the `printf` prototype as `@trusted` for this to work though. (There are `pragma(printf)` functions that still have a `@system` interface even when there is nothing wrong with the format string and arguments, e.g. `sprintf`.) It would apply to snprintf, but not sprintf which is not fixable. > For everyone who is not aware, here's D's existing `printf` support: > https://dlang.org/spec/pragma.html#printf > > Probably `pragma(scanf)` would need to get similar treatment. Possibly, but scanf is almost never used :-/ |
Copyright © 1999-2021 by the D Language Foundation