What's new

Escaping bug in helper.sh

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

Dabombber

Senior Member
The _quote function used in helper.sh escapes the pipe character '|' and ignores the ampersand '&'.
Code:
_quote() {
    echo $1 | sed 's/[]\/$*.^|[]/\\&/g'
}

Examples where this is broken, and an echo bug for good measure:
Code:
#!/bin/sh

source /usr/sbin/helper.sh

TMPFILE="output.txt"

echo -e "a\nb\nc\n" > "$TMPFILE"
pc_replace "|b" "123" "$TMPFILE"
echo 'pc_replace "|b" "123" "$TMPFILE"'
cat "$TMPFILE"

echo -e "a\nb\nc\n" > "$TMPFILE"
pc_replace "b" "&123&" "$TMPFILE"
echo 'pc_replace "b" "&123&" "$TMPFILE"'
cat "$TMPFILE"

echo -e "a\nb\nc\n" > "$TMPFILE"
pc_replace "b" "-n" "$TMPFILE"
echo 'pc_replace "b" "-n" "$TMPFILE"'
cat "$TMPFILE"

rm "$TMPFILE"

Code:
$ sh test.sh
pc_replace "|b" "123" "$TMPFILE"
123a
123
123c
123
pc_replace "b" "&123&" "$TMPFILE"
a
b123b
c

pc_replace "b" "-n" "$TMPFILE"
a

c

This could be fixed by changing the _quote function to
Code:
_quote() {
    printf "%s\n" "$1" | sed 's/[]\/$*.^&[]/\\&/g'
}
 
So there's also a bit of weirdness with the 'a' sed option.
Code:
$ echo -e "abc\ndef\n" | sed "/b/a123"
abc
123
def

$ echo -e "abc\ndef\n" | sed "/b/a\123"
abc
123
def

$ echo -e "abc\ndef\n" | sed "/b/a\\123"
abc
123
def

$ echo -e "abc\ndef\n" | sed "/b/a\\\123"
abc
123
def

$ echo -e "abc\ndef\n" | sed "/b/a\\\\123"
abc
123
def

$ echo -e "abc\ndef\n" | sed "/b/a\\\\\123"
abc
\123
def

It seems the fourth and last examples are "right", so pc_insert should be:
Code:
pc_insert() {
    PATTERN=$(_quote "$1")
    CONTENT=$(_quote "$2")
    sed -i "/$PATTERN/a\\\$CONTENT" $3
}
 
This could be fixed by changing the _quote function to

There's no print command in the firmware.

Are you sure you are running your tests using ash and not bash?
 
There's no print command in the firmware.

Are you sure you are running your tests using ash and not bash?
Code:
# which printf
/usr/bin/printf
# file /usr/bin/printf
/usr/bin/printf: symbolic link to ../../bin/busybox
 
Gotcha. For some reason I was trying to use print instead of printf.
 
Urgh, looks like I missed a 'n' after the backslashes, but then that doesn't work either.
Code:
$ echo -e "abc\ndef\n" | sed "/b/a\\\n123"
abc

123
def

$ echo -e "abc\ndef\n" | sed "/b/a\\
> 123"
abc
123
def
I guess that was a one line syntax for some non GNU sed, but escaped characters seem to be handled differently in busybox. Where the standard is:
Code:
$ echo -e "abc\ndef\n" | sed -e "/b/a\\" -e "123"
abc
123
def

It is possible to use whitespace instead of backslashes, but then you lose any whitespace at the start of the replacement which isn't useful. And the reason backslashes weren't working was the shell doing its own thing before sed
Code:
$ echo -e "abc\ndef\n" | sed -e '/b/a\' -e '\\123'
abc
\123
def

$ echo -e "abc\ndef\n" | sed -e "/b/a\\" -e "\\\\123"
abc
\123
def

Some tests with fixed? functions.
Code:
#!/bin/sh

_quote() {
    printf "%s\n" "$1" | sed 's/[]\/$*.^&[]/\\&/g'
}

pc_replace_a() {
    PATTERN="$(_quote "$1")"
    CONTENT="$(_quote "$2")"
    sed -i "/$PATTERN/a\\
$CONTENT" "$3"
}

pc_replace_b() {
    PATTERN="$(_quote "$1")"
    CONTENT="$(_quote "$2")"
    sed -i -e "/$PATTERN/a\\" -e "$CONTENT" "$3"
}


test() {
    TMPFILE="output.txt"

    echo -e "a\nb\nc\n" > "$TMPFILE"
    pc_replace_a "$1" "$2" "$TMPFILE"
    echo "pc_replace_a($1, $2)"
    cat "$TMPFILE"

    echo -e "a\nb\nc\n" > "$TMPFILE"
    pc_replace_b "$1" "$2" "$TMPFILE"
    echo "pc_replace_b($1, $2)"
    cat "$TMPFILE"

    rm "$TMPFILE"
}

test "b" "&123&"
test "|b" "123"
test "b" "-n"
test "b" "\\"
test "b" "\$"

Code:
$ sh test.sh
pc_replace_a(b, &123&)
a
b
&123&
c

pc_replace_b(b, &123&)
a
b
&123&
c

pc_replace_a(|b, 123)
a
b
c

pc_replace_b(|b, 123)
a
b
c

pc_replace_a(b, -n)
a
b
-n
c

pc_replace_b(b, -n)
a
b
-n
c

pc_replace_a(b, \)
a
b
\
c

pc_replace_b(b, \)
a
b
\
c

pc_replace_a(b, $)
a
b
$
c

pc_replace_b(b, $)
a
b
$
c
 

Similar threads

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top