Paul Eggert wrote:
> As a minor point, both uses like this:
>
> '4' <= *p && *p <= '7'
>
> can be replaced with something like this:
>
> '4' <= *p
>
...
>
> The replacements are not only shorter, but easier
> to understand, because otherwise the reader is left
> wondering why that unnecessary comparison to '7'
> (or '0') is in there.
Yep, you are right - as the octal value of *p/*b is checked later, this
shorter way is better readable and shorter.
Added the NEWS entry in addition to address Eric's email.
Greetings,
Ondrej Vasik
>From 81802d8daf94684300b55272d171e65b53d5fede Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Va=C5=A1=C3=ADk?= <[email protected]>
Date: Mon, 6 Dec 2010 17:10:31 +0100
Subject: [PATCH] echo,printf,stat: Allow only 8-bit octal input for backslash-escaped chars
* src/echo.c: (usage) Document \NNN octal format in --help
(main) Allow only 8-bit octal input for backslash-escaped chars
* src/printf.c: (print_esc) Likewise
* src/stat.c: (print_it) Likewise
* doc/coreutils.texi: Clarify printf documentation about byte octal input
* tests/misc/printf: Add test for "like 9-bit" octal value backslash-escaped
char
---
NEWS | 4 ++++
doc/coreutils.texi | 6 +++---
src/echo.c | 7 ++++++-
src/printf.c | 10 +++++++---
src/stat.c | 4 +++-
tests/misc/printf | 3 +++
6 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/NEWS b/NEWS
index c3110a3..c8a45ee 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,10 @@ GNU coreutils NEWS -*- outline -*-
sort -u with at least two threads could attempt to read through a
corrupted pointer. [bug introduced in coreutils-8.6]
+ echo, printf and stat now don't allow 9-bit octal values for
+ backslash-escaped chars.
+
+
** New features
split accepts the --number option to generate a specific number of files.
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 34d9ff0..11a9d16 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -11116,9 +11116,9 @@ the command @samp{printf %g 3,14} is an error.
@kindex \...@var{ooo}
@kindex \...@var{hh}
@command{printf} interprets @sam...@var{ooo}} in @var{format} as an octal number
-(if @var{ooo} is 1 to 3 octal digits) specifying a character to print,
-and @samp...@var{hh}} as a hexadecimal number (if @var{hh} is 1 to 2 hex
-digits) specifying a character to print.
+(if @var{ooo} is 1 to 3 octal digits byte value) specifying a character
+to print, and @samp...@var{hh}} as a hexadecimal number (if @var{hh} is
+1 to 2 hex digits) specifying a character to print.
@kindex \uhhhh
@kindex \Uhhhhhhhh
diff --git a/src/echo.c b/src/echo.c
index 6a1eeed..b72dcd5 100644
--- a/src/echo.c
+++ b/src/echo.c
@@ -78,6 +78,7 @@ If -e is in effect, the following sequences are recognized:\n\
"), stdout);
fputs (_("\
\\0NNN byte with octal value NNN (1 to 3 digits)\n\
+ \\NNN byte with octal value NNN (1 to 3 digits)\n\
\\xHH byte with hexadecimal value HH (1 to 2 digits)\n\
"), stdout);
printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
@@ -197,6 +198,7 @@ just_echo:
{
char const *s = argv[0];
unsigned char c;
+ bool threeoctdigits = false;
while ((c = *s++))
{
@@ -235,12 +237,15 @@ just_echo:
c = *s++;
/* Fall through. */
case '1': case '2': case '3':
+ if (c < '4')
+ threeoctdigits = true;
case '4': case '5': case '6': case '7':
c -= '0';
if ('0' <= *s && *s <= '7')
c = c * 8 + (*s++ - '0');
- if ('0' <= *s && *s <= '7')
+ if (threeoctdigits && '0' <= *s && *s <= '7')
c = c * 8 + (*s++ - '0');
+ threeoctdigits = false;
break;
case '\\': break;
diff --git a/src/printf.c b/src/printf.c
index 1f5451e..ca05118 100644
--- a/src/printf.c
+++ b/src/printf.c
@@ -236,6 +236,7 @@ print_esc (const char *escstart, bool octal_0)
const char *p = escstart + 1;
int esc_value = 0; /* Value of \nnn escape. */
int esc_length; /* Length of \nnn escape. */
+ int max_octdigits = 3; /* Maximum length of byte octal input. */
if (*p == 'x')
{
@@ -252,9 +253,12 @@ print_esc (const char *escstart, bool octal_0)
{
/* Parse \0ooo (if octal_0 && *p == '0') or \ooo (otherwise).
Allow \ooo if octal_0 && *p != '0'; this is an undocumented
- extension to POSIX that is compatible with Bash 2.05b. */
- for (esc_length = 0, p += octal_0 && *p == '0';
- esc_length < 3 && isodigit (*p);
+ extension to POSIX that is compatible with Bash 2.05b.
+ If the octal character begins with number 4 or higher,
+ only 2 octal digits fit to byte */
+ for (esc_length = 0, p += octal_0 && *p == '0',
+ max_octdigits -= '4' <= *p;
+ esc_length < max_octdigits && isodigit (*p);
++esc_length, ++p)
esc_value = esc_value * 8 + octtobin (*p);
putchar (esc_value);
diff --git a/src/stat.c b/src/stat.c
index b419f19..005aa8e 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -1096,7 +1096,9 @@ print_it (char const *format, char const *filename,
{
int esc_value = octtobin (*b);
int esc_length = 1; /* number of octal digits */
- for (++b; esc_length < 3 && isodigit (*b);
+ int max_octdigits = 3; /* maximum length of byte octal input */
+ for (max_octdigits -= '4' <= *b, ++b;
+ esc_length < max_octdigits && isodigit (*b);
++esc_length, ++b)
{
esc_value = esc_value * 8 + octtobin (*b);
diff --git a/tests/misc/printf b/tests/misc/printf
index b02352b..9c99853 100755
--- a/tests/misc/printf
+++ b/tests/misc/printf
@@ -72,6 +72,8 @@ POSIXLY_CORRECT=1 \
"$prog" '11 %*c\n' 2 x >>out || fail=1
+"$prog" '12 \0610\n' >>out || fail=1
+
"$prog" '%#d\n' 0 >>out 2> /dev/null && fail=1
"$prog" '%0s\n' 0 >>out 2> /dev/null && fail=1
@@ -92,6 +94,7 @@ cat <<\EOF > exp
9 0 x
10 0x
11 x
+12 10
EOF
compare out exp || fail=1
--
1.7.1