You want this, too? Ingo ----- Forwarded message from Ingo Schwarze <schwarze@cvs.openbsd.org> ----- From: Ingo Schwarze <schwarze@cvs.openbsd.org> Date: Mon, 19 Dec 2011 17:41:24 -0700 (MST) To: source-changes@cvs.openbsd.org Subject: CVS: cvs.openbsd.org: src CVSROOT: /cvs Module name: src Changes by: schwarze@cvs.openbsd.org 2011/12/19 17:41:24 Modified files: usr.bin/mandoc : apropos_db.c mandocdb.c Log message: Do not cast void pointers to pointers requiring alignment. This makes mandocdb(8)/apropos(1) work on strict alignment architectures. Basic way to fix this confirmed by deraadt@ and kettenis@, thanks. This now works on both sparc64 and i386, but note that the binary database format is still machine-dependent. ----- End forwarded message ----- Index: apropos_db.c =================================================================== RCS file: /cvs/src/usr.bin/mandoc/apropos_db.c,v retrieving revision 1.15 diff -u -p -r1.15 apropos_db.c --- apropos_db.c 19 Dec 2011 02:26:33 -0000 1.15 +++ apropos_db.c 20 Dec 2011 00:18:56 -0000 @@ -160,7 +160,7 @@ btree_read(const DBT *k, const DBT *v, const struct mchars *mc, struct db_val *dbv, char **buf) { - const struct db_val *vp; + struct db_val raw_dbv; /* Are our sizes sane? */ if (k->size < 2 || sizeof(struct db_val) != v->size) @@ -170,10 +170,10 @@ btree_read(const DBT *k, const DBT *v, if ('\0' != ((const char *)k->data)[(int)k->size - 1]) return(0); - vp = v->data; norm_string((const char *)k->data, mc, buf); - dbv->rec = betoh32(vp->rec); - dbv->mask = betoh64(vp->mask); + memcpy(&raw_dbv, v->data, v->size); + dbv->rec = betoh32(raw_dbv.rec); + dbv->mask = betoh64(raw_dbv.mask); return(1); } @@ -369,7 +369,8 @@ index_read(const DBT *key, const DBT *va return(0); cp = val->data; - rec->res.rec = *(recno_t *)key->data; + assert(sizeof(recno_t) == key->size); + memcpy(&rec->res.rec, key->data, key->size); rec->res.volume = index; if ('d' == (type = *cp++)) Index: mandocdb.c =================================================================== RCS file: /cvs/src/usr.bin/mandoc/mandocdb.c,v retrieving revision 1.26 diff -u -p -r1.26 mandocdb.c --- mandocdb.c 19 Dec 2011 02:26:33 -0000 1.26 +++ mandocdb.c 20 Dec 2011 00:18:58 -0000 @@ -518,6 +518,7 @@ index_merge(const struct of *of, struct struct mdoc *mdoc; struct man *man; const char *fn, *msec, *mtitle, *arch; + uint64_t mask; size_t sv; unsigned seq; struct db_val vbuf; @@ -648,7 +649,9 @@ index_merge(const struct of *of, struct seq = R_FIRST; while (0 == (ch = (*hash->seq)(hash, &key, &val, seq))) { seq = R_NEXT; - vbuf.mask = htobe64(*(uint64_t *)val.data); + assert(sizeof(uint64_t) == val.size); + memcpy(&mask, val.data, val.size); + vbuf.mask = htobe64(mask); val.size = sizeof(struct db_val); val.data = &vbuf; dbt_put(db, dbf, &key, &val); @@ -701,7 +704,8 @@ index_prune(const struct of *ofile, DB * seq = R_FIRST; while (0 == (ch = (*idx->seq)(idx, &key, &val, seq))) { seq = R_NEXT; - *maxrec = *(recno_t *)key.data; + assert(sizeof(recno_t) == key.size); + memcpy(maxrec, key.data, key.size); /* Deleted records are zero-sized. Skip them. */ @@ -1061,6 +1065,7 @@ pmdoc_Sh(MDOC_ARGS) static void hash_put(DB *db, const struct buf *buf, uint64_t mask) { + uint64_t oldmask; DBT key, val; int rc; @@ -1073,8 +1078,11 @@ hash_put(DB *db, const struct buf *buf, if ((rc = (*db->get)(db, &key, &val, 0)) < 0) { perror("hash"); exit((int)MANDOCLEVEL_SYSERR); - } else if (0 == rc) - mask |= *(uint64_t *)val.data; + } else if (0 == rc) { + assert(sizeof(uint64_t) == val.size); + memcpy(&oldmask, val.data, val.size); + mask |= oldmask; + } val.data = &mask; val.size = sizeof(uint64_t); -- To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv
> You want this, too? Is it easier to apply this or wait for the patch being reviewed by millert@? Whichever's more convenient for you. However, I don't like the assertions in this code. A bad database shouldn't result in assertions (except the internal hashtable, as it's a programmatic matter). All of these areas (index_prune(), index_read(), etc.), are built with failure handlers when break;ing or return badly. Can you modify the patch to use these instead? But of course, I'm following these conversations and want these also! Thanks, Kristaps > Ingo > > ----- Forwarded message from Ingo Schwarze<schwarze@cvs.openbsd.org> ----- > > From: Ingo Schwarze<schwarze@cvs.openbsd.org> > Date: Mon, 19 Dec 2011 17:41:24 -0700 (MST) > To: source-changes@cvs.openbsd.org > Subject: CVS: cvs.openbsd.org: src > > CVSROOT: /cvs > Module name: src > Changes by: schwarze@cvs.openbsd.org 2011/12/19 17:41:24 > > Modified files: > usr.bin/mandoc : apropos_db.c mandocdb.c > > Log message: > Do not cast void pointers to pointers requiring alignment. > This makes mandocdb(8)/apropos(1) work on strict alignment architectures. > Basic way to fix this confirmed by deraadt@ and kettenis@, thanks. > > This now works on both sparc64 and i386, but note that the binary > database format is still machine-dependent. > > ----- End forwarded message ----- > > Index: apropos_db.c > =================================================================== > RCS file: /cvs/src/usr.bin/mandoc/apropos_db.c,v > retrieving revision 1.15 > diff -u -p -r1.15 apropos_db.c > --- apropos_db.c 19 Dec 2011 02:26:33 -0000 1.15 > +++ apropos_db.c 20 Dec 2011 00:18:56 -0000 > @@ -160,7 +160,7 @@ btree_read(const DBT *k, const DBT *v, > const struct mchars *mc, > struct db_val *dbv, char **buf) > { > - const struct db_val *vp; > + struct db_val raw_dbv; > > /* Are our sizes sane? */ > if (k->size< 2 || sizeof(struct db_val) != v->size) > @@ -170,10 +170,10 @@ btree_read(const DBT *k, const DBT *v, > if ('\0' != ((const char *)k->data)[(int)k->size - 1]) > return(0); > > - vp = v->data; > norm_string((const char *)k->data, mc, buf); > - dbv->rec = betoh32(vp->rec); > - dbv->mask = betoh64(vp->mask); > + memcpy(&raw_dbv, v->data, v->size); > + dbv->rec = betoh32(raw_dbv.rec); > + dbv->mask = betoh64(raw_dbv.mask); > return(1); > } > > @@ -369,7 +369,8 @@ index_read(const DBT *key, const DBT *va > return(0); > > cp = val->data; > - rec->res.rec = *(recno_t *)key->data; > + assert(sizeof(recno_t) == key->size); > + memcpy(&rec->res.rec, key->data, key->size); > rec->res.volume = index; > > if ('d' == (type = *cp++)) > Index: mandocdb.c > =================================================================== > RCS file: /cvs/src/usr.bin/mandoc/mandocdb.c,v > retrieving revision 1.26 > diff -u -p -r1.26 mandocdb.c > --- mandocdb.c 19 Dec 2011 02:26:33 -0000 1.26 > +++ mandocdb.c 20 Dec 2011 00:18:58 -0000 > @@ -518,6 +518,7 @@ index_merge(const struct of *of, struct > struct mdoc *mdoc; > struct man *man; > const char *fn, *msec, *mtitle, *arch; > + uint64_t mask; > size_t sv; > unsigned seq; > struct db_val vbuf; > @@ -648,7 +649,9 @@ index_merge(const struct of *of, struct > seq = R_FIRST; > while (0 == (ch = (*hash->seq)(hash,&key,&val, seq))) { > seq = R_NEXT; > - vbuf.mask = htobe64(*(uint64_t *)val.data); > + assert(sizeof(uint64_t) == val.size); > + memcpy(&mask, val.data, val.size); > + vbuf.mask = htobe64(mask); > val.size = sizeof(struct db_val); > val.data =&vbuf; > dbt_put(db, dbf,&key,&val); > @@ -701,7 +704,8 @@ index_prune(const struct of *ofile, DB * > seq = R_FIRST; > while (0 == (ch = (*idx->seq)(idx,&key,&val, seq))) { > seq = R_NEXT; > - *maxrec = *(recno_t *)key.data; > + assert(sizeof(recno_t) == key.size); > + memcpy(maxrec, key.data, key.size); > > /* Deleted records are zero-sized. Skip them. */ > > @@ -1061,6 +1065,7 @@ pmdoc_Sh(MDOC_ARGS) > static void > hash_put(DB *db, const struct buf *buf, uint64_t mask) > { > + uint64_t oldmask; > DBT key, val; > int rc; > > @@ -1073,8 +1078,11 @@ hash_put(DB *db, const struct buf *buf, > if ((rc = (*db->get)(db,&key,&val, 0))< 0) { > perror("hash"); > exit((int)MANDOCLEVEL_SYSERR); > - } else if (0 == rc) > - mask |= *(uint64_t *)val.data; > + } else if (0 == rc) { > + assert(sizeof(uint64_t) == val.size); > + memcpy(&oldmask, val.data, val.size); > + mask |= oldmask; > + } > > val.data =&mask; > val.size = sizeof(uint64_t); > -- > To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv > -- To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv
Hi Kristaps, Kristaps Dzonsons wrote on Tue, Dec 20, 2011 at 11:58:07AM +0100: > Is it easier to apply this or wait for the patch being reviewed by > millert@? Whichever's more convenient for you. I guess i'll apply it unless millert@ provides feedback before we agree on it. > However, I don't like the assertions in this code. A bad database > shouldn't result in assertions (except the internal hashtable, as > it's a programmatic matter). I fully agree with that, but there are no assertions of the kind you seem to suspect. > All of these areas (index_prune(), index_read(), etc.), are built > with failure handlers when break;ing or return badly. Can you > modify the patch to use these instead? That's already the case. Yours, Ingo >>@@ -170,10 +170,10 @@ btree_read(const DBT *k, const DBT *v, >> if ('\0' != ((const char *)k->data)[(int)k->size - 1]) >> return(0); >> >>- vp = v->data; >> norm_string((const char *)k->data, mc, buf); >>- dbv->rec = betoh32(vp->rec); >>- dbv->mask = betoh64(vp->mask); >>+ memcpy(&raw_dbv, v->data, v->size); >>+ dbv->rec = betoh32(raw_dbv.rec); >>+ dbv->mask = betoh64(raw_dbv.mask); >> return(1); >> } >> No assertion here, checks are above (unchanged). >>@@ -369,7 +369,8 @@ index_read(const DBT *key, const DBT *va >> return(0); >> >> cp = val->data; >>- rec->res.rec = *(recno_t *)key->data; >>+ assert(sizeof(recno_t) == key->size); >>+ memcpy(&rec->res.rec, key->data, key->size); >> rec->res.volume = index; >> >> if ('d' == (type = *cp++)) The key is not stored in the database but is just the record number in the file, so this asserts against internal malfunctioning of recno(3). >>@@ -648,7 +649,9 @@ index_merge(const struct of *of, struct >> seq = R_FIRST; >> while (0 == (ch = (*hash->seq)(hash,&key,&val, seq))) { >> seq = R_NEXT; >>- vbuf.mask = htobe64(*(uint64_t *)val.data); >>+ assert(sizeof(uint64_t) == val.size); >>+ memcpy(&mask, val.data, val.size); >>+ vbuf.mask = htobe64(mask); >> val.size = sizeof(struct db_val); >> val.data =&vbuf; >> dbt_put(db, dbf,&key,&val); Assert against hash mishandling. >>@@ -701,7 +704,8 @@ index_prune(const struct of *ofile, DB * >> seq = R_FIRST; >> while (0 == (ch = (*idx->seq)(idx,&key,&val, seq))) { >> seq = R_NEXT; >>- *maxrec = *(recno_t *)key.data; >>+ assert(sizeof(recno_t) == key.size); >>+ memcpy(maxrec, key.data, key.size); >> >> /* Deleted records are zero-sized. Skip them. */ >> Assert against internal recno(3) errors, see above. >>@@ -1073,8 +1078,11 @@ hash_put(DB *db, const struct buf *buf, >> if ((rc = (*db->get)(db,&key,&val, 0))< 0) { >> perror("hash"); >> exit((int)MANDOCLEVEL_SYSERR); >>- } else if (0 == rc) >>- mask |= *(uint64_t *)val.data; >>+ } else if (0 == rc) { >>+ assert(sizeof(uint64_t) == val.size); >>+ memcpy(&oldmask, val.data, val.size); >>+ mask |= oldmask; >>+ } Against hash mishandling, see above. -- To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv
On 12/20/11 17:47, Ingo Schwarze wrote:
> Hi Kristaps,
>
> Kristaps Dzonsons wrote on Tue, Dec 20, 2011 at 11:58:07AM +0100:
>
>> Is it easier to apply this or wait for the patch being reviewed by
>> millert@? Whichever's more convenient for you.
>
> I guess i'll apply it unless millert@ provides feedback before
> we agree on it.
>
>> However, I don't like the assertions in this code. A bad database
>> shouldn't result in assertions (except the internal hashtable, as
>> it's a programmatic matter).
>
> I fully agree with that, but there are no assertions of the kind you
> seem to suspect.
>
>> All of these areas (index_prune(), index_read(), etc.), are built
>> with failure handlers when break;ing or return badly. Can you
>> modify the patch to use these instead?
>
> That's already the case.
Gah, you're absolutely right -- I didn't look closely enough. Thanks again!
--
To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv