Skip to content

Commit

Permalink
Fix 'printf -v varname %B' overwriting/truncating data
Browse files Browse the repository at this point in the history
Reproducer:

    typeset  -b foo
    read -N8 foo <<<abcdefghijklmnop
    printf -v got '%s / %B\n' "$foo" foo
    print -rn "$got"

Expected output:

    YWJjZGVmZ2g= / abcdefgh

Actual output:

    YWJjZGVm

Thanks to @JohnoKing for finding the cause, which is a conflicting
use of sh.strbuf2 by the code handling the %B format specifier.

The many formatting specifiers to printf involve code paths into
various parts of the shell, some of which use both sh.strbuf and
sh.strbuf2, so neither of those are safe to use here.

src/cmd/ksh93/bltins/print.c: b_print():
- To avoid the possibility of any conflict, use a dedicated locally
  scoped Sfio string buffer instead of sh.strbuf2.

Resolves: #608
  • Loading branch information
McDutchie committed Mar 29, 2023
1 parent 470222a commit 3dbb088
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 4 deletions.
5 changes: 5 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ This documents significant changes in the dev branch of ksh 93u+m.
For full details, see the git log at: https://github.com/ksh93/ksh
Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library.

2023-03-29:

- Fixed a bug in 'printf -v' (added on 2021-11-18) where using the %B format
specifier would overwrite any data already written to the variable.

2023-03-26:

- Fixed an intermittent crash in 'command -x' experienced on some arm/arm64
Expand Down
7 changes: 4 additions & 3 deletions src/cmd/ksh93/bltins/print.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,10 @@ int b_print(int argc, char *argv[], Shbltin_t *context)
argv++;
if(vname)
{
if(!sh.strbuf2)
sh.strbuf2 = sfstropen();
outfile = sh.strbuf2;
static Sfio_t *vbuf;
if(!vbuf)
vbuf = sfstropen();
outfile = vbuf;
goto printf_v;
}
skip2:
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/ksh93/include/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
#define SH_RELEASE_SVER "1.1.0-alpha" /* semantic version number: https://semver.org */
#define SH_RELEASE_DATE "2023-03-26" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_DATE "2023-03-29" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_CPYR "(c) 2020-2023 Contributors to ksh " SH_RELEASE_FORK

/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */
Expand Down
14 changes: 14 additions & 0 deletions src/cmd/ksh93/tests/builtins.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1655,5 +1655,19 @@ got=$(set +x; { "$SHELL" -c 'read -rd $'\''\200'\'' && echo "$REPLY"';} 2>&1 <<<
"(expected status 0, '$exp';" \
"got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
# ======
# printf -v varname %B overwrites/truncates data
# https://github.com/ksh93/ksh/issues/608
exp='YWJjZGVmZ2g= / abcdefgh'
got=$(
typeset -b foo
read -N8 foo <<<abcdefghijklmnop &&
printf -v got '%s / %B\n' "$foo" foo &&
print -rn "$got"
)
[[ e=$? -eq 0 && $got == "$exp" ]] || err_exit "read -N8 && printf -v %B" \
"(expected status 0, '$exp';" \
"got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
# ======
exit $((Errors<125?Errors:125))

0 comments on commit 3dbb088

Please sign in to comment.