Date: Sun, 18 Sep 2011 18:56:49 +0300 From: Kostik Belousov <kostikbel@gmail.com> To: Jilles Tjoelker <jilles@stack.nl> Cc: Peter Pentchev <roam@ringlet.net>, freebsd-current@freebsd.org, Jeremie Le Hen <jeremie@le-hen.org>, David Xu <davidxu@freebsd.org>, Oliver Lehmann <lehmann@ans-netz.de> Subject: Re: Segfault in libthr.so on 9.0-BETA2 (with stunnel FWIW) Message-ID: <20110918155649.GY1511@deviant.kiev.zoral.com.ua> In-Reply-To: <20110918115650.GA36162@stack.nl> References: <20110914123607.GM65366@felucia.tataz.chchile.org> <20110914125953.GX17489@deviant.kiev.zoral.com.ua> <20110914154221.GB7863@felucia.tataz.chchile.org> <20110914200456.GE17489@deviant.kiev.zoral.com.ua> <20110918115650.GA36162@stack.nl>
next in thread | previous in thread | raw e-mail | index | archive | help
--6749iDyxihQ87e9v Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Sun, Sep 18, 2011 at 01:56:50PM +0200, Jilles Tjoelker wrote: > On Wed, Sep 14, 2011 at 11:04:56PM +0300, Kostik Belousov wrote: > > tzload() allocates ~80KB for the local variables. The backtrace you pro= vided > > shows the nested call to tzload(), so there is total 160KB of the stack > > space consumed. >=20 > > By default, stack for the amd64 thread is 4MB, that should be plenty. T= his > > is not the case for ezm3. Possibly, stunnel also reduces the size of the > > thread stack. >=20 > > Please, try the patch below. I did not tested it, only compiled. I see > > that now tzload allocates only ~300 bytes on the stack. >=20 > 80KB seems quite a lot indeed, good to bring it down. >=20 > > diff --git a/contrib/tzcode/stdtime/localtime.c b/contrib/tzcode/stdtim= e/localtime.c > > index 80b70ac..55d55e0 100644 > > --- a/contrib/tzcode/stdtime/localtime.c > > +++ b/contrib/tzcode/stdtime/localtime.c > [snip] > > @@ -406,16 +409,24 @@ register const int doextend; > > ** to hold the longest file name string that the implementation > > ** guarantees can be opened." > > */ > > - char fullname[FILENAME_MAX + 1]; > > + char *fullname; > > + > > + fullname =3D malloc(FILENAME_MAX + 1); > > + if (fullname =3D=3D NULL) > > + goto out; > > =20 > > if (name[0] =3D=3D ':') > > ++name; > > doaccess =3D name[0] =3D=3D '/'; > > if (!doaccess) { > > - if ((p =3D TZDIR) =3D=3D NULL) > > + if ((p =3D TZDIR) =3D=3D NULL) { > > + free(fullname); > > return -1; > > - if ((strlen(p) + 1 + strlen(name) + 1) >=3D sizeof fullname) > > + } > > + if ((strlen(p) + 1 + strlen(name) + 1) >=3D sizeof fullname) { >=20 > This sizeof is now the sizeof of a pointer. The comparison should be > against FILENAME_MAX + 1 instead. >=20 > Alternatively, the name could be created using asprintf(). You are right. I fixed the defect. Updated patch below. diff --git a/contrib/tzcode/stdtime/localtime.c b/contrib/tzcode/stdtime/lo= caltime.c index 80b70ac..b1981b6 100644 --- a/contrib/tzcode/stdtime/localtime.c +++ b/contrib/tzcode/stdtime/localtime.c @@ -380,13 +380,16 @@ register const int doextend; int fid; int stored; int nread; + int res; union { struct tzhead tzhead; char buf[2 * sizeof(struct tzhead) + 2 * sizeof *sp + 4 * TZ_MAX_TIMES]; - } u; + } *u; =20 + u =3D NULL; + res =3D -1; sp->goback =3D sp->goahead =3D FALSE; =20 /* XXX The following is from OpenBSD, and I'm not sure it is correct */ @@ -406,16 +409,24 @@ register const int doextend; ** to hold the longest file name string that the implementation ** guarantees can be opened." */ - char fullname[FILENAME_MAX + 1]; + char *fullname; + + fullname =3D malloc(FILENAME_MAX + 1); + if (fullname =3D=3D NULL) + goto out; =20 if (name[0] =3D=3D ':') ++name; doaccess =3D name[0] =3D=3D '/'; if (!doaccess) { - if ((p =3D TZDIR) =3D=3D NULL) + if ((p =3D TZDIR) =3D=3D NULL) { + free(fullname); return -1; - if ((strlen(p) + 1 + strlen(name) + 1) >=3D sizeof fullname) + } + if (strlen(p) + 1 + strlen(name) >=3D FILENAME_MAX) { + free(fullname); return -1; + } (void) strcpy(fullname, p); (void) strcat(fullname, "/"); (void) strcat(fullname, name); @@ -426,37 +437,45 @@ register const int doextend; doaccess =3D TRUE; name =3D fullname; } - if (doaccess && access(name, R_OK) !=3D 0) + if (doaccess && access(name, R_OK) !=3D 0) { + free(fullname); return -1; - if ((fid =3D _open(name, OPEN_MODE)) =3D=3D -1) + } + if ((fid =3D _open(name, OPEN_MODE)) =3D=3D -1) { + free(fullname); return -1; + } if ((_fstat(fid, &stab) < 0) || !S_ISREG(stab.st_mode)) { + free(fullname); _close(fid); return -1; } } - nread =3D _read(fid, u.buf, sizeof u.buf); + u =3D malloc(sizeof(*u)); + if (u =3D=3D NULL) + goto out; + nread =3D _read(fid, u->buf, sizeof u->buf); if (_close(fid) < 0 || nread <=3D 0) - return -1; + goto out; for (stored =3D 4; stored <=3D 8; stored *=3D 2) { int ttisstdcnt; int ttisgmtcnt; =20 - ttisstdcnt =3D (int) detzcode(u.tzhead.tzh_ttisstdcnt); - ttisgmtcnt =3D (int) detzcode(u.tzhead.tzh_ttisgmtcnt); - sp->leapcnt =3D (int) detzcode(u.tzhead.tzh_leapcnt); - sp->timecnt =3D (int) detzcode(u.tzhead.tzh_timecnt); - sp->typecnt =3D (int) detzcode(u.tzhead.tzh_typecnt); - sp->charcnt =3D (int) detzcode(u.tzhead.tzh_charcnt); - p =3D u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; + ttisstdcnt =3D (int) detzcode(u->tzhead.tzh_ttisstdcnt); + ttisgmtcnt =3D (int) detzcode(u->tzhead.tzh_ttisgmtcnt); + sp->leapcnt =3D (int) detzcode(u->tzhead.tzh_leapcnt); + sp->timecnt =3D (int) detzcode(u->tzhead.tzh_timecnt); + sp->typecnt =3D (int) detzcode(u->tzhead.tzh_typecnt); + sp->charcnt =3D (int) detzcode(u->tzhead.tzh_charcnt); + p =3D u->tzhead.tzh_charcnt + sizeof u->tzhead.tzh_charcnt; if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || sp->typecnt <=3D 0 || sp->typecnt > TZ_MAX_TYPES || sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || (ttisstdcnt !=3D sp->typecnt && ttisstdcnt !=3D 0) || (ttisgmtcnt !=3D sp->typecnt && ttisgmtcnt !=3D 0)) - return -1; - if (nread - (p - u.buf) < + goto out; + if (nread - (p - u->buf) < sp->timecnt * stored + /* ats */ sp->timecnt + /* types */ sp->typecnt * 6 + /* ttinfos */ @@ -464,7 +483,7 @@ register const int doextend; sp->leapcnt * (stored + 4) + /* lsinfos */ ttisstdcnt + /* ttisstds */ ttisgmtcnt) /* ttisgmts */ - return -1; + goto out; for (i =3D 0; i < sp->timecnt; ++i) { sp->ats[i] =3D (stored =3D=3D 4) ? detzcode(p) : detzcode64(p); @@ -473,7 +492,7 @@ register const int doextend; for (i =3D 0; i < sp->timecnt; ++i) { sp->types[i] =3D (unsigned char) *p++; if (sp->types[i] >=3D sp->typecnt) - return -1; + goto out; } for (i =3D 0; i < sp->typecnt; ++i) { struct ttinfo * ttisp; @@ -483,11 +502,11 @@ register const int doextend; p +=3D 4; ttisp->tt_isdst =3D (unsigned char) *p++; if (ttisp->tt_isdst !=3D 0 && ttisp->tt_isdst !=3D 1) - return -1; + goto out; ttisp->tt_abbrind =3D (unsigned char) *p++; if (ttisp->tt_abbrind < 0 || ttisp->tt_abbrind > sp->charcnt) - return -1; + goto out; } for (i =3D 0; i < sp->charcnt; ++i) sp->chars[i] =3D *p++; @@ -512,7 +531,7 @@ register const int doextend; ttisp->tt_ttisstd =3D *p++; if (ttisp->tt_ttisstd !=3D TRUE && ttisp->tt_ttisstd !=3D FALSE) - return -1; + goto out; } } for (i =3D 0; i < sp->typecnt; ++i) { @@ -525,7 +544,7 @@ register const int doextend; ttisp->tt_ttisgmt =3D *p++; if (ttisp->tt_ttisgmt !=3D TRUE && ttisp->tt_ttisgmt !=3D FALSE) - return -1; + goto out; } } /* @@ -558,11 +577,11 @@ register const int doextend; /* ** If this is an old file, we're done. */ - if (u.tzhead.tzh_version[0] =3D=3D '\0') + if (u->tzhead.tzh_version[0] =3D=3D '\0') break; - nread -=3D p - u.buf; + nread -=3D p - u->buf; for (i =3D 0; i < nread; ++i) - u.buf[i] =3D p[i]; + u->buf[i] =3D p[i]; /* ** If this is a narrow integer time_t system, we're done. */ @@ -570,39 +589,43 @@ register const int doextend; break; } if (doextend && nread > 2 && - u.buf[0] =3D=3D '\n' && u.buf[nread - 1] =3D=3D '\n' && + u->buf[0] =3D=3D '\n' && u->buf[nread - 1] =3D=3D '\n' && sp->typecnt + 2 <=3D TZ_MAX_TYPES) { - struct state ts; + struct state *ts; register int result; =20 - u.buf[nread - 1] =3D '\0'; - result =3D tzparse(&u.buf[1], &ts, FALSE); - if (result =3D=3D 0 && ts.typecnt =3D=3D 2 && - sp->charcnt + ts.charcnt <=3D TZ_MAX_CHARS) { + ts =3D malloc(sizeof(*ts)); + if (ts =3D=3D NULL) + goto out; + u->buf[nread - 1] =3D '\0'; + result =3D tzparse(&u->buf[1], ts, FALSE); + if (result =3D=3D 0 && ts->typecnt =3D=3D 2 && + sp->charcnt + ts->charcnt <=3D TZ_MAX_CHARS) { for (i =3D 0; i < 2; ++i) - ts.ttis[i].tt_abbrind +=3D + ts->ttis[i].tt_abbrind +=3D sp->charcnt; - for (i =3D 0; i < ts.charcnt; ++i) + for (i =3D 0; i < ts->charcnt; ++i) sp->chars[sp->charcnt++] =3D - ts.chars[i]; + ts->chars[i]; i =3D 0; - while (i < ts.timecnt && - ts.ats[i] <=3D + while (i < ts->timecnt && + ts->ats[i] <=3D sp->ats[sp->timecnt - 1]) ++i; - while (i < ts.timecnt && + while (i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES) { sp->ats[sp->timecnt] =3D - ts.ats[i]; + ts->ats[i]; sp->types[sp->timecnt] =3D sp->typecnt + - ts.types[i]; + ts->types[i]; ++sp->timecnt; ++i; } - sp->ttis[sp->typecnt++] =3D ts.ttis[0]; - sp->ttis[sp->typecnt++] =3D ts.ttis[1]; + sp->ttis[sp->typecnt++] =3D ts->ttis[0]; + sp->ttis[sp->typecnt++] =3D ts->ttis[1]; } + free(ts); } if (sp->timecnt > 1) { for (i =3D 1; i < sp->timecnt; ++i) @@ -620,7 +643,10 @@ register const int doextend; break; } } - return 0; + res =3D 0; +out: + free(u); + return (res); } =20 static int --6749iDyxihQ87e9v Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (FreeBSD) iEYEARECAAYFAk52FMEACgkQC3+MBN1Mb4gsYgCgvVypsbgE/rSIdiNeCk2D5oDx 1vsAn1Zpa4zeGTuXYWrB6n2abT95wVO7 =Gczh -----END PGP SIGNATURE----- --6749iDyxihQ87e9v--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20110918155649.GY1511>