Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 527848 - app-shells/dash: printf %b mishandles \02dd escape sequences
Summary: app-shells/dash: printf %b mishandles \02dd escape sequences
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: Gentoo's Team for Core System packages
Depends on:
Reported: 2014-11-01 16:33 UTC by John Keeping
Modified: 2016-12-08 05:59 UTC (History)
0 users

See Also:
Package list:
Runtime testing required: ---


Note You need to log in before you can comment on or make changes to this bug.
Description John Keeping 2014-11-01 16:33:55 UTC
The POSIX standard for printf(1) says:

> 7. An  additional conversion specifier character, b, shall be supported as
> follows. The argument shall be taken to be a string that may contain
> <backslash>-escape sequences. The following <backslash>-escape sequences
> shall be supported: 
>    --  "\0ddd", where ddd is a zero, one, two, or three-digit octal number
>        that shall be converted to a byte  with the numeric value specified
>        by the octal number

This is broken due to the Gentoo patch dash-

Expected result:
    $ printf '%b' '\0204' | hexdump -C
    00000000  84                                                |.|

Actual result:
    $ printf '%b' '\0204' | hexdump -C
    00000000  10 34                                             |.4|

The correct patch to fix bug #337329 appears to be:

diff --git a/src/bltin/printf.c b/src/bltin/printf.c
index 5f9e81c..19b882f 100644
--- a/src/bltin/printf.c
+++ b/src/bltin/printf.c
@@ -287,8 +287,7 @@ conv_escape(char *str, int *conv_ch)
                value = '\\';
                goto out;
-       case '0': case '1': case '2': case '3':
-       case '4': case '5': case '6': case '7':
+       case '0':
                ch = 3;
                value = 0;
                do {

Reproducible: Always
Comment 1 John Keeping 2014-11-01 17:06:01 UTC
Having investigated a bit more, my previously proposed patch is wrong because it breaks handling of octal escapes in the printf(1) format string, which do not have a leading zero.

The patch attached to bug #337329 [1] is closer but a bit too aggressive.


The correct patch is:

diff --git a/src/bltin/printf.c b/src/bltin/printf.c
index 5f9e81c..b17e6dc 100644
--- a/src/bltin/printf.c
+++ b/src/bltin/printf.c
@@ -260,6 +260,11 @@ conv_escape_str(char *str)
                                ch += k;
                        } while (--i);
+               } else if ('1' <= ch && ch < '8') {
+                       /* Stop conv_escape handling these as octal. */
+                       ch = '\\';
+                       str--;
+                       continue;
                /* Finally test for sequences valid in the format string */
Comment 2 SpanKY gentoo-dev 2014-11-01 18:40:15 UTC
(In reply to John Keeping from comment #1)

thanks for the heads up, but unfortunately, not even this patch is sufficient.  i think we need to plumb down the logic of whether this is `echo` or `printf`.
Comment 3 John Keeping 2014-11-01 18:46:04 UTC
Upstream is not going to take any patch on this [1], and I agree that dash conforms to POSIX in this area.

Since dash has been the default on Debian for a while now, I wonder if Gentoo could just drop the patch and allow the upstream behaviour.  I would hope that most problems will already have been caught and fixed.

Comment 4 SpanKY gentoo-dev 2014-11-01 18:48:48 UTC
(In reply to SpanKY from comment #2)

actually, your patch is sufficient if we want echo to conform to XSI.  bash doesn't do this by default while dash does.  bash requires `shopt -s xpg_echo` to be enabled.

for sake of simplicity/size/speed, i think we should neuter dash's echo so it simply writes back exactly what it is given and does not respect any option at all.
Comment 5 SpanKY gentoo-dev 2014-11-01 18:52:05 UTC
(In reply to John Keeping from comment #3)

i had a similar discussion a while ago:

while POSIX gives `echo` wide berth to generate whatever junk it wants when it sees a backslash, that doesn't mean the shell should include (arguably) garbage behavior.

i'm just going to neuter the echo and see what happens.
Comment 6 SpanKY gentoo-dev 2014-11-01 19:18:21 UTC
should be all set now in the tree; thanks for the report!

Commit message: Replace the octal patch with a dumb echo patch
Comment 7 Alexander Tsoy 2014-11-02 15:54:29 UTC
(In reply to SpanKY from comment #5)

> i'm just going to neuter the echo and see what happens.

JFYI: this change breaks icu, see bug 528022. Of course this is not a fault of dash.
Comment 8 Joshua Kinard gentoo-dev 2014-11-27 14:05:32 UTC
The dumb echo patch breaks sys-apps/pm-utils, too, it looks, if /bin/sh -> dash:

From setting PM_DEBUG=true and then running 'pm-suspend':

Thu Nov 27 08:53:13 EST 2014: performing suspend
+ sync
+ do_suspend
+ echo -n mem
sh: echo: I/O error
+ r=128
+ date
+ log Thu Nov 27 08:53:14 EST 2014: Awake.

That 'echo -n mem' fails because I'll bet the '-n' is echoed in the output and fails whatever it was trying to do.

I'll create a bug for this later on.  Just documenting it here in case anyone else comes searching...
Comment 9 Mikael Magnusson 2015-01-21 22:15:56 UTC
This patch also breaks, among other things, ncurses' configure script:
First run is with patch, second is without.
Comment 10 SpanKY gentoo-dev 2015-04-03 07:07:38 UTC
(In reply to Joshua Kinard from comment #8)
(In reply to Mikael Magnusson from comment #9)

packages that rely on `echo -n` are broken.  please file bugs for them, and perhaps contact the respective upstreams as well.  it's pretty trivial to resolve in a portable way:
-echo -n foo
+printf "%s\n" foo