[Top][All Lists]
[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)