Hello tech@,

When toying with SHY I found (thanks to sthen@) that printf(1) supports
\x syntax, but if I use isxdigit(3) characters as suffix I found the
behaviour somewhat surprising: all extra characters were consumed.

Looking at our closest neighbours:
- FreeBSD: doesn't support \x
- NetBSD: Limits to 2 characters, no characters => NUL-btye
- gprintf (coreutils): Limits to 2 characters, no characters => error

We currently have NetBSD's behaviour when it comes to to no characters,
so no need to change there imho, but the 2 character limit seems like
a good place to stop, especially since there's no way to break out of
this hungry hungry hippo.

limiter inspiration taken from octal notation.

While here, also document \x notation.

OK? if so, pre or post release?

martijn@

Index: printf.1
===================================================================
RCS file: /cvs/src/usr.bin/printf/printf.1,v
retrieving revision 1.34
diff -u -p -r1.34 printf.1
--- printf.1    16 Jan 2020 16:46:47 -0000      1.34
+++ printf.1    16 Apr 2021 01:28:20 -0000
@@ -103,6 +103,11 @@ Write a backslash character.
 Write an 8-bit character whose ASCII value is
 the 1-, 2-, or 3-digit octal number
 .Ar num .
+.It Cm \ex Ns Ar num
+Write an 8-bit character whose ASCII value is
+the 1- or 2-digit hexadecimal
+number
+.Ar num .
 .El
 .Pp
 Each format specification is introduced by the percent
@@ -383,7 +388,8 @@ and always operates as if
 were set.
 .Pp
 The escape sequences
-.Cm \ee
+.Cm \ee ,
+.Cm \ex
 and
 .Cm \e' ,
 as well as omitting the leading digit
Index: printf.c
===================================================================
RCS file: /cvs/src/usr.bin/printf/printf.c,v
retrieving revision 1.26
diff -u -p -r1.26 printf.c
--- printf.c    18 Nov 2016 15:53:16 -0000      1.26
+++ printf.c    16 Apr 2021 01:28:20 -0000
@@ -275,7 +275,7 @@ static int
 print_escape(const char *str)
 {
        const char *start = str;
-       int value;
+       int value = 0;
        int c;
 
        str++;
@@ -283,7 +283,7 @@ print_escape(const char *str)
        switch (*str) {
        case '0': case '1': case '2': case '3':
        case '4': case '5': case '6': case '7':
-               for (c = 3, value = 0; c-- && isodigit(*str); str++) {
+               for (c = 3; c-- && isodigit(*str); str++) {
                        value <<= 3;
                        value += octtobin(*str);
                }
@@ -293,13 +293,9 @@ print_escape(const char *str)
 
        case 'x':
                str++;
-               for (value = 0; isxdigit((unsigned char)*str); str++) {
+               for (c = 2; c-- && isxdigit((unsigned char)*str); str++) {
                        value <<= 4;
                        value += hextobin(*str);
-               }
-               if (value > UCHAR_MAX) {
-                       warnx ("escape sequence out of range for character");
-                       rval = 1;
                }
                putchar (value);
                return str - start - 1;


Reply via email to