tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
printf(1) and incomplete escape sequence
Hello folks,
I have discovered a possible edge-case in printf(1) usage when
providing as an argument just a single backslash (`\'). In that
case printf(1) try to print through the end of *argv[] leading to
print out the first environment variable, e.g.:
| % /usr/bin/printf '\'
| printf: unknown escape sequence `\'
| ACRONYMDB=...
This happen because in printf.c:173 (-r1.37) conv_escape() is called
with a fmt that is just a `\0':
169 /* find next format specification */
170 for (fmt = format; (ch = *fmt++) != '\0';) {
171 if (ch == '\\') {
172 char c_ch;
173 fmt = conv_escape(fmt, &c_ch);
174 putchar(c_ch);
175 continue;
176 }
...and then in conv_escape() we do:
426 static char *
427 conv_escape(char *str, char *conv_ch)
428 {
429 char value;
430 char ch;
431 char num_buf[4], *num_end;
432
433 ch = *str++;
434
435 switch (ch) {
... ...
472 default:
473 warnx("unknown escape sequence `\\%c'", ch);
474 rval = 1;
475 value = ch;
476 break;
477 }
478
479 *conv_ch = value;
480 return str;
481 }
So ch is actually `\0' and due the *str++ we "jump" over the `\0', so
when the execution come back to printf.c:174 no `\0' will be found and
we iterate pass through *argv[].
What should we do if we receive just a `printf '\''?
IIUC according POSIX this is unspecified behaviour and for consistency
I have treated it similarly to the `default' case for "unknown
escape sequence" (possible patch with a candidate commit message
attached in this email).
What do you think we should do? Any feedbacks/comments about it?
Thank you!
Fix possible out-of-bounds read for empty escape sequence (i.e. a `\' alone).
The single `\' is treated as `\\' and a warning is printed and the exit status
raised (like other unknown escape sequences).
Index: printf.c
===================================================================
RCS file: /cvsroot/src/usr.bin/printf/printf.c,v
retrieving revision 1.37
diff -u -p -r1.37 printf.c
--- printf.c 16 Jun 2015 22:54:10 -0000 1.37
+++ printf.c 2 Jul 2018 14:35:45 -0000
@@ -430,6 +430,14 @@ conv_escape(char *str, char *conv_ch)
char ch;
char num_buf[4], *num_end;
+ if (*str == '\0') {
+ warnx("incomplete escape sequence");
+ rval = 1;
+ value = '\\';
+ *conv_ch = value;
+ return str;
+ }
+
ch = *str++;
switch (ch) {
Home |
Main Index |
Thread Index |
Old Index