Package: coreutils;
Reported by: Edward Schwartz <edmcman <at> cmu.edu>
Date: Mon, 11 Jun 2012 19:27:01 UTC
Severity: normal
Done: Jim Meyering <jim <at> meyering.net>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Jim Meyering <jim <at> meyering.net> To: Edward Schwartz <edmcman <at> cmu.edu> Cc: 11675 <at> debbugs.gnu.org Subject: bug#11675: stty bad C semantics Date: Tue, 12 Jun 2012 16:33:47 +0200
Edward Schwartz wrote: > Hi, > > I think there is a bug in main() of stty in coreutils 8.17. The gist > of the problem is that two structures are initialized: > > struct termios mode = { 0, }; > > and > > struct termios new_mode = { 0, }; > > They are then both modified, and then compared with memcmp. The > problem is that the structs contain padding bytes. The C99 standard > says "The value of padding bytes when storing values in structures or > unions (6.2.6.1)." is unspecified, so the padding bytes may not be set > to zero. > > I don't have any problem compiling with gcc. On my machine, gcc > initializes the entire struct memory with a loop that writes 0. > > I came across the bug when compiling coreutils under CIL, which > rewrites many C language constructs to make them easier to analyze. > CIL writes 0 to each struct field, leaving padding bytes untouched. > Both are correct, under my interpretation of the C99 standard. > However, CIL's behavior violates the assumptions of stty's memcmp, > which assumes padding bytes are set to zero. > > The problem is easily fixed by using memset, instead of implied > initializations. I am attaching a patch that does this. While it > won't affect most coreutils users, it might save some time for someone > using a non-standard compiler or analysis platform. > > Thanks, > Ed > > Index: stty.c > =================================================================== > --- stty.c (revision 11019) > +++ stty.c (working copy) > @@ -729,7 +729,8 @@ > { > /* Initialize to all zeroes so there is no risk memcmp will report a > spurious difference in an uninitialized portion of the structure. */ > - struct termios mode = { 0, }; > + struct termios mode; > + memset(&mode, 0, sizeof(mode)); > > enum output_type output_type; > int optc; > @@ -1002,8 +1003,9 @@ > { > /* Initialize to all zeroes so there is no risk memcmp will report a > spurious difference in an uninitialized portion of the structure. */ > - struct termios new_mode = { 0, }; > - > + struct termios new_mode; > + memset(&new_mode, 0, sizeof(new_mode)); > + > if (tcsetattr (STDIN_FILENO, TCSADRAIN, &mode)) > error (EXIT_FAILURE, errno, "%s", device_name); Hi Ed, Thank you for the report and the patch. That has prompted a nicely animated debate ;-) Here's a way to solve the problem that doesn't require restoring the memset calls. It feels slightly hackish, but there's already a comment in each case, so it seems ok. From 5c2181c870f4bc1abaee8ffd0b088ab05f87a61c Mon Sep 17 00:00:00 2001 From: Jim Meyering <meyering <at> redhat.com> Date: Tue, 12 Jun 2012 16:13:43 +0200 Subject: [PATCH] stty: portability: accommodate CIL * src/stty.c (main): Declare locals "mode" and "new_mode" to be static to ensure that each is initialized to zero, *including* all padding. While gcc clears padding of a local automatic initialized to "{ 0, }", CIL does not, and the C99 standard is not clear on this issue. Reported by Edward Schwartz. See http://bugs.gnu.org/11675 for details. --- THANKS.in | 1 + src/stty.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/THANKS.in b/THANKS.in index b9a6c64..51b2c7d 100644 --- a/THANKS.in +++ b/THANKS.in @@ -172,6 +172,7 @@ Doug Coleman coleman <at> iarc1.ece.utexas.edu Doug McLaren dougmc <at> comco.com Dragos Harabor dharabor <at> us.oracle.com Duncan Roe duncanr <at> optimation.com.au +Edward Schwartz edmcman <at> cmu.edu Edward Welbourne eddy <at> opera.com Edzer Pebesma Edzer.Pebesma <at> rivm.nl Egmont Koblinger egmont <at> uhulinux.hu diff --git a/src/stty.c b/src/stty.c index a3fc3dd..83b502c 100644 --- a/src/stty.c +++ b/src/stty.c @@ -730,7 +730,7 @@ main (int argc, char **argv) { /* Initialize to all zeroes so there is no risk memcmp will report a spurious difference in an uninitialized portion of the structure. */ - struct termios mode = { 0, }; + static struct termios mode; enum output_type output_type; int optc; @@ -1003,7 +1003,7 @@ main (int argc, char **argv) { /* Initialize to all zeroes so there is no risk memcmp will report a spurious difference in an uninitialized portion of the structure. */ - struct termios new_mode = { 0, }; + static struct termios new_mode; if (tcsetattr (STDIN_FILENO, TCSADRAIN, &mode)) error (EXIT_FAILURE, errno, "%s", device_name); -- 1.7.11.rc2.5.g68f532f
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.