Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock X-Debbugs-Cc: m...@packages.debian.org, t...@mirbsd.de Control: affects -1 + src:mksh
Please unblock package mksh [ Reason ] Some bugfixes regarding formatting, shift/rotate arithmetics, and a few cases where the parser was not properly reentrant leading to use-after-free/double-free for recursive parsing. Also add some tests for the printf builtin to the testsuite. [ Impact ] Probably low. I haven’t hit any of these in practice, but fuzzing would find them. [ Tests ] There is a new test for the printf builtin, but the other changes have only been manually tested to not crash (also with Valgrind and ASan/UBSan) after the change. [ Risks ] I’ve only cherry-picked the changes I’m fully confident of and that do not touch larger areas of code. They have been in use for several weeks, and no new issues popped up. [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [↓] attach debdiff against the package in testing [ Other info ] Instead of a debdiff, because all changes are contained in d/patches/debian-changes, I attached a diff of the unpacked and patched package minus d/patches/. The changes to Build.sh and check.t are to test the printf builtin. The change to mbsdint.h is the arithmetic fix: a % b instead of a & (b-1) The change to shf.c is to fix the formatting stuff. The changes to sh.h and syn.c are the parser fixes, plus sh.h assigns a unique upstream revision date to the so-patched version to ease $KSH_VERSION-based bugspotting. I cherry-picked the fixes only but kept the RCS IDs as is in order to not clutter the diff for easier review. unblock mksh/59c-28
diff -pruN mksh-59c-26/Build.sh mksh-59c-28/Build.sh --- mksh-59c-26/Build.sh 2023-05-16 19:13:21.000000000 +0200 +++ mksh-59c-28/Build.sh 2023-05-16 19:13:32.000000000 +0200 @@ -2805,6 +2805,7 @@ fi if test 1 = "$USE_PRINTF_BUILTIN"; then cpp_define MKSH_PRINTF_BUILTIN 1 + check_categories="$check_categories printf-builtin" else USE_PRINTF_BUILTIN=0 fi diff -pruN mksh-59c-26/check.t mksh-59c-28/check.t --- mksh-59c-26/check.t 2023-05-16 19:13:21.000000000 +0200 +++ mksh-59c-28/check.t 2023-05-16 19:13:32.000000000 +0200 @@ -31,7 +31,7 @@ # (2013/12/02 20:39:44) http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date expected-stdout: - KSH R59 2023/01/31 + KSH R59 2023/04/28 description: Check base version of full shell stdin: @@ -14254,3 +14254,43 @@ expected-stdout: 2 eh . 3 eh . --- +name: optional-printf-builtin +description: + printf(1) minimal tests +category: printf-builtin +stdin: + t() { + o=$(\\builtin printf "$@"; echo .) + r=$? + print -r -- "$((++n)) ${o%.} : $r" + } + t '<%s>' a b\ c + t '%s - %c %s %d %i %o %u %x %X %b' 3 + t '%% %c %s %d %i %o %u %x %X' 72 73 74 75 76 77 78 79 + t '\\\a\b\f\n\r\t\v\01234' + let n+=2 + t '%b foo %s bar' '\\\a\b\f\n\r\t\v\01234\cdefg' + let ++n + t '<%d>' 1 +2 -3 0x1a 0X1B 010 -011 +012 \'1 \"2 + t '<%d|%d><%+d|%+d><% d|% d><%+ d|%+ d>' 1 -1 1 -1 1 -1 1 -1 + t '<%o|%#o><%x|%#x><%X|%#X>' 8 9 10 11 12 13 + #XXX replace with below + t '|%3d|%-3d|%+3d|%-+3d|%03d|%-03d|%3d|%.3d|notyet|' \ + 1 2 3 4 5 6 7777 8 + #t '|%3d|%-3d|%+3d|%-+3d|%03d|%-03d|%3d|%.3d|%5.3d|' \ + # 1 2 3 4 5 6 7777 8 9 + #12 | 1|2 | +3|+4 |005|6 |7777|008| 009| : 0 +expected-stdout: + 1 <a><b c> : 0 + 2 3 - 0 0 0 0 0 0 : 0 + 3 % 7 73 74 75 114 77 4e 4F : 0 + 4 \ + + 34 : 0 + 7 \ + S4 : 0 + 9 <1><2><-3><26><27><8><-9><10><49><50> : 0 + 10 <1|-1><+1|-1>< 1|-1><+1|-1> : 0 + 11 <10|011><a|0xb><C|0XD> : 0 + 12 | 1|2 | +3|+4 |005|6 |7777|008|notyet| : 0 +--- diff -pruN mksh-59c-26/debian/changelog mksh-59c-28/debian/changelog --- mksh-59c-26/debian/changelog 2023-02-15 16:04:53.000000000 +0100 +++ mksh-59c-28/debian/changelog 2023-04-28 23:34:20.000000000 +0200 @@ -1,3 +1,21 @@ +mksh (59c-28) unstable; urgency=medium + + * Revert 59c-27 changes as mksh is, surprisingly, still a key + package for this release, shunit check-B-D + * Add cherry-picked individual fixes + - fix some formatting routine corner cases + - check the optional printf builtin (used for lksh) in the + testsuite, to avoid the issues reappearing + * Cherry-pick more individual fixes from upstream + - fix shift/rotate for nōn-power-of-two-sized bit quantities + - correct 59c regression in recursive parser for command + substitution and fix the other place it was not reentrant + as well (by moving function-static storage to stack/heap); + crash discovered by Riccardo Felici, USI Lugano + * Revert RCS ID changes, but assign individual version datestamp + + -- Thorsten Glaser <t...@mirbsd.de> Fri, 28 Apr 2023 23:34:20 +0200 + mksh (59c-26) unstable; urgency=medium * Fixup more update-shells breakage also found by piuparts diff -pruN mksh-59c-26/mbsdint.h mksh-59c-28/mbsdint.h --- mksh-59c-26/mbsdint.h 2023-05-16 19:13:21.000000000 +0200 +++ mksh-59c-28/mbsdint.h 2023-05-16 19:13:32.000000000 +0200 @@ -675,7 +675,7 @@ mbiCTAS(mbsdint_h) { #define mbiK_sr(ut,n,vl,vr,vz) mbiK_SR(ut, mbiTYPE_UBITS(ut), n, vl, vr, vz) #define mbiMK_sr(ut,FM,n,l,r,z) mbiMM(ut, (FM), mbiK_SR(ut, mbiMASK_BITS(FM), \ n, mbiMM(ut, (FM), (l)), (r), (z))) -#define mbiK_SR(ut,b,n,l,r,vz) mbiK_RS(ut, b, n, l, mbiUI(r) & (b - 1U), (vz)) +#define mbiK_SR(ut,b,n,l,r,vz) mbiK_RS(ut, b, n, l, mbiUI(r) % mbiUI(b), (vz)) #define mbiK_RS(ut,b,n,v,cl,zx) mbiOT(ut, cl, n(ut, v, cl, b - (cl), zx), v) #define mbiK_shl(ut,ax,cl,CL,z) mbiOshl(ut, ax, cl) #define mbiK_shr(ut,ax,cl,CL,z) mbiOshr(ut, ax, cl) diff -pruN mksh-59c-26/sh.h mksh-59c-28/sh.h --- mksh-59c-26/sh.h 2023-05-16 19:13:21.000000000 +0200 +++ mksh-59c-28/sh.h 2023-05-16 19:13:32.000000000 +0200 @@ -235,7 +235,7 @@ #define __SCCSID(x) __IDSTRING(sccsid,x) #endif -#define MKSH_VERSION "R59 2023/01/31" +#define MKSH_VERSION "R59 2023/04/28" /* shell types */ typedef unsigned char kby; /* byte */ @@ -2150,6 +2150,7 @@ struct ioword { #define IOBASH BIT(10) /* &> etc. */ #define IOHERESTR BIT(11) /* <<< (here string) */ #define IONDELIM BIT(12) /* null delimiter (<<) */ +#define IOSYNIONEXT BIT(13) /* already fully configured */ /* execute/exchild flags */ #define XEXEC BIT(0) /* execute without forking */ diff -pruN mksh-59c-26/shf.c mksh-59c-28/shf.c --- mksh-59c-26/shf.c 2023-05-16 19:13:21.000000000 +0200 +++ mksh-59c-28/shf.c 2023-05-16 19:13:32.000000000 +0200 @@ -837,20 +837,15 @@ shf_smprintf(const char *fmt, ...) char * kslfmt(ksl number, kui flags, char *numbuf) { + /* easy for positive number */ + if (number >= 0) + return (kulfmt((kul)number, flags, numbuf)); + /* negative signed quantity */ if (!IS(flags, FM_TYPE, FL_SGN)) { - /* uh-oh, unsigned? what? be bitwise faithful here */ - union { - /*XXX hopefully not UB… */ - ksl s; - kul u; - } v; - - v.s = number; - return (kulfmt(v.u, flags, numbuf)); + /* uh-oh, output a signed quantity unsignedly */ + return (kulfmt(KSL2UL(number), flags, numbuf)); } - if (number < 0) - flags |= FL_NEG; - return (kulfmt(KSL2NEGUL(number), flags, numbuf)); + return (kulfmt(KSL2NEGUL(number), flags | FL_NEG, numbuf)); } /* pre-initio() */ @@ -892,13 +887,13 @@ kulfmt(kul number, kui flags, char *numb number /= 10UL; } while (number); - if (!IS(flags, FM_TYPE, FL_DEC)) { + if (IS(flags, FM_TYPE, FL_SGN)) { if (HAS(flags, FL_NEG)) *--cp = '-'; else if (HAS(flags, FL_PLUS)) *--cp = '+'; else if (HAS(flags, FL_BLANK)) - *--cp = '-'; + *--cp = ' '; } break; } diff -pruN mksh-59c-26/syn.c mksh-59c-28/syn.c --- mksh-59c-26/syn.c 2023-05-16 19:13:21.000000000 +0200 +++ mksh-59c-28/syn.c 2023-05-16 19:13:32.000000000 +0200 @@ -191,19 +191,16 @@ static struct ioword * synio(int cf) { struct ioword *iop; - static struct ioword *nextiop; Wahr ishere; - if (nextiop != NULL) { - iop = nextiop; - nextiop = NULL; - return (iop); - } - if (tpeek(cf) != REDIR) return (NULL); ACCEPT; iop = yylval.iop; + if (iop->ioflag & IOSYNIONEXT) { + iop->ioflag &= ~IOSYNIONEXT; + return (iop); + } ishere = (iop->ioflag & IOTYPE) == IOHERE; if (iop->ioflag & IOHERESTR) { musthave(LWORD, 0); @@ -228,17 +225,21 @@ synio(int cf) if (iop->ioflag & IOBASH) { char *cp; - nextiop = alloc(sizeof(*iop), ATEMP); - nextiop->ioname = cp = alloc(3, ATEMP); + iop->ioflag &= ~IOBASH; + + cp = alloc(sizeof(struct ioword) + 3U, ATEMP); + yylval.iop = (void *)cp; + cp += sizeof(struct ioword); + yylval.iop->ioname = cp; *cp++ = CHAR; *cp++ = digits_lc[iop->unit]; *cp = EOS; - - iop->ioflag &= ~IOBASH; - nextiop->unit = 2; - nextiop->ioflag = IODUP; - nextiop->delim = NULL; - nextiop->heredoc = NULL; + yylval.iop->delim = NULL; + yylval.iop->heredoc = NULL; + yylval.iop->ioflag = IODUP | IOSYNIONEXT; + yylval.iop->unit = 2; + REJECT; + symbol = REDIR; } return (iop); } @@ -282,7 +283,7 @@ get_command(int cf, int sALIAS) XPtrV args, vars; struct nesting_state old_nesting; Wahr check_decl_utility; - static struct ioword *iops[NUFILE + 1]; + struct ioword *iops[NUFILE + 1]; XPinit(args, 16); XPinit(vars, 16);