* Segmentation fault immediately after 'unset PATH' @ 2019-07-10 20:55 Shane Squires 2019-07-10 21:52 ` Mikael Magnusson 0 siblings, 1 reply; 5+ messages in thread From: Shane Squires @ 2019-07-10 20:55 UTC (permalink / raw) To: zsh-workers [-- Attachment #1: Type: text/plain, Size: 1592 bytes --] I'm running the most recent version of zsh available on my system (I am not an admin), which is: ------------------ % zsh --version zsh 5.3.1 (x86_64-unknown-linux-gnu) ------------------ The following script, when executed, produces a segmentation fault for me. This is the most minimal example I can construct. ------------------ File run.zsh: ------------------ #! /usr/bin/zsh run() { typeset -U path=( $path ) unset PATH } run ------------------ ------------------ % ./run.zsh [1] 13415 segmentation fault ./run.zsh ------------------ As far as I can tell, the problem has to involve all three elements here: (1) the type of 'path' has to be modified, (2) 'PATH' has to be unset, and (3) this has to happen inside a function. I can imagine that what's going on here is that, for some reason, changing the type of 'path' from inside a function causes it and 'PATH' to fall "out of sync" somehow, and this creates problems when 'PATH' is being unset. But this is extremely vague and speculative, so I won't waste any more time by discussing it. Before anyone lectures me on this, I realize that unsetting 'PATH' is not advisable in general! It is unfortunately unavoidable in my particular case. 'PATH' needs to be unset and then immediately set to a new value, and (because this is being handled in an automated way for many environment variables) I cannot just immediately re-assign its value. I will find another workaround on my end, but I'm reporting this here mainly because it seems to be a genuine bug in zsh. Thanks in advance for looking into this-- Shane ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Segmentation fault immediately after 'unset PATH' 2019-07-10 20:55 Segmentation fault immediately after 'unset PATH' Shane Squires @ 2019-07-10 21:52 ` Mikael Magnusson 2019-07-11 8:44 ` Peter Stephenson 0 siblings, 1 reply; 5+ messages in thread From: Mikael Magnusson @ 2019-07-10 21:52 UTC (permalink / raw) To: Shane Squires; +Cc: zsh-workers On 7/10/19, Shane Squires <shane2squires@gmail.com> wrote: > I'm running the most recent version of zsh available on my system (I am not > an admin), which is: > > ------------------ > % zsh --version > zsh 5.3.1 (x86_64-unknown-linux-gnu) > ------------------ > > The following script, when executed, produces a segmentation fault for me. > This is the most minimal example I can construct. > > ------------------ > File run.zsh: > ------------------ > #! /usr/bin/zsh > > run() { > typeset -U path=( $path ) > unset PATH > } > > run > ------------------ > > ------------------ > % ./run.zsh > [1] 13415 segmentation fault ./run.zsh > ------------------ > > As far as I can tell, the problem has to involve all three elements here: > (1) the type of 'path' has to be modified, (2) 'PATH' has to be unset, and > (3) this has to happen inside a function. > > I can imagine that what's going on here is that, for some reason, changing > the type of 'path' from inside a function causes it and 'PATH' to fall "out > of sync" somehow, and this creates problems when 'PATH' is being unset. > But this is extremely vague and speculative, so I won't waste any more time > by discussing it. > > Before anyone lectures me on this, I realize that unsetting 'PATH' is not > advisable in general! It is unfortunately unavoidable in my particular > case. 'PATH' needs to be unset and then immediately set to a new value, > and (because this is being handled in an automated way for many environment > variables) I cannot just immediately re-assign its value. I will find > another workaround on my end, but I'm reporting this here mainly because it > seems to be a genuine bug in zsh. > > Thanks in advance for looking into this-- > Shane This is the backtrace i get with debugging symbols, Program received signal SIGSEGV, Segmentation fault. 0x00000000004832b8 in unsetparam_pm (pm=0x716a70, altflag=1, exp=1) at params.c:3614 3614 pm->gsu.s->unsetfn(pm, exp); (gdb) bt #0 0x00000000004832b8 in unsetparam_pm (pm=0x716a70, altflag=1, exp=1) at params.c:3614 #1 0x000000000048338b in unsetparam_pm (pm=0x6e75b0 <special_params+5360>, altflag=0, exp=1) at params.c:3634 #2 0x000000000041e22a in bin_unset (name=0x7ffff7fe7760 "unset", argv=0x7ffff7fe77a8, ops=0x7fffffffc2c0, func=31) at builtin.c:3739 #3 0x000000000041093c in execbuiltin (args=0x7ffff7fe7770, assigns=0x0, bn=0x6e37a0 <builtins+4416>) at builtin.c:507 #4 0x00000000004394d0 in execcmd_exec (state=0x7fffffffcbe0, eparams=0x7fffffffc800, input=0, output=0, how=18, last1=2, close_if_forked=-1) at exec.c:4096 #5 0x0000000000432dfe in execpline2 (state=0x7fffffffcbe0, pcode=67, how=18, input=0, output=0, last1=0) at exec.c:1929 #6 0x0000000000431a44 in execpline (state=0x7fffffffcbe0, slcode=4098, how=18, last1=0) at exec.c:1660 #7 0x0000000000430d2c in execlist (state=0x7fffffffcbe0, dont_change_job=1, exiting=0) at exec.c:1415 #8 0x0000000000430399 in execode (p=0x7ffff7ff2700, dont_change_job=1, exiting=0, context=0x4c5eca "shfunc") at exec.c:1194 #9 0x000000000043e357 in runshfunc (prog=0x7ffff7ff2700, wrap=0x0, name=0x7ffff7fe7170 "(anon)") at exec.c:5979 #10 0x000000000043db7d in doshfunc (shfunc=0x715450, doshargs=0x7ffff7ff2738, noreturnval=0) at exec.c:5829 #11 0x000000000043ca64 in execshfunc (shf=0x715450, args=0x7ffff7ff2738) at exec.c:5398 #12 0x000000000043c4b9 in execfuncdef (state=0x7fffffffd420, redir_prog=0x0) at exec.c:5264 #13 0x00000000004306a0 in execsimple (state=0x7fffffffd420) at exec.c:1248 #14 0x0000000000430b57 in execlist (state=0x7fffffffd420, dont_change_job=0, exiting=1) at exec.c:1378 #15 0x0000000000430399 in execode (p=0x7ffff7ff2638, dont_change_job=0, exiting=1, context=0x4c8792 "cmdarg") at exec.c:1194 #16 0x0000000000430261 in execstring ( s=0x7fffffffda8b "() { typeset -U path=( $path ); unset PATH }", dont_change_job=0, exiting=1, context=0x4c8792 "cmdarg") at exec.c:1160 ---Type <return> to continue, or q <return> to quit---q Quit (gdb) p pm $1 = (Param) 0x716a70 (gdb) p pm->gsu.s $2 = (GsuScalar) 0x0 (gdb) fr 1 #1 0x000000000048338b in unsetparam_pm (pm=0x6e75b0 <special_params+5360>, altflag=0, exp=1) at params.c:3634 3634 unsetparam_pm(altpm, 1, exp); (gdb) list 3629 if (oldpm && !altpm->level) { 3630 oldpm->old = NULL; 3631 /* fudge things so removenode isn't called */ 3632 altpm->level = 1; 3633 } 3634 unsetparam_pm(altpm, 1, exp); 3635 } 3636 3637 zsfree(altremove); 3638 } (gdb) p altpm $3 = (Param) 0x716a70 Adding a check for that particular NULL causes the following backtrace instead: Program received signal SIGSEGV, Segmentation fault. 0x00000000004868a5 in scanendscope (hn=0x6e7ce0 <special_params+7200>, flags=0) at params.c:5621 5621 pm->old = tpm->old; (gdb) p pm $1 = (Param) 0x6e7ce0 <special_params+7200> (gdb) p pm->old $2 = (Param) 0x0 (gdb) p pm $3 = (Param) 0x6e7ce0 <special_params+7200> (gdb) p tpm $4 = (Param) 0x0 (gdb) bt #0 0x00000000004868a5 in scanendscope (hn=0x6e7ce0 <special_params+7200>, flags=0) at params.c:5621 #1 0x000000000044ab7f in scanmatchtable (ht=0x7069c0, pprog=0x0, sorted=0, flags1=0, flags2=0, scanfunc=0x4867af <scanendscope>, scanflags=0) at hashtable.c:428 #2 0x000000000044ac09 in scanhashtable (ht=0x7069c0, sorted=0, flags1=0, flags2=0, scanfunc=0x4867af <scanendscope>, scanflags=0) at hashtable.c:444 #3 0x0000000000486667 in endparamscope () at params.c:5587 #4 0x000000000043e38c in runshfunc (prog=0x7ffff7ff2700, wrap=0x0, name=0x7ffff7fe7170 "(anon)") at exec.c:5984 #5 0x000000000043db7d in doshfunc (shfunc=0x715450, doshargs=0x7ffff7ff2738, noreturnval=0) at exec.c:5829 #6 0x000000000043ca64 in execshfunc (shf=0x715450, args=0x7ffff7ff2738) at exec.c:5398 #7 0x000000000043c4b9 in execfuncdef (state=0x7fffffffd420, redir_prog=0x0) at exec.c:5264 #8 0x00000000004306a0 in execsimple (state=0x7fffffffd420) at exec.c:1248 #9 0x0000000000430b57 in execlist (state=0x7fffffffd420, dont_change_job=0, exiting=1) at exec.c:1378 #10 0x0000000000430399 in execode (p=0x7ffff7ff2638, dont_change_job=0, exiting=1, context=0x4c8792 "cmdarg") at exec.c:1194 #11 0x0000000000430261 in execstring ( s=0x7fffffffda8b "() { typeset -U path=( $path ); unset PATH }", dont_change_job=0, exiting=1, context=0x4c8792 "cmdarg") at exec.c:1160 #12 0x0000000000458f20 in init_misc ( cmd=0x7fffffffda8b "() { typeset -U path=( $path ); unset PATH }", zsh_name=0x7fffffffda84 "zsh") at init.c:1374 #13 0x000000000045a309 in zsh_main (argc=3, argv=0x7fffffffd608) at init.c:1758 #14 0x000000000040fa46 in main (argc=3, argv=0x7fffffffd608) at ./main.c:93 -- Mikael Magnusson ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Segmentation fault immediately after 'unset PATH' 2019-07-10 21:52 ` Mikael Magnusson @ 2019-07-11 8:44 ` Peter Stephenson 2019-07-11 10:48 ` Peter Stephenson 0 siblings, 1 reply; 5+ messages in thread From: Peter Stephenson @ 2019-07-11 8:44 UTC (permalink / raw) To: zsh-workers On Wed, 2019-07-10 at 23:52 +0200, Mikael Magnusson wrote: > On 7/10/19, Shane Squires <shane2squires@gmail.com> wrote: > > The following script, when executed, produces a segmentation fault for me. > > This is the most minimal example I can construct. > > > > ------------------ > > File run.zsh: > > ------------------ > > #! /usr/bin/zsh > > > > run() { > > typeset -U path=( $path ) > > unset PATH > > } > > > > run > > This is the backtrace i get with debugging symbols, > Program received signal SIGSEGV, Segmentation fault. > 0x00000000004832b8 in unsetparam_pm (pm=0x716a70, altflag=1, exp=1) at > params.c:3614 > 3614 pm->gsu.s->unsetfn(pm, exp); > (gdb) bt > #0 0x00000000004832b8 in unsetparam_pm (pm=0x716a70, altflag=1, > exp=1) at params.c:3614 The gsu element (get/set/unset handlers) of that parameter element, which is the special one for path (N.B. not PATH which is linked), are null. That shouldn't ever happen, so it's already broken. Presumably this is somehow associated with the typeset. The parameter structure looks otherwise reasonable, except the PM_UNIQUE flag has gone by this point. I'm seeing PM_RESTRICTED|PM_DONTIMPORT|PM_SPECIAL|PM_TIED|PM_ARRAY all of which make sense. pws ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Segmentation fault immediately after 'unset PATH' 2019-07-11 8:44 ` Peter Stephenson @ 2019-07-11 10:48 ` Peter Stephenson 2019-07-11 10:58 ` Peter Stephenson 0 siblings, 1 reply; 5+ messages in thread From: Peter Stephenson @ 2019-07-11 10:48 UTC (permalink / raw) To: zsh-workers hu, 2019-07-11 at 09:44 +0100, Peter Stephenson wrote: Wed, 2019-07-10 at 23:52 +0200, Mikael Magnusson wrote: On 7/10/19, Shane Squires <shane2squires@gmail.com> wrote: > > The following script, when executed, produces a segmentation fault for me. > This is the most minimal example I can construct. > > ------------------ > File run.zsh: > ------------------ > #! /usr/bin/zsh > > run() { > typeset -U path=( $path ) > unset PATH > } > > run I think the issue is that to be able to save and restore path, which is special, we stick the old values on the end but keep the special parameter structure in front. The value to be saved for the environment is associated with path, so when we try to unset that we throw away the real special parameter, which we should simply mark as unset. It's straightforward to fix the actual crash. The other business here is that the "unset" unsets the global PATH, as there isn't a local parameter, just the local path which refers to the same data but has a separate parameter interface. So PATH remains unset until you explicitly set it again. It's deliberate that you can unset one of the variables and still leave the other visible. Given that, forcing them both to be local at the same time is a bit murky, and I can more or less guarantee a bug-prone mess if we try. pws diff --git a/Src/params.c b/Src/params.c index 1859c7c12..95181f533 100644 --- a/Src/params.c +++ b/Src/params.c @@ -3617,10 +3617,18 @@ unsetparam_pm(Param pm, int altflag, int exp) altpm = (Param) paramtab->getnode(paramtab, altremove); /* tied parameters are at the same local level as each other */ oldpm = NULL; - while (altpm && altpm->level > pm->level) { - /* param under alternate name hidden by a local */ - oldpm = altpm; - altpm = altpm->old; + /* + * Look for param under alternate name hidden by a local. + * If this parameter is special, however, the visible + * parameter is the special and the hidden one is keeping + * and old value --- we just mark the visible one as unset. + */ + if (altpm && !(altpm->node.flags & PM_SPECIAL)) + { + while (altpm && altpm->level > pm->level) { + oldpm = altpm; + altpm = altpm->old; + } } if (altpm) { if (oldpm && !altpm->level) { ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Segmentation fault immediately after 'unset PATH' 2019-07-11 10:48 ` Peter Stephenson @ 2019-07-11 10:58 ` Peter Stephenson 0 siblings, 0 replies; 5+ messages in thread From: Peter Stephenson @ 2019-07-11 10:58 UTC (permalink / raw) To: zsh-workers On Thu, 2019-07-11 at 11:48 +0100, Peter Stephenson wrote: > diff --git a/Src/params.c b/Src/params.c > index 1859c7c12..95181f533 100644 > --- a/Src/params.c > +++ b/Src/params.c > @@ -3617,10 +3617,18 @@ unsetparam_pm(Param pm, int altflag, int exp) > altpm = (Param) paramtab->getnode(paramtab, altremove); > /* tied parameters are at the same local level as each other */ > oldpm = NULL; > - while (altpm && altpm->level > pm->level) { > - /* param under alternate name hidden by a local */ > - oldpm = altpm; > - altpm = altpm->old; > + /* > + * Look for param under alternate name hidden by a local. > + * If this parameter is special, however, the visible > + * parameter is the special and the hidden one is keeping > + * and old value --- we just mark the visible one as unset. > + */ > + if (altpm && !(altpm->node.flags & PM_SPECIAL)) > + { > + while (altpm && altpm->level > pm->level) { > + oldpm = altpm; > + altpm = altpm->old; > + } > } > if (altpm) { > if (oldpm && !altpm->level) { Hmm... can that loop I've "if"ed out ever be right? It's meaning we're unsetting the saved version of a parameter, not the visible one. That looks pretty fishy at any time. pws ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-07-11 10:59 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-07-10 20:55 Segmentation fault immediately after 'unset PATH' Shane Squires 2019-07-10 21:52 ` Mikael Magnusson 2019-07-11 8:44 ` Peter Stephenson 2019-07-11 10:48 ` Peter Stephenson 2019-07-11 10:58 ` Peter Stephenson
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/zsh/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).