Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Fix an (apparent) ancient ash bug, that was apparently fixed...



details:   https://anonhg.NetBSD.org/src/rev/dc4ed715d991
branches:  trunk
changeset: 451014:dc4ed715d991
user:      kre <kre%NetBSD.org@localhost>
date:      Sat May 04 02:52:22 2019 +0000

description:
Fix an (apparent) ancient ash bug, that was apparently fixed sometime
in the past, but managed to re-surface...

The expression "${0+\}}" should expand to "}" not "\}"
Almost all other shells handle it that way (incl FreeBSD & dash).

Issue pointed out by Martijn Dekker.

Add ATF sub-tests for the 4 old var expand operators (${var+word}
${var-word} ${var-word} and ${var?word} - including the forms
with the ':' included) and amongst those tests include test cases
for this issue, so if the bug tries to appear again, we can squash
it quicker.   (The newer pattern matching operators are already
well tested as part of testing patterns.)

diffstat:

 bin/sh/parser.c          |    5 +-
 tests/bin/sh/t_expand.sh |  276 ++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 278 insertions(+), 3 deletions(-)

diffs (truncated from 327 to 300 lines):

diff -r 37259640d658 -r dc4ed715d991 bin/sh/parser.c
--- a/bin/sh/parser.c   Sat May 04 02:06:59 2019 +0000
+++ b/bin/sh/parser.c   Sat May 04 02:52:22 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: parser.c,v 1.167 2019/02/27 04:10:56 kre Exp $ */
+/*     $NetBSD: parser.c,v 1.168 2019/05/04 02:52:22 kre Exp $ */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)parser.c   8.7 (Berkeley) 5/16/95";
 #else
-__RCSID("$NetBSD: parser.c,v 1.167 2019/02/27 04:10:56 kre Exp $");
+__RCSID("$NetBSD: parser.c,v 1.168 2019/05/04 02:52:22 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -1974,6 +1974,7 @@
                        CVTRACE(DBG_LEXER, quotef==0, (" QF=1 "));
                        quotef = 1;     /* current token is quoted */
                        if (quoted && c != '\\' && c != '`' &&
+                           (c != '}' || varnest == 0) &&
                            c != '$' && (c != '"' || magicq)) {
                                /*
                                 * retain the \ (which we *know* needs CTLESC)
diff -r 37259640d658 -r dc4ed715d991 tests/bin/sh/t_expand.sh
--- a/tests/bin/sh/t_expand.sh  Sat May 04 02:06:59 2019 +0000
+++ b/tests/bin/sh/t_expand.sh  Sat May 04 02:52:22 2019 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: t_expand.sh,v 1.21 2019/04/10 08:13:11 kre Exp $
+# $NetBSD: t_expand.sh,v 1.22 2019/05/04 02:52:22 kre Exp $
 #
 # Copyright (c) 2007, 2009 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -1332,10 +1332,283 @@
                EOF
 }
 
+check3()
+{
+       check "X=foo; ${1}"             "$2" 0
+       check "X=; ${1}"                "$3" 0
+       check "unset X; ${1}"           "$4" 0
+}
+
+atf_test_case alternative
+alternative_head() {
+       atf_set descr 'Test various possibilities for ${var+xxx}'
+}
+alternative_body() {
+       reset alternative
+
+       # just to verify (validate) that the test method works as expected
+       # (this is currently the very first test performed in this test set)
+       check   'printf %s a b'                         ab      0       #  1
+
+       check3  'set -- ${X+bar}; echo "$#:$1"'         1:bar 1:bar 0:  #  4
+       check3  'set -- ${X+}; echo "$#:$1"'            0: 0: 0:        #  7
+       check3  'set -- ${X+""}; echo "$#:$1"'          1: 1: 0:        # 10
+       check3  'set -- "${X+}"; echo "$#:$1"'          1: 1: 1:        # 13
+       check3  'set -- "${X+bar}"; echo "$#:$1"'       1:bar 1:bar 1:  # 16
+
+       check3  'set -- ${X+a b c}; echo "$#:$1"'       3:a 3:a 0:      # 19
+       check3  'set -- ${X+"a b c"}; echo "$#:$1"'     '1:a b c' '1:a b c' 0:
+       check3  'set -- "${X+a b c}"; echo "$#:$1"'     '1:a b c' '1:a b c' 1:
+       check3  'set -- ${X+a b\ c}; echo "$#:$1"'      2:a 2:a 0:      # 28
+       check3  'set -- ${X+"a b" c}; echo "$#:$1"'     '2:a b' '2:a b' 0:
+
+       check3  'printf %s "" ${X+}'                    ''  ''  ''      # 34
+       check3  'printf %s ""${X+bar}'                  bar bar ''      # 37
+
+       check3  'Y=bar; printf %s ${X+x}${Y+y}'         xy  xy  y       # 40
+       check3  'Y=bar; printf %s ""${X+${Y+z}}'        z   z   ''      # 43
+       check3  'Y=; printf %s ""${X+${Y+z}}'           z   z   ''      # 46
+       check3  'unset Y; printf %s ""${X+${Y+z}}'      ''  ''  ''      # 49
+       check3  'Y=1; printf %s a ${X+"${Y+z}"}'        az  az  a       # 52
+
+       check3  'printf %s ${X+}x}'                     x}  x}  x}      # 55
+       check3  'printf %s ${X+}}'                       }   }   }      # 58
+       check3  'printf %s "" ${X+"}"x}'                }x  }x  ''      # 61
+       check3  'printf %s "" ${X+\}x}'                 }x  }x  ''      # 64
+       check3  'printf %s "${X+\}x}"'                  }x  }x  ''      # 67
+       check3  'printf %s "${X+\}}"'                    }  }   ''      # 70
+
+       check3  'set -- ${X:+bar}; echo "$#:$1"'        1:bar 0: 0:     # 73
+       check3  'set -- ${X:+}; echo "$#:$1"'           0: 0: 0:        # 76
+       check3  'set -- ${X:+""}; echo "$#:$1"'         1: 0: 0:        # 79
+       check3  'set -- "${X:+}"; echo "$#:$1"'         1: 1: 1:        # 80
+       check3  'set -- "${X:+bar}"; echo "$#:$1"'      1:bar 1: 1:     # 83
+
+       check3  'set -- ${X:+a b c}; echo "$#:$1"'      3:a 0: 0:       # 86
+       check3  'set -- ${X:+"a b c"}; echo "$#:$1"'    '1:a b c' 0: 0: # 89
+       check3  'set -- "${X:+a b c}"; echo "$#:$1"'    '1:a b c' 1: 1: # 92
+       check3  'set -- ${X:+a b\ c}; echo "$#:$1"'     2:a 0: 0:       # 95
+       check3  'set -- ${X:+"a b" c}; echo "$#:$1"'    '2:a b' 0: 0:   # 98
+
+       check3  'printf %s "" ${X:+}'                   ''  ''  ''      #101
+       check3  'printf %s ""${X:+bar}'                 bar ''  ''      #104
+
+       check3  'Y=bar; printf %s ${X:+x}${Y:+y}'       xy  y   y       #107
+       check3  'Y=bar; printf %s ""${X:+${Y:+z}}'      z   ''  ''      #110
+       check3  'Y=; printf %s ""${X:+${Y+z}}'          z   ''  ''      #113
+       check3  'Y=; printf %s ""${X:+${Y:+z}}'         ''  ''  ''      #116
+       check3  'unset Y; printf %s ""${X:+${Y:+z}}'    ''  ''  ''      #119
+       check3  'Y=1; printf %s a ${X:+"${Y:+z}"}'      az  a   a       #122
+
+       check3  'printf %s ${X:+}x}'                    x}  x}  x}      #125
+       check3  'printf %s ${X:+}}'                      }   }   }      #128
+       check3  'printf %s "" ${X:+"}"x}'               }x  ''  ''      #131
+       check3  'printf %s "" ${X:+\}x}'                }x  ''  ''      #134
+       check3  'printf %s "${X:+\}x}"'                 }x  ''  ''      #137
+       check3  'printf %s "${X:+\}}"'                   }  ''  ''      #140
+
+       results
+}
+
+atf_test_case default
+default_head() {
+       atf_set descr 'Test various possibilities for ${var-xxx}'
+}
+default_body() {
+       reset default
+
+       check3  'set -- ${X-bar}; echo "$#:$1"'         1:foo 0: 1:bar  #  3
+       check3  'set -- ${X-}; echo "$#:$1"'            1:foo 0: 0:     #  6
+       check3  'set -- ${X-""}; echo "$#:$1"'          1:foo 0: 1:     #  9
+       check3  'set -- "${X-}"; echo "$#:$1"'          1:foo 1: 1:     # 12
+       check3  'set -- "${X-bar}"; echo "$#:$1"'       1:foo 1: 1:bar  # 15
+
+       check3  'set -- ${X-a b c}; echo "$#:$1"'       1:foo 0: 3:a    # 18
+       check3  'set -- ${X-"a b c"}; echo "$#:$1"'     1:foo 0: '1:a b c' #21
+       check3  'set -- "${X-a b c}"; echo "$#:$1"'     1:foo 1: '1:a b c' #24
+       check3  'set -- ${X-a b\ c}; echo "$#:$1"'      1:foo 0: 2:a    # 27
+       check3  'set -- ${X-"a b" c}; echo "$#:$1"'     1:foo 0: '2:a b'   #30
+
+       check3  'printf %s "" ${X-}'                    foo '' ''       # 33
+       check3  'printf %s ""${X-bar}'                  foo '' bar      # 36
+
+       check3  'Y=bar; printf %s ${X-x}${Y-y}'         foobar bar xbar # 39
+       check3  'Y=bar; printf %s ""${X-${Y-z}}'        foo '' bar      # 42
+       check3  'Y=; printf %s ""${X-${Y-z}}'           foo '' ''       # 45
+       check3  'unset Y; printf %s ""${X-${Y-z}}'      foo '' z        # 48
+       check3  'Y=1; printf %s a ${X-"${Y-z}"}'        afoo a a1       # 51
+
+       check3  'printf %s ${X-}x}'                     foox} x} x}     # 54
+       check3  'printf %s ${X-}}'                       foo}  }  }     # 57
+       check3  'printf %s ${X-{}}'                      foo}  } {}     # 60
+       check3  'printf %s "" ${X-"}"x}'                foo ''  }x      # 63
+       check3  'printf %s "" ${X-\}x}'                 foo ''  }x      # 66
+       check3  'printf %s "${X-\}x}"'                  foo ''  }x      # 69
+       check3  'printf %s "${X-\}}"'                   foo ''  }       # 72
+
+       check3  'set -- ${X:-bar}; echo "$#:$1"'        1:foo 1:bar 1:bar  #75
+       check3  'set -- ${X:-}; echo "$#:$1"'           1:foo 0: 0:     # 78
+       check3  'set -- ${X:-""}; echo "$#:$1"'         1:foo 1: 1:     # 81
+       check3  'set -- "${X:-}"; echo "$#:$1"'         1:foo 1: 1:     # 84
+       check3  'set -- "${X:-bar}"; echo "$#:$1"'      1:foo 1:bar 1:bar  #87
+
+       check3  'set -- ${X:-a b c}; echo "$#:$1"'      1:foo 3:a 3:a   # 90
+       check3  'set -- ${X:-"a b c"}; echo "$#:$1"' 1:foo '1:a b c' '1:a b c'
+       check3  'set -- "${X:-a b c}"; echo "$#:$1"' 1:foo '1:a b c' '1:a b c'
+       check3  'set -- ${X:-a b\ c}; echo "$#:$1"'     1:foo 2:a 2:a   # 99
+       check3  'set -- ${X:-"a b" c}; echo "$#:$1"'    1:foo '2:a b' '2:a b'
+
+       check3  'printf %s "" ${X:-}'                   foo ''  ''      #105
+       check3  'printf %s ""${X:-bar}'                 foo bar bar     #108
+
+       check3  'Y=bar; printf %s ${X:-x}${Y:-y}'       foobar xbar xbar #111
+       check3  'Y=bar; printf %s ""${X:-${Y:-z}}'      foo  bar bar    #114
+       check3  'Y=; printf %s ""${X:-${Y-z}}'          foo  ''  ''     #117
+       check3  'Y=; printf %s ""${X:-${Y:-z}}'         foo  z   z      #120
+       check3  'unset Y; printf %s ""${X:-${Y:-z}}'    foo  z   z      #123
+       check3  'Y=1; printf %s a ${X:-"${Y:-z}"}'      afoo a1  a1     #126
+
+       check3  'printf %s ${X:-}x}'                    foox} x}  x}    #129
+       check3  'printf %s ${X:-}}'                      foo}  }   }    #132
+       check3  'printf %s ${X:-{}}'                     foo} {}  {}    #135
+       check3  'printf %s "" ${X:-"}"x}'                foo  }x  }x    #138
+       check3  'printf %s "" ${X:-\}x}'                 foo  }x  }x    #141
+       check3  'printf %s "${X:-\}x}"'                  foo  }x  }x    #144
+       check3  'printf %s "${X:-\}}"'                   foo  }   }     #147
+
+       results
+}
+
+atf_test_case assign
+assign_head() {
+       atf_set descr 'Test various possibilities for ${var=xxx}'
+}
+assign_body() {
+       reset assign
+
+       check3  'set -- ${X=bar}; echo "$#:$1"'         1:foo 0: 1:bar  #  3
+       check3  'set -- ${X=}; echo "$#:$1"'            1:foo 0: 0:     #  6
+       check3  'set -- ${X=""}; echo "$#:$1"'          1:foo 0: 0:     #  9
+       check3  'set -- "${X=}"; echo "$#:$1"'          1:foo 1: 1:     # 12
+       check3  'set -- "${X=bar}"; echo "$#:$1"'       1:foo 1: 1:bar  # 15
+
+       check3  'set -- ${X=a b c}; echo "$#:$1"'       1:foo 0: 3:a    # 18
+       check3  'set -- ${X="a b c"}; echo "$#:$1"'     1:foo 0: 3:a    # 21
+       check3  'set -- "${X=a b c}"; echo "$#:$1"'     1:foo 1: '1:a b c' #24
+       check3  'set -- ${X=a b\ c}; echo "$#:$1"'      1:foo 0: 3:a    # 27
+       check3  'set -- ${X="a b" c}; echo "$#:$1"'     1:foo 0: 3:a    # 30
+
+       check3  'printf %s "" ${X=}'                    foo '' ''       # 33
+       check3  'printf %s ""${X=bar}'                  foo '' bar      # 36
+
+       check3  'Y=bar; printf %s ${X=x}${Y=y}'         foobar bar xbar # 39
+       check3  'Y=bar; printf %s ""${X=${Y=z}}'        foo '' bar      # 42
+       check3  'Y=; printf %s ""${X=${Y=z}}'           foo '' ''       # 45
+       check3  'unset Y; printf %s ""${X=${Y=z}}'      foo '' z        # 48
+       check3  'Y=1; printf %s a ${X="${Y=z}"}'        afoo a a1       # 51
+
+       check3  'printf %s ${X=}x}'                     foox} x} x}     # 54
+       check3  'printf %s ${X=}}'                       foo}  }  }     # 57
+       check3  'printf %s ${X={}}'                      foo}  } {}     # 60
+       check3  'printf %s "" ${X="}"x}'                foo ''  }x      # 63
+       check3  'printf %s "" ${X=\}x}'                 foo ''  }x      # 66
+       check3  'printf %s "${X=\}x}"'                  foo ''  }x      # 69
+       check3  'printf %s "${X=\}}"'                   foo ''  }       # 72
+
+       check3  'set -- ${X=a b c}; echo "$#:$1:$X"'  1:foo:foo 0:: '3:a:a b c'
+       check3  'set -- ${X="a b c"}; echo "$#:$1:$X"' 1:foo:foo 0:: '3:a:a b c'
+       check3  'set -- "${X=a b c}"; echo "$#:$1:$X"' \
+                                               1:foo:foo 1:: '1:a b c:a b c'
+       check3  'set -- ${X=a b\ c}; echo "$#:$1:$X"' 1:foo:foo 0:: '3:a:a b c'
+       check3  'set -- ${X="a b" c}; echo "$#:$1:$X"' 1:foo:foo 0:: '3:a:a b c'
+
+       check3  'printf %s ${X=}x}; printf :%s "${X-U}"' foox}:foo x}: x}: #90
+       check3  'printf %s ${X=}}; printf :%s "${X-U}"'  foo}:foo }:  }:   #93
+       check3  'printf %s ${X={}}; printf :%s "${X-U}"' foo}:foo }: {}:{  #96
+
+       check3  'set -- ${X:=bar}; echo "$#:$1"'        1:foo 1:bar 1:bar # 99  
+       check3  'set -- ${X:=}; echo "$#:$1"'           1:foo 0: 0:     #102
+       check3  'set -- ${X:=""}; echo "$#:$1"'         1:foo 0: 0:     #105
+       check3  'set -- "${X:=}"; echo "$#:$1"'         1:foo 1: 1:     #108
+       check3  'set -- "${X:=bar}"; echo "$#:$1"'      1:foo 1:bar 1:bar #111
+
+       check3  'set -- ${X:=a b c}; echo "$#:$1"'      1:foo 3:a 3:a   #114
+       check3  'set -- ${X:="a b c"}; echo "$#:$1"' 1:foo 3:a 3:a      #117
+       check3  'set -- "${X:=a b c}"; echo "$#:$1"' 1:foo '1:a b c' '1:a b c'
+       check3  'set -- ${X:=a b\ c}; echo "$#:$1"'     1:foo 3:a 3:a   #123
+       check3  'set -- ${X:="a b" c}; echo "$#:$1"'    1:foo 3:a 3:a   #126
+
+       check3  'printf %s "" ${X:=}'                   foo ''  ''      #129
+       check3  'printf %s ""${X:=bar}'                 foo bar bar     #132
+
+       check3  'Y=bar; printf %s ${X:=x}${Y:=y}'       foobar xbar xbar #135
+       check3  'Y=bar; printf %s ""${X:=${Y:=z}}'      foo  bar bar    #138
+       check3  'Y=; printf %s ""${X:=${Y=z}}'          foo  ''  ''     #141
+       check3  'Y=; printf %s ""${X:=${Y:=z}}'         foo  z   z      #144
+       check3  'unset Y; printf %s ""${X:=${Y:=z}}'    foo  z   z      #147
+       check3  'Y=1; printf %s a ${X:="${Y:=z}"}'      afoo a1  a1     #150
+
+       check3  'printf %s ${X:=}x}'                    foox} x}  x}    #153
+       check3  'printf %s ${X:=}}'                      foo}  }   }    #156
+       check3  'printf %s ${X:={}}'                     foo} {}  {}    #159
+       check3  'printf %s "" ${X:="}"x}'                foo  }x  }x    #162
+       check3  'printf %s "" ${X:=\}x}'                 foo  }x  }x    #165
+       check3  'printf %s "${X:=\}x}"'                  foo  }x  }x    #168
+       check3  'printf %s "${X:=\}}"'                   foo  }   }     #171
+
+       check3  'set -- ${X:=a b c}; echo "$#:$1:$X"' \
+                               1:foo:foo '3:a:a b c' '3:a:a b c'       #174
+       check3  'set -- ${X:="a b c"}; echo "$#:$1:$X"' \
+                               1:foo:foo '3:a:a b c' '3:a:a b c'       #177
+       check3  'set -- "${X:=a b c}"; echo "$#:$1:$X"' \
+                               1:foo:foo '1:a b c:a b c' '1:a b c:a b c' #180
+       check3  'set -- ${X:=a b\ c}; echo "$#:$1:$X"' \
+                               1:foo:foo '3:a:a b c' '3:a:a b c'       #183
+       check3  'set -- ${X:="a b" c}; echo "$#:$1:$X"' \
+                               1:foo:foo '3:a:a b c' '3:a:a b c'       #186
+
+       check3  'printf %s ${X:=}x}; printf :%s "${X-U}"' foox}:foo x}: x}:
+       check3  'printf %s ${X:=}}; printf :%s "${X-U}"'  foo}:foo }:  }:
+       check3  'printf %s ${X:=\}}; printf :%s "${X-U}"' foo:foo }:}  }:}
+       check3  'printf %s ${X:={}}; printf :%s "${X-U}"' foo}:foo {}:{ {}:{
+                                                                       #198
+
+       results
+}
+
+atf_test_case error
+error_head() {
+       atf_set descr 'Test various possibilities for ${var?xxx}'
+}
+error_body() {
+       reset error
+
+       check 'X=foo; printf %s ${X?X is not set}'      foo     0       #1
+       check 'X=; printf %s ${X?X is not set}'         ''      0       #2
+       check 'unset X; printf %s ${X?X is not set}'    ''      2       #3
+
+       check 'X=foo; printf %s ${X?}'                  foo     0       #4
+       check 'X=; printf %s ${X?}'                     ''      0       #5
+       check 'unset X; printf %s ${X?}'                ''      2       #6
+
+       check 'X=foo; printf %s ${X:?X is not set}'     foo     0       #7
+       check 'X=; printf %s ${X:?X is not set}'        ''      2       #8



Home | Main Index | Thread Index | Old Index