printf %n is not implemented
The following code does not work as expected:
int main(int argc, char **argv) {
int i, len;
char buf[100];
len = snprintf(buf, sizeof(buf), "Hello-%n%s", &i, argv[0]);
printf(">> all=%s\n", buf);
printf(">> par=%.*s\n", len-i, &buf[i]);
return 0;
}
When compiled on Linux, the output is:
>> all=Hello-./main
>> par=./main
When compiled with Cosmopolitan, the output is:
>> all=Hello-n�,@
>> par=
I can get that fixed for you.
Hi Justine, It's not blocking right now (I have split a single, clumsy, unreadable call to snprintf to two separate ones).... but I created that task just to remember to do it eventually (I can also take a look later). (I am testing the implementation of the syslog-related functions). Regards, Fab
On Tue, Mar 23, 2021 at 3:34 PM Justine Tunney @.***> wrote:
I can get that fixed for you.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/jart/cosmopolitan/issues/133#issuecomment-805177292, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB5RDSKWUS5D7VYD5ZYURRTTFDUM3ANCNFSM4ZVG3L7Q .
Hmm it seems this is the formatting directive that has a history of being misused. Sadly POSIX doesn't say it's optional. Implementing this one is going to be a little painful because __fmt currently doesn't track the number of bytes written, but that could be changed.
Is there such a thing as a legitimate use of %n which isn't for exploit development ?
Internet experts seem to consider that question an open question:
- https://stackoverflow.com/questions/3401156/what-is-the-use-of-the-n-format-specifier-in-c
- https://news.ycombinator.com/item?id=24317249
Wouldn't « implementing a new libc » be the right place to stop that questionable option from being a thing, and not implement it ?
Is there such a thing as a legitimate use of %n which isn't for exploit development ?
FWIW, I use it everyday for parsing lists of numbers of unknown length (typically 2 or 3 numbers)
// fill the array "t" with at most "nmax" numbers parsed from the string "s"
// return the number of parsed numbers
// example:
// double t[10];
// int n = parse_doubles(t, 10, "[1, 2, 3; 4, 5, 6]");
// // n = 6; t = {1,2,3,4,5,6}
int parse_doubles(double *t, int nmax, const char *s)
{
int i = 0, w;
while (i < nmax && 1 == sscanf(s, "%*[][ \n\t,:;]%lf%n", t + i, &w)) {
i += 1;
s += w;
}
return i;
}
but this is just a matter of lazy convenience. It wouldn't be a great deal if it disappeared, and I would totally understand the reasons.