On Linux, Bash is fine if you don't mind your package builds spending 50% of their time compiling, and 50% spinning in shell scripts. If you'd rather spend your power bill on useful gcc cycles though, you might desire to use a different shell for running build scripts - like pdksh, which is conveniently available at bootstrap time. But what if pdksh does this to you? pdksh -c 'f=`pdksh -c set | wc -l`; f=$((f+1)); while ((f < 100000)); do f=$((f+1)); eval "v_${f}=0"; echo "$f"; done'|tail -1 13106 segmentation fault (core dumped) pdksh -c Well that's annoying, isn't it. % echo $(((13106*10+7)/8)) 16383 ... that's a magical number. Coincidence? Well, no. tp->nfree = 8*nsize/10; /* table can get 80% full */ This particularly ugly overflow happens because tp->size is a short. When texpand() does: p = &ntblp[hash(tblp->name) & (tp->size-1)]; tp->size-1 will, given enough variables (80% of 2^15), type coerce into a sign-extended 32-bit value of: info registers $ecx ecx 0xffff7fff -32769 That hash() function does more or less what you guess, it's a 32 bit unsigned value. The chances of the final pointer pointing inside the valid allocated block of memory are very low indeed. The least-change solution is to change tp->size to a 32 bit value. I've left it signed because that matches, for example, the size parameter passed to texpand(). But really this code would be more correct with a liberal sprinkling of "unsigned", and perhaps a bit of "size_t". This change allows ffmpeg's configure script, as interpreted by pdksh, to produce more usable output than a core file. Bump PKGREVISION for code change.diff -r1.22 -r1.23 pkgsrc/shells/pdksh/Makefile
(dsainty)
@@ -1,18 +1,18 @@ | @@ -1,18 +1,18 @@ | |||
1 | # $NetBSD: Makefile,v 1.22 2014/10/09 14:06:56 wiz Exp $ | 1 | # $NetBSD: Makefile,v 1.23 2015/09/07 06:43:48 dsainty Exp $ | |
2 | # | 2 | # | |
3 | 3 | |||
4 | DISTNAME= pdksh-5.2.14 | 4 | DISTNAME= pdksh-5.2.14 | |
5 | PKGREVISION= 5 | 5 | PKGREVISION= 6 | |
6 | CATEGORIES= shells | 6 | CATEGORIES= shells | |
7 | MASTER_SITES= ftp://ftp.cs.mun.ca/pub/pdksh/ \ | 7 | MASTER_SITES= ftp://ftp.cs.mun.ca/pub/pdksh/ \ | |
8 | http://gd.tuwien.ac.at/utils/shells/pdksh/ \ | 8 | http://gd.tuwien.ac.at/utils/shells/pdksh/ \ | |
9 | ftp://ftp.lip6.fr/pub/unix/shells/pdksh/ \ | 9 | ftp://ftp.lip6.fr/pub/unix/shells/pdksh/ \ | |
10 | ftp://ftp.demon.net/pub/mirrors/pdksh/ | 10 | ftp://ftp.demon.net/pub/mirrors/pdksh/ | |
11 | MASTER_SITES= # maintained locally | 11 | MASTER_SITES= # maintained locally | |
12 | DISTFILES= # empty | 12 | DISTFILES= # empty | |
13 | 13 | |||
14 | MAINTAINER= schmonz@NetBSD.org | 14 | MAINTAINER= schmonz@NetBSD.org | |
15 | HOMEPAGE= http://web.cs.mun.ca/~michael/pdksh/ | 15 | HOMEPAGE= http://web.cs.mun.ca/~michael/pdksh/ | |
16 | COMMENT= Free clone of the AT&T Korn shell | 16 | COMMENT= Free clone of the AT&T Korn shell | |
17 | 17 | |||
18 | BOOTSTRAP_PKG= yes | 18 | BOOTSTRAP_PKG= yes |
@@ -1,22 +1,22 @@ | @@ -1,22 +1,22 @@ | |||
1 | /* $NetBSD: table.h,v 1.2 2008/05/31 16:47:37 tnn Exp $ */ | 1 | /* $NetBSD: table.h,v 1.3 2015/09/07 06:43:48 dsainty Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * generic hashed associative table for commands and variables. | 4 | * generic hashed associative table for commands and variables. | |
5 | */ | 5 | */ | |
6 | 6 | |||
7 | struct table { | 7 | struct table { | |
8 | Area *areap; /* area to allocate entries */ | 8 | Area *areap; /* area to allocate entries */ | |
9 | short size, nfree; /* hash size (always 2^^n), free entries */ | 9 | int size, nfree; /* hash size (always 2^^n), free entries */ | |
10 | struct tbl **tbls; /* hashed table items */ | 10 | struct tbl **tbls; /* hashed table items */ | |
11 | }; | 11 | }; | |
12 | 12 | |||
13 | struct tbl { /* table item */ | 13 | struct tbl { /* table item */ | |
14 | Tflag flag; /* flags */ | 14 | Tflag flag; /* flags */ | |
15 | int type; /* command type (see below), base (if INTEGER), | 15 | int type; /* command type (see below), base (if INTEGER), | |
16 | * or offset from val.s of value (if EXPORT) */ | 16 | * or offset from val.s of value (if EXPORT) */ | |
17 | Area *areap; /* area to allocate from */ | 17 | Area *areap; /* area to allocate from */ | |
18 | union { | 18 | union { | |
19 | char *s; /* string */ | 19 | char *s; /* string */ | |
20 | long i; /* integer */ | 20 | long i; /* integer */ | |
21 | int (*f) ARGS((char **)); /* int function */ | 21 | int (*f) ARGS((char **)); /* int function */ | |
22 | struct op *t; /* "function" tree */ | 22 | struct op *t; /* "function" tree */ |