Package: zsh Version: 5.0.8-3 Severity: normal Hi,
zsh 5.0.8 segfaults on the while [[ -n "$1" ]]; do line in the attached script; zsh 5.0.7 (and before) was fine. gdb backtrace: #0 __strlen_sse2_bsf () at ../sysdeps/i386/i686/multiarch/strlen-sse2-bsf.S:50 #1 0x080bc801 in taddstr (s=0x1f09d4a3 <error: Cannot access memory at address 0x1f09d4a3>) at ../../Src/text.c:115 #2 0x080bc952 in taddlist (state=state@entry=0xffffcbf0, num=30, num@entry=57) at ../../Src/text.c:141 #3 0x080bdc58 in taddlist (num=57, state=0xffffcbf0) at ../../Src/text.c:637 #4 gettext2 (state=state@entry=0xffffcbf0) at ../../Src/text.c:472 #5 0x080bdfdf in getjobtext (prog=0xf7fd6b98, c=0xf7fd6cb8) at ../../Src/text.c:230 #6 0x0806bdcd in execpline2 (state=state@entry=0xffffce70, pcode=pcode@entry=1411, how=how@entry=18, input=0, output=0, last1=0) at ../../Src/exec.c:1710 #7 0x0806c0f6 in execpline (state=state@entry=0xffffce70, slcode=<optimized out>, how=how@entry=18, last1=0) at ../../Src/exec.c:1500 #8 0x0806d23d in execlist (state=0xffffce70, dont_change_job=0, exiting=0) at ../../Src/exec.c:1276 #9 0x0806d4d4 in execode (p=0xf7fd6b98, dont_change_job=0, exiting=0, context=0x80cca55 "toplevel") at ../../Src/exec.c:1074 #10 0x0807ee41 in loop (toplevel=1, justonce=0) at ../../Src/init.c:207 #11 0x08081dbe in zsh_main (argc=2, argv=0xffffd024) at ../../Src/init.c:1674 #12 0x0805497b in main (argc=2, argv=0xffffd024) at ../../Src/main.c:93 Andras Versions of packages zsh depends on: ii dpkg 1.18.0 ii libc6 2.19-18 ii libcap2 1:2.24-8 ii libtinfo5 5.9+20150516-1 ii zsh-common 5.0.7-6 Versions of packages zsh recommends: ii libncursesw5 5.9+20150516-1 ii libpcre3 2:8.35-3.3 Versions of packages zsh suggests: pn zsh-doc <none> -- no debconf information
#!/bin/zsh # # This script is intended to wrap start-stop-daemon. It will call the # original start-stop-daemon with the supplied arguments unless the daemon # to be started appears to exist as a runit service, in which case it will # map the start-stop-daemon call to an sv(8) call. # # If called by non-root user, fall back to original start-stop-daemon # unconditionally [[ $UID -gt 0 ]] && exec /sbin/start-stop-daemon.real $@ set -A args $@ SVDIR=${SVDIR:-/etc/service} unset mode signal exec timeout startas testmode oknodo quiet verbose command svstat oknodo=0 quiet=0 while [[ -n "$1" ]]; do case "$1" in -S|--start) mode=start ;; -K|--stop) mode=stop ;; -T|--status) mode=status ;; -H|--help|-V|--version) exec /sbin/start-stop-daemon.real $args ;; -x|--exec) shift exec="$1" ;; -s|--signal) shift signal=$1 ;; --signal=*) signal="${1/--signal=/}" ;; -R|--retry) shift timeout="$1" ;; --retry=*) timeout="${1/--retry=/}" ;; -a|--startas) shift startas="$1" ;; -t|--test) testmode=1 ;; -o|--oknodo) oknodo=1 ;; -q|--quiet) quiet=1 exec >/dev/null ;; -v|--verbose) verbose=1 ;; -p|--pidfile|-n|--name|-u|--user|-g|--group|-r|--chroot|-d|--chdir|-N|--nicelevel|-P|--procsched|-I|--iosched|-k|--umask|-m|--make-pidfile) # ignored shift ;; --pidfile=*|-b|--background|--nicelevel=*|--procsched=*|--iosched=*|--umask=*) ;; --) # What follows is args to the daemon. Avoid parsing # those accidentally. break ;; *) # Assume the previous was the last option; the rest # is the name of the daemon plus args, of which we # only care about the daemon. command=$1 break ;; esac shift done # returns success if $1 appears to be the name of a runit service function issvname() { if [[ -d "$SVDIR/$1/supervise/." ]]; then return 0 # 'supervise' could still be a symlink to a directory that doesn't exist yet elif [[ -L $SVDIR/$1/supervise ]] && ! [[ -e $SVDIR/$1/supervise ]]; then return 0 else return 1 fi } # TODO: decide what to do if the runit service we're supposed to manage # doesn't exist in the current svdir but does in other "runlevels" # Try to infer runit service name. If our parent is an initscript, use its # basename foundsvname=0 read -A cmdline </proc/$PPID/cmdline while [[ -n "$cmdline[1]" ]]; do if [[ "${cmdline[1]:h}" = /etc/init.d ]]; then svname=${cmdline[1]:t} break fi shift cmdline done if [[ -z "$svname" ]] && [[ "${$(readlink -f /proc/$PPID/exe):h}" = /etc/init.d ]]; then read svname < /proc/$PPID/comm fi issvname $svname && foundsvname=1 # if not, try other heuristics if [[ $foundsvname = 0 ]]; then svnames=($startas $exec $command) while [[ -n "$svnames[1]" ]]; do if issvname ${svnames[1]:t}; then svname=${svnames[1]:t} foundsvname=1 break else shift svnames fi done fi # if still not found, call real start-stop-daemon if [[ "$foundsvname" = 0 ]]; then exec /sbin/start-stop-daemon.real $args fi # otherwise, do what we've been asked to [[ "$quiet" = "0" ]] && [[ "$verbose" = "1" ]] && echo "start-stop-daemon.runit: will act on $svname service." >&2 function sendsig() { case "$signal" in HUP|1) sv hup $svname ;; INT|2) sv interrupt $svname ;; QUIT|3) sv quit $svname ;; KILL|9) sv d $svname sv kill $svname ;; USR1|10) sv 1 $svname ;; USR2|12) sv 2 $svname ;; ALRM|14) sv alarm $svname ;; TERM|15) sv down $svname ;; CONT|18) sv cont $svname ;; STOP|19) sv pause $svname ;; *) echo "$0: ERROR: don't know how to send $signal signal to $svname." >&2 exit 3 ;; esac } function wait_until_exited() { counter=0 read svstat < $SVDIR/$svname/supervise/stat while ! [[ "$svstat" = down ]]; do ((counter++)) [[ $counter -gt $timeout ]] && return 1 sleep 1 read svstat < $SVDIR/$svname/supervise/stat done return 0 } function do_stop() { if [[ $timeout =~ / ]]; then # handle complex schedule OLDIFS="$IFS" IFS=/ echo $timeout | read -A schedule IFS="$OLDIFS" while [[ -n "$schedule[1]" ]]; do signal=$schedule[1] sendsig shift schedule timeout=$schedule[1] wait_until_exited && exit 0 shift schedule done exit 2 else # simple timeout if [[ -z "$signal" ]]; then if [[ $timeout =~ ^[0-9]+$ ]]; then export SVWAIT=$timeout fi if sv stop $svname; then exit 0 else exit 1 fi else sendsig [[ -n "$timeout" ]] && if wait_until_exited; then exit 0 else exit 1 fi fi fi } if [[ -r $SVDIR/$svname/supervise/stat ]]; then read svstat < $SVDIR/$svname/supervise/stat else # runsv is not yet up svstat=none fi case "$mode" in start) [[ "$svstat" = run ]] && [[ "$oknodo" = "0" ]] && exit 1 # Emulate start-stop-daemon semantics [[ -z "$testmode" ]] && ! [[ "$svstat" = "none" ]] && sv start $svname exit 0 ;; stop) [[ "$svstat" = none ]] && exit 0 [[ "$svstat" = down ]] && [[ "$oknodo" = "1" ]] && exit 1 # Emulate start-stop-daemon semantics [[ -z "$testmode" ]] && do_stop # handles --retry and --signal, therefore separate function ;; status) case "$svstat" in # States are complex; we only handle the most basic cases here and bail on # the rest (e.g. "finish" cannot be correctly reported as "running" or "not # running") run) exit 0 ;; down|none) exit 3 ;; *) exit 4 ;; esac ;; esac exit 0