Bug#943425: klibc: [s390x] SIGSEGV in mksh testcase funsub-2

2021-05-03 Thread Thorsten Glaser
Package: libklibc-dev
Version: 2.0.8-6
Followup-For: Bug #943425
X-Debbugs-Cc: t...@debian.org

I am able to track this down on the porterbox zelenka.

$ apt-get source mksh
$ cd mksh-59c
$ mkdir -p build/klibc
$ cd build/klibc
$ cp /usr/lib/klibc/bin/mksh .
$ chmod +x mksh   # because the x attribute is removed if testsfail
$ gdb --args ./mksh -c 'x=q; e=1; x=${ echo a; typeset e=2; return 3; echo 
x$e;}; echo 3:y$x,$e,$?.'
(gdb) r
[...]
Program received signal SIGSEGV, Segmentation fault.
0x01007c32 in comsub (fn=14, cp=0x0, xp=) at 
../../eval.c:1611
warning: Source file is more recent than executable.
1611lseek(shf_fileno(shf), (off_t)0, SEEK_SET);
(gdb) bt
#0  0x01007c32 in comsub (fn=14, cp=0x0, xp=) at 
../../eval.c:1611
#1  expand (ccp=ccp@entry=0x3fffdfe4768 "\001x\001=\016\\echo a ; \\typeset e=2 
; \\return 3 ; \\echo x$e ",
wp=wp@entry=0x3ffed48, f=f@entry=4128) at ../../eval.c:346
#2  0x0100a366 in evalstr (
cp=0x3fffdfe4768 "\001x\001=\016\\echo a ; \\typeset e=2 ; \\return 3 ; 
\\echo x$e ", f=f@entry=4128)
at ../../eval.c:173
#3  0x0100d082 in comexec (t=0x3fffdfe4888, tp=tp@entry=0x0, 
ap=0x3fffdfe45e8, flags=,
xerrok=) at ../../exec.c:640
#4  0x0100bf0a in execute (t=, flags=, 
xerrok=xerrok@entry=0x0)
at ../../exec.c:162
#5  0x0100c0a2 in execute (t=t@entry=0x3fffdfe4588, 
flags=flags@entry=0, xerrok=xerrok@entry=0x0)
at ../../exec.c:204
#6  0x0101e048 in shell (s=s@entry=0x3fffdfe3b68, level=level@entry=0) 
at ../../main.c:954
#7  0x01000e78 in main (argc=, argv=) at 
../../main.c:742
(gdb) print shf
$1 = (struct shf *) 0x0


The code in question (where it crashes) is thus:

   1584 } else if (fn == FUNSUB) {
   1585 int ofd1;
   1586 struct temp *tf = NULL;
   1587 
   1588 /*
   1589  * create a temporary file, open for reading and 
writing,
   1590  * with an shf open for reading (buffered) but yet 
unused
   1591  */
   1592 maketemp(ATEMP, TT_FUNSUB, );
   1593 if (!tf->shf) {
   1594 errorf(Tf_temp,
   1595 Tcreate, tf->tffn, cstrerror(errno));
   1596 }
   1597 /* extract shf from temporary file, unlink and free it 
*/
   1598 shf = tf->shf;
   1599 unlink(tf->tffn);
   1600 afree(tf, ATEMP);
   1601 /* save stdout and let it point to the tempfile */
   1602 ofd1 = savefd(1);
   1603 ksh_dup2(shf_fileno(shf), 1, false);
   1604 /*
   1605  * run tree, with output thrown into the tempfile,
   1606  * in a new function block
   1607  */
   1608 valsub(t, NULL);
   1609 subst_exstat = exstat & 0xFF;
   1610 /* rewind the tempfile and restore regular stdout */
   1611 lseek(shf_fileno(shf), (off_t)0, SEEK_SET);
   1612 restfd(1, ofd1);

The crash occurs in line 1611 because shf (a local variable) is nil.

The really interesting part, though, is in line 1608, a call to valsub():

   2093 /* helper function due to setjmp/longjmp woes */
   2094 static char *
   2095 valsub(struct op *t, Area *ap)
   2096 {
   2097 char * volatile cp = NULL;
   2098 struct tbl * volatile vp = NULL;
   2099 
   2100 newenv(E_FUNC);
   2101 newblock();
   2102 if (ap)
   2103 vp = local(TREPLY, false);
   2104 if (!kshsetjmp(e->jbuf))
   2105 execute(t, XXCOM | XERROK, NULL);
   2106 if (vp)
   2107 strdupx(cp, str_val(vp), ap);
   2108 quitenv(NULL);
   2109 
   2110 return (cp);
   2111 }

Let's look again at the invocation that caused the crash:

x=q; e=1; x=${ echo a; typeset e=2; return 3; echo x$e;}; echo 
3:y$x,$e,$?.

This one does not crash:

x=q; e=1; x=${ echo a; typeset e=2; echo x$e;}; echo 2:y$x,$e,$?.

The difference here is that 'return' is used in the crash case,
which executes a kshlongjmp(), that is siglongjmp(); kshsetjmp(x)
is sigsetjmp(x,0), which klibc defines as:

 34 #define sigsetjmp(__env, __save) \
 35 ({ \
 36   struct __sigjmp_buf *__e = (__env); \
 37   sigprocmask(0, NULL, &__e->__sigs); \
 38   setjmp(__e->__jmpbuf); \
 39 })

This apparently has two problems:

- the __save argument is ignored, contrary to sigsetjmp docs:

   If, and only if, the savesigs argument provided to sigsetjmp() is  non-
   zero, the process's current signal mask is saved in env and will be re-
   stored if a siglongjmp() is later performed with this env.

- it appears as if the combination of sigsetjmp/siglongjmp does not restore
  all callee-saved variables 

Bug#943425: klibc: [s390x] SIGSEGV in mksh testcase funsub-2

2019-10-25 Thread Thorsten Glaser
Control: block 943425 by 925358

I can’t debug this currently ☹ hitting qemu-user-static bugs.

bye,
//mirabilos
-- 
15:41⎜ Somebody write a testsuite for helloworld :-)



Bug#943425: klibc: [s390x] SIGSEGV in mksh testcase funsub-2

2019-10-24 Thread Thorsten Glaser
Package: libklibc-dev
Version: 2.0.7-1

When building mksh against klibc on s390x, one testcase positively fails:

FAIL ../../check.t:funsub-2
Description:
You can now reliably use local and return in funsubs
(not exit though)
unexpected exit status 11 (signal 11), expected 0
unexpected stdout - got too little output
wanted: 
1:ya x2,2,0.
2:ya x2,1,0.
3:ya,1,3.
got:
1:ya x2,2,0.
2:ya x2,1,0.

I’ll need to track this down later, filing the bug to remember.

bye,
//mirabilos
-- 
tarent solutions GmbH
Rochusstraße 2-4, D-53123 Bonn • http://www.tarent.de/
Tel: +49 228 54881-393 • Fax: +49 228 54881-235
HRB 5168 (AG Bonn) • USt-ID (VAT): DE122264941
Geschäftsführer: Dr. Stefan Barth, Kai Ebenrett, Boris Esser, Alexander Steeg

**

Mit der tarent Academy bieten wir auch Trainings und Schulungen in den
Bereichen Softwareentwicklung, Agiles Arbeiten und Zukunftstechnologien an.

Besuchen Sie uns auf www.tarent.de/academy. Wir freuen uns auf Ihren Kontakt.

**