[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
avoid undefined behavior in format(%c)
From: |
Eric Blake |
Subject: |
avoid undefined behavior in format(%c) |
Date: |
Mon, 09 Jul 2007 06:52:52 -0600 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.4) Gecko/20070604 Thunderbird/2.0.0.4 Mnenhy/0.7.5.666 |
-----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 <address@hidden>
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 address@hidden
-----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-----
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 <address@hidden> 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;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- avoid undefined behavior in format(%c),
Eric Blake <=