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: TAKAI Kousuke
Subject: Re: bug: printf overruns an argument
Date: Thu, 27 Mar 2003 22:29:25 +0900
User-agent: T-gnus/6.15.10 (based on Oort Gnus v0.10) EMIKO/1.14.1 (Choanoflagellata) SLIM/1.14.8 (小池栄子) APEL/10.3 Emacs/21.3 (sparc-sun-solaris2.6) MULE/5.0 (賢木)

Hello,

Paul Eggert <address@hidden> wrote:

>> 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:

I found yet other ones:

  $ ./printf '\0123'
  S

POSIX says that octal escape sequences in FORMAT are specified
as "\ddd" where ddd is a one, two, or three-digit octal number,
thus the output should be a newline character (\012) followed
by a character `3'.
(In the other hand, octal escape sequences in %b's arguments
are specified as "\0ddd" where ddd is zero to three-digit octal
number, which meets current GNU printf's behaviour.)

  $ ./printf 'ab\cdef'
  ab

POSIX says that \c is only recognized in arguments for %b,
thus I think `ab\cdef' is better output than `ab'.

Here is a patch for these problem.  Change for \c may break
some existing applications, so I protected it with POSIXLY_CORRECT,
but this may not be appropriate.

2003-03-27  TAKAI Kousuke  <address@hidden>

        * src/printf.c (print_esc): New argument PERCENT_B.
        Recognize \ooo for FORMAT, \0ooo for %b.
        Handle \c here, but don't handle when parsing FORMAT
        and POSIXLY_CORRECT is set.
        (print_esc_char): Remove handling of \c.
        (print_esc_string, print_formatted): Callers of `print_esc'
        changed.

--- coreutils-4.5.11/src/printf.c.orig  2003-03-27 20:54:17.000000000 +0900
+++ coreutils-4.5.11/src/printf.c       2003-03-27 22:03:56.131165180 +0900
@@ -208,9 +208,6 @@ print_esc_char (int c)
     case 'b':                  /* Backspace. */
       putchar (8);
       break;
-    case 'c':                  /* Cancel the rest of the output. */
-      exit (EXIT_SUCCESS);
-      break;
     case 'f':                  /* Form feed. */
       putchar (12);
       break;
@@ -237,7 +234,7 @@ print_esc_char (int c)
    besides the backslash. */
 
 static int
-print_esc (const char *escstart)
+print_esc (const char *escstart, bool percent_b)
 {
   register const char *p = escstart + 1;
   int esc_value = 0;           /* Value of \nnn escape. */
@@ -254,17 +251,29 @@ print_esc (const char *escstart)
        error (EXIT_FAILURE, 0, _("missing hexadecimal number in escape"));
       putchar (esc_value);
     }
+  else if (!percent_b && isodigit (*p))
+    {
+      /* An octal \ooo esacape sequence has 1 to 3 octal digits.
+        Recognized only in FORMAT.  */
+      for (esc_value = octtobin (*p), esc_length = 1, ++p;
+          esc_length < 3 && isodigit (*p);
+          ++esc_length, ++p)
+       esc_value = esc_value * 8 + octtobin (*p);
+      putchar (esc_value);
+    }
   else if (*p == '0')
     {
       /* An octal \0ooo escape sequence has 0 to 3 octal digits
-        after the leading \0.  */
+        after the leading \0.  Recognized for arguments for %b.  */
       for (esc_length = 0, ++p;
           esc_length < 3 && isodigit (*p);
           ++esc_length, ++p)
        esc_value = esc_value * 8 + octtobin (*p);
       putchar (esc_value);
     }
-  else if (*p && strchr ("\"\\abcfnrtv", *p))
+  else if ((!posixly_correct || percent_b) && *p == 'c')
+    exit (EXIT_SUCCESS);       /* Cancel the rest of the output. */
+  else if (*p && strchr ("\"\\abfnrtv", *p))
     print_esc_char (*p++);
   else if (!posixly_correct && (*p == 'u' || *p == 'U'))
     {
@@ -313,7 +322,7 @@ print_esc_string (const char *str)
 {
   for (; *str; str++)
     if (*str == '\\')
-      str += print_esc (str);
+      str += print_esc (str, true);
     else
       putchar (*str);
 }
@@ -531,7 +540,7 @@ print_formatted (const char *format, int
          break;
 
        case '\\':
-         f += print_esc (f);
+         f += print_esc (f, false);
          break;
 
        default:
[patch ends here]

Sorry for my poor English, and for troubling you
about my incomplete patch.

-- 
 TAKAI Kousuke <address@hidden>
  Dept. of Communications and Computer Engineering,
  Graduate School of Infomatics, Kyoto University, Japan




reply via email to

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