unescape() is used by several tools, in particular printf(1) and tr(1), which should stop the octal escape at a maximum of 3 digits:
printf(1) > In addition to the escape sequences shown in XBD 5. File Format > Notation ('\\', '\a', '\b', '\f', '\n', '\r', '\t', '\v'), "\ddd", > where ddd is a one, two, or three-digit octal number, shall be > written as a byte with the numeric value specified by the octal > number. tr(1) > An octal sequence shall consist of a <backslash> followed by the > longest sequence of one, two, or three-octal-digit characters. Previously, the maximum was set to 4 (possibly a typo?), which meant that printf '\0123' printed `S` instead of `<newline>3`. To check that this doesn't break any other tools using unescape: - cut: used for -d parameter, escapes are non-standard - join: used for -t parameter, escapes are non-standard - nl: used for -s parameter, escapes are non-standard - paste: used for -d parameter, POSIX specifies \n, \t, \\, and \0, \0 followed by a digit is unspecified - sort: used for -t parameter, escapes are non-standard --- libutil/unescape.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libutil/unescape.c b/libutil/unescape.c index d8ed2a2..b8f75ca 100644 --- a/libutil/unescape.c +++ b/libutil/unescape.c @@ -37,7 +37,7 @@ unescape(char *s) } else if (escapes[(unsigned char)*r]) { *w++ = escapes[(unsigned char)*r++]; } else if (is_odigit(*r)) { - for (q = 0, m = 4; m && is_odigit(*r); m--, r++) + for (q = 0, m = 3; m && is_odigit(*r); m--, r++) q = q * 8 + (*r - '0'); *w++ = MIN(q, 255); } else if (*r == 'x' && isxdigit(r[1])) { -- 2.45.2