1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-15 04:32:24 +00:00

Fix "$*" doing pattern matching if $IFS is wildcard (BUG_IFSGLOBS)

The bug is that "$*", and related expansions such as "${arr[*]}",
etc., do pattern matching if the first character of $IFS is a
wildcard. For example, the following:

    IFS=*
    set -- F ''
    case BUGFREE in
    BUG"$*")        echo bug ;;
    esac

outputs 'bug'. This bug can be reproduced in every other glob
pattern matching context as well, but not in pathname expansion.

src/cmd/ksh93/sh/macro.c: varsub():
- When joining fields into one for a "$*"-type expansion, check if
  a glob pattern matching operation follows (mp->pattern is set).
  If so, write a preceding backslash to escape the separator.

Resolves: https://github.com/ksh93/ksh/issues/489
Resolves: https://github.com/att/ast/issues/12
This commit is contained in:
Martijn Dekker 2022-07-28 22:04:18 +02:00
parent 441dcc0483
commit 9f6841c37e
4 changed files with 49 additions and 3 deletions

5
NEWS
View file

@ -3,6 +3,11 @@ For full details, see the git log at: https://github.com/ksh93/ksh/tree/1.0
Any uppercase BUG_* names are modernish shell bug IDs.
2022-07-28:
- Fixed BUG_IFSGLOBS ("$*" does pattern matching if the first character of
$IFS is a wildcard).
2022-07-27:
- Fixed a bug introduced on 2022-02-08 where $PPID was incorrect when a script

View file

@ -17,8 +17,8 @@
#include <releaseflags.h>
#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
#define SH_RELEASE_SVER "1.0.0-rc.3" /* semantic version number: https://semver.org */
#define SH_RELEASE_DATE "2022-07-27" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_SVER "1.0.0-rc.4" /* semantic version number: https://semver.org */
#define SH_RELEASE_DATE "2022-07-28" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_CPYR "(c) 2020-2022 Contributors to ksh " SH_RELEASE_FORK
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */

View file

@ -59,7 +59,7 @@ typedef struct _mac_
char quote; /* set within double quoted contexts */
char lit; /* set within single quotes */
char split; /* set when word splitting is possible */
char pattern; /* set when file expansion follows */
char pattern; /* set when glob pattern expansion or matching follows */
char patfound; /* set if pattern character found */
char assign; /* set for assignments */
char arith; /* set for ((...)) */
@ -1985,6 +1985,8 @@ retry2:
* We're joining fields into one; write the output field separator, which may be multi-byte.
* For "$@" it's a space, for "$*" it's the 1st char of IFS (space if unset, none if empty).
*/
if(mp->pattern) /* avoid BUG_IFSGLOBS */
sfputc(sfio_ptr, '\\');
if(mode == '@' || !mp->ifsp) /* if expanding $@ or if IFS is unset... */
sfputc(sfio_ptr, ' ');
else if(mp->ifs) /* else if IFS is non-empty... */

View file

@ -313,5 +313,44 @@ three
[[ $got == "$exp" ]] || err_exit "Line continuation broken within backtick command substitution" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
# ======
# BUG_IFSGLOBS: https://github.com/ksh93/ksh/issues/489
# "$*" does pattern matching if the first char of $IFS is a wildcard
IFS=* # output field separator for "$*"
set -- F '' # "$*" is now "F*"
exp=BUGFREE
got=${exp%"$*"} # the quoted "*" in "F*" should not act as a wildcard
[[ $got == "$exp" ]] || err_exit 'BUG_IGSGLOBS reproducer 1' \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
case BUGFREE in
BUG"$*") err_exit 'BUG_IFSGLOBS reproducer 2' ;;
BUGFREE) ;;
*) err_exit 'BUG_IFSGLOBS reproducer 2 fails badly' ;;
esac
IFS=?
exp=abcd
set a c
got=${exp#"$*"}
[[ $got == "$exp" ]] || err_exit 'BUG_IFSGLOBS reproducer 3' \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
case abc in
"$*") err_exit 'BUG_IFSGLOBS reproducer 4' ;;
esac
[[ abc = "$*" ]] && err_exit 'BUG_IFSGLOBS reproducer 5'
# https://unix.stackexchange.com/questions/411001/using-case-and-arrays-together-in-bash/411006#411006
IFS='|'
arr=(opt1 opt2 opt3)
case opt2 in
@("${arr[*]}"))
err_exit 'BUG_IFSGLOBS reproducer 6' ;;
esac
[[ opt2 == @("${arr[*]}") ]] && err_exit 'BUG_IFSGLOBS reproducer 7'
unset arr
IFS=$' \t\n'
# ======
exit $((Errors<125?Errors:125))