GNU bug report logs -
#11675
stty bad C semantics
Previous Next
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.
Full log
Message #29 received at 11675 <at> debbugs.gnu.org (full text, mbox):
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
This bug report was last modified 12 years and 342 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.