avoid undefined behavior in format(%c)
Eric Blake <[email protected]>
| Newsgroups | gmane.comp.gnu.m4.patches |
|---|---|
| Message-ID | <[email protected]> |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
I introduced a regression in 1.4.9b where format(%c,65) would call
printf("%*.*c",0,-1,'a') under the hood, but that is undefined in POSIX.
This is just a stop-gap measure so that I can release 1.4.10 without known
undefined behavior; I still intend to make 1.4.11 where the format builtin
has more capabilities bringing it more in line with printf(1), but want to
get a GPLv3 version out now rather than after completing that patch.
I'm applying this to both branch and head. My goal is to get 1.4.10 out
by tomorrow.
2007-07-09 Eric Blake <[email protected]>
Avoid undefined behavior of %.*c in printf.
* src/format.c (format): Special case %c.
* TODO: Document that more remains to be done.
* NEWS: Document the fix.
- --
Don't work too hard, make some time for fun as well!
Eric Blake [email protected]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFGki+k84KuGfSFAYARAiJPAJwJMnYYR3/K6SpeKR5VMmetyBSjYwCgqqFU
97SHUuO1CrJlcNjXa4RQBwY=
=iTY5
-----END PGP SIGNATURE-----
_______________________________________________
M4-patches mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/m4-patches
m4.patch272
(text/plain, 4.3 KB)
Index: NEWS =================================================================== RCS file: /sources/m4/m4/NEWS,v retrieving revision 1.1.1.1.2.106 diff -u -p -r1.1.1.1.2.106 NEWS --- NEWS 5 Jul 2007 03:53:05 -0000 1.1.1.1.2.106 +++ NEWS 9 Jul 2007 12:50:54 -0000 @@ -5,6 +5,11 @@ Foundation, Inc. Version 1.4.10 - ?? ??? 2007, by ???? (CVS version 1.4.9c) * Upgrade from GPL version 2 to GPL version 3 or later. +* A number of portability improvements inherited from gnulib. +* Avoid undefined behavior introduced in 1.4.9b in the `format' builtin + when handling %c. However, this area of code has never been documented, + and currently does not match the POSIX behavior of printf(1), so it may + have further changes in the next version. Version 1.4.9b - 29 May 2007, by Eric Blake (CVS version 1.4.9a) @@ -19,7 +24,9 @@ Version 1.4.9b - 29 May 2007, by Eric Bl more predictably when stdin is seekable. * The `format' builtin now understands formats such as %a, %A, and %'hhd, and works around a number of platform printf bugs. Furthermore, the - sequence format(%*.*d,-1,-1,1) no longer outputs random data. + sequence format(%*.*d,-1,-1,1) no longer outputs random data. However, + some non-compliant platforms such as mingw still have known bugs in + strtod that may cause testsuite failures. * The testsuite is improved to also run gnulib portability tests for the features that M4 imports from gnulib. Index: TODO =================================================================== RCS file: /sources/m4/m4/TODO,v retrieving revision 1.1.1.1.2.2 diff -u -p -r1.1.1.1.2.2 TODO --- TODO 22 Aug 2006 16:13:38 -0000 1.1.1.1.2.2 +++ TODO 9 Jul 2007 12:50:54 -0000 @@ -4,6 +4,9 @@ Tell <[email protected]> if you feel like v of these ideas, listed more or less in decreasing order of priority. * Features or problems + - Fix format() builtin to handle %c more like printf(1) in the shell + http://lists.gnu.org/archive/html/bug-m4/2007-05/msg00047.html + Also, gnulib needs help to overcome mingw bugs related to format(). - Update documentation from accumulated mail about it - Study synclines at the very beginning of each diverted sequence - Make eval work on bignums - the 32 bits limit is artificial @@ -34,7 +37,7 @@ mode: outline outline-regexp: " *[-+*.] \\|" End: -Copyright (C) 2000, 2006 Free Software Foundation, Inc. +Copyright (C) 2000, 2006, 2007 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or Index: src/format.c =================================================================== RCS file: /sources/m4/m4/src/Attic/format.c,v retrieving revision 1.1.1.1.2.7 diff -u -p -r1.1.1.1.2.7 format.c --- src/format.c 29 May 2007 13:19:47 -0000 1.1.1.1.2.7 +++ src/format.c 9 Jul 2007 12:50:54 -0000 @@ -85,9 +85,9 @@ format (struct obstack *obs, int argc, t /* Buffer and stuff. */ char *str; /* malloc'd buffer of formatted text */ - enum {INT, LONG, DOUBLE, STR} datatype; + enum {CHAR, INT, LONG, DOUBLE, STR} datatype; - f = fmt = (const char *) ARG_STR (argc, argv); + f = fmt = ARG_STR (argc, argv); memset (ok, 0, sizeof ok); for (;;) { @@ -176,13 +176,11 @@ format (struct obstack *obs, int argc, t fmt++; } else - { - while (isdigit (to_uchar (*fmt))) - { - width = 10 * width + *fmt - '0'; - fmt++; - } - } + while (isdigit (to_uchar (*fmt))) + { + width = 10 * width + *fmt - '0'; + fmt++; + } /* Maximum precision; an explicit negative precision is the same as not giving the precision. A lone '.' is a precision of 0. */ @@ -238,14 +236,13 @@ format (struct obstack *obs, int argc, t fmt--; continue; } - *p++ = c; - *p = '\0'; /* Specifiers. We don't yet recognize C, S, n, or p. */ switch (c) { case 'c': - datatype = INT; + datatype = CHAR; + p -= 2; /* %.*c is undefined, so undo the '.*'. */ break; case 's': @@ -275,9 +272,15 @@ format (struct obstack *obs, int argc, t default: abort (); } + *p++ = c; + *p = '\0'; - switch(datatype) + switch (datatype) { + case CHAR: + str = xasprintf (fstart, width, ARG_INT(argc, argv)); + break; + case INT: str = xasprintf (fstart, width, prec, ARG_INT(argc, argv)); break;