On Wed, 28 Jun 2023 12:42:16 +0200 Fabien Orjollet <of1+bugb...@disroot.org> wrote:
> On 28/06/2023 00:40, Kerin Millar wrote: > > On Tue, 27 Jun 2023 21:52:53 +0200 > > of1 <o...@disroot.org> wrote: > > > >> On 27/06/2023 21:05, Kerin Millar wrote: > >>> It doesn't work at all for >=5.2. The reason for this is interesting and > >>> I may make a separate post about it. > >>> > >>> Prior to 5.2, it can easily be tricked into printing names that do not > >>> exist. > >>> > >>> $ VAR=$'\nNONEXISTENT=' ./declare-P | grep ^NONEXISTENT > >>> NONEXISTENT > >>> > >> Thank you. I was just reading the discussion in Gentoo forum and > >> realizing that I've been to quickly: it doesn't pass the > >> FOO=$'\nBAR BAZ QUUX=' test. But what about this? (I also quickly > >> tested with Bash 5.2.15). > >> > >> > >> FOO=$'\nBAR BAZ QUUX=' > >> VAR=$'\nNONEXISTENT=' > >> > >> declare-P() { > >> local curVar > >> declare -a curVars > >> > >> readarray -t curVars <<<"$1" > >> curVars=( "${curVars[@]%%=*}" ) > >> curVars=( "${curVars[@]##* }" ) > >> for curVar in "${curVars[@]}"; do > >> ### we can use [[ -v "$curVar" ]] at some point! > >> [[ "${curVar//[a-zA-Z0-9_]}" || \ > >> "${curVar:0:1}" == [0-9] || \ > >> ! -v "$curVar" || \ > >> ! "$curVar" =~ $2 ]] || printf '%s\n' "$curVar" > >> done > >> } > >> > >> declare-P "$(declare -p)" > >> echo "##################" > >> declare-P "$(declare -p)" "QU|^NON|VAR"r > >> > > > > This use of test -v is probably sufficient to address that particular > > issue. It is just as well that the test occurs after determining that the > > string is a valid identifier because test -v has the power to facilitate > > arbitrary code execution. > > > > My assertion that your code is broken in 5.2 was incorrect. Rather, the > > problem seems to be that regcomp(3) behaviour differs across platforms, > > where given an empty expression to compile. To address that, you could > > determine whether a second positional parameter was given and is non-empty > > before proceeding to use it. > > Thank you, good to know. I think that ${2:-.} should be correct. > > > > > Curiously, repeated invocation may lead to obvious issues of resource > > consumption. > > > > # This is excruciatingly expensive > > time for i in {1..100}; do > > declare-P "$(declare -p)" > > done > > > > # This is not so expensive (!) > > time for i in {1..100}; do > > declare-P "$(declare -p)" > > : > > done > > I made some testing by adding > echo -n "$(( ++COUNT ))>$(wc -c <<<"$1") " > echo "$1" >"/tmp/declare-P$COUNT" > to the function: > > 1>4651 2>9785 3>15283 4>21504 5>29173 6>39739 7>56095 8>84036 > 9>135145 10>232592 11>422710 12>798174 13>1544326 14>3031854 > 15>6002134 16>11937918 ^C > > ls -rtnh /tmp/declare-P* > -rw-r--r-- 1 1000 1000 4,6K 28 juin 11:09 /tmp/declare-P1 > -rw-r--r-- 1 1000 1000 9,6K 28 juin 11:09 /tmp/declare-P2 > -rw-r--r-- 1 1000 1000 15K 28 juin 11:09 /tmp/declare-P3 > -rw-r--r-- 1 1000 1000 21K 28 juin 11:09 /tmp/declare-P4 > -rw-r--r-- 1 1000 1000 29K 28 juin 11:09 /tmp/declare-P5 > -rw-r--r-- 1 1000 1000 39K 28 juin 11:09 /tmp/declare-P6 > -rw-r--r-- 1 1000 1000 55K 28 juin 11:09 /tmp/declare-P7 > -rw-r--r-- 1 1000 1000 83K 28 juin 11:09 /tmp/declare-P8 > -rw-r--r-- 1 1000 1000 132K 28 juin 11:09 /tmp/declare-P9 > -rw-r--r-- 1 1000 1000 228K 28 juin 11:09 /tmp/declare-P10 > -rw-r--r-- 1 1000 1000 413K 28 juin 11:09 /tmp/declare-P11 > -rw-r--r-- 1 1000 1000 780K 28 juin 11:09 /tmp/declare-P12 > -rw-r--r-- 1 1000 1000 1,5M 28 juin 11:09 /tmp/declare-P13 > -rw-r--r-- 1 1000 1000 2,9M 28 juin 11:09 /tmp/declare-P14 > -rw-r--r-- 1 1000 1000 5,8M 28 juin 11:09 /tmp/declare-P15 > -rw-r--r-- 1 1000 1000 12M 28 juin 11:09 /tmp/declare-P16 > > But by adding set -p to the subshell: Your best option would probably be to run declare -p within the function while avoiding the use of command substitution altogether, so as not to 'pollute' the _ variable. -- Kerin Millar