bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: bug: printf overruns an argument


From: Paul Eggert
Subject: Re: bug: printf overruns an argument
Date: 24 Mar 2003 16:23:37 -0800
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.3

TAKAI Kousuke <address@hidden> writes:

> I made the following patch to fix this problem.  I also made
> a lone backslash at the end of string to be treated as a
> literal backslash (Solaris and FreeBSD's printf behave as
> this), but this may be inappropriate.

Thanks for reporting this.  Your patch is quite appropriate as far as
it goes, but unfortunately it is incomplete, since there's another
related buffer overrun.  Also, I found some other examples where
printf does not conform to POSIX:

        $ ./printf '\X'
        printf: \X: invalid escape

POSIX says that the output should be '\X'.


        $ ./printf '\x40'
        @

POSIX says that the output should be '\x40'.


        $ ./printf '% +d' 234
        printf: %+: invalid directive

POSIX says that the output should be '+234'.


Here is a proposed patch for all these problems:

2003-03-24  Paul Eggert  <address@hidden>

        Fix buffer overrun problem reported by TAKAI Kousuke, along
        with some other POSIX incompatibilities.

        * src/printf.c (print_esc): Do not treat \x specially if
        POSIXLY_CORRECT.  Avoid buffer overrun if the format ends
        in backslash.  Treat incomplete escape sequences as strings
        of characters, as POSIX requires.
        (print_formatted): Allow multiple flags.  Avoid buffer overrun
        if the format is incomplete.

--- printf.c    2003/03/11 10:30:59     4.5.11.0
+++ printf.c    2003/03/25 00:17:55     4.5.11.4
@@ -243,7 +243,7 @@ print_esc (const char *escstart)
   int esc_value = 0;           /* Value of \nnn escape. */
   int esc_length;              /* Length of \nnn escape. */
 
-  if (*p == 'x')
+  if (!posixly_correct && (*p == 'x'))
     {
       /* A hexadecimal \xhh escape sequence must have 1 or 2 hex. digits.  */
       for (esc_length = 0, ++p;
@@ -264,7 +264,7 @@ print_esc (const char *escstart)
        esc_value = esc_value * 8 + octtobin (*p);
       putchar (esc_value);
     }
-  else if (strchr ("\"\\abcfnrtv", *p))
+  else if (*p && strchr ("\"\\abcfnrtv", *p))
     print_esc_char (*p++);
   else if (!posixly_correct && (*p == 'u' || *p == 'U'))
     {
@@ -295,7 +295,14 @@ print_esc (const char *escstart)
       print_unicode_char (stdout, uni_value, 0);
     }
   else
-    error (EXIT_FAILURE, 0, _("\\%c: invalid escape"), *p);
+    {
+      putchar ('\\');
+      if (*p)
+       {
+         putchar (*p);
+         p++;
+       }
+    }
   return p - escstart - 1;
 }
 
@@ -449,7 +456,7 @@ print_formatted (const char *format, int
                }
              break;
            }
-         if (strchr ("-+ #", *f))
+         while (*f == ' ' || *f == '#' || *f == '+' || *f == '-')
            {
              ++f;
              ++direc_length;
@@ -508,7 +515,7 @@ print_formatted (const char *format, int
              ++f;
              ++direc_length;
            }
-         if (!strchr ("diouxXfeEgGcs", *f))
+         if (! (*f && strchr ("diouxXfeEgGcs", *f)))
            error (EXIT_FAILURE, 0, _("%%%c: invalid directive"), *f);
          ++direc_length;
          if (argc > 0)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]