From 4961f247a203adb5826f4a9bfa067e8d97829dc6 Mon Sep 17 00:00:00 2001 From: Ezra Peisach Date: Tue, 30 May 1995 14:48:59 +0000 Subject: [PATCH] If the size field of a struct datum != size field of DBT, you need to copy the information from one structure to the other without casting as you wind up with stack garbage. (DEC alpha OSF) git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5913 dc483132-0cff-0310-8789-dd5450dbe970 --- src/util/berk_db/hash/ChangeLog | 9 +++++ src/util/berk_db/hash/configure.in | 37 +++++++++++++++++++ src/util/berk_db/hash/krb5_ndbm.c | 58 ++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 src/util/berk_db/hash/ChangeLog diff --git a/src/util/berk_db/hash/ChangeLog b/src/util/berk_db/hash/ChangeLog new file mode 100644 index 000000000..e1bd2c4fe --- /dev/null +++ b/src/util/berk_db/hash/ChangeLog @@ -0,0 +1,9 @@ +Tue May 30 09:53:05 1995 Ezra Peisach (epeisach@kangaroo.mit.edu) + + * krb5_ndbm.c: If the size field of datum and DBT do not match, + then passing structures subject to stack garbage. Copy + instaead. + + * configure.in: Determine the size of the datum and DBT size + fields. + diff --git a/src/util/berk_db/hash/configure.in b/src/util/berk_db/hash/configure.in index bac927b85..2d49046af 100644 --- a/src/util/berk_db/hash/configure.in +++ b/src/util/berk_db/hash/configure.in @@ -9,6 +9,43 @@ AC_PROG_RANLIB AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) + +dnl Determine the size of datum and DBT size fields. If they are not the same +dnl then the elements need to be copied. +AC_MSG_CHECKING(size of datum.dsize) +AC_CACHE_VAL(ac_cv_sizeof_datum_dsize, +[AC_TRY_RUN([#include +#include +main() +{ + FILE *f=fopen("conftestval", "w"); + datum k; + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(k.dsize)); + exit(0); +}], ac_cv_sizeof_datum_dsize=`cat conftestval`)])dnl +AC_MSG_RESULT($ac_cv_sizeof_datum_dsize) +AC_DEFINE_UNQUOTED(SIZEOF_DATUM_DSIZE, $ac_cv_sizeof_datum_dsize) + +AC_MSG_CHECKING(size of DBT.size) +AC_CACHE_VAL(ac_cv_sizeof_dbt_size, +[AC_TRY_RUN([#include +#include +typedef struct { + void *data; /* data */ + size_t size; /* data length */ +} DBT; +main() +{ + FILE *f=fopen("conftestval", "w"); + DBT k; + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(k.size)); + exit(0); +}], ac_cv_sizeof_dbt_size=`cat conftestval`)])dnl +AC_MSG_RESULT($ac_cv_sizeof_dbt_size) +AC_DEFINE_UNQUOTED(SIZEOF_DBT_SIZE, $ac_cv_sizeof_dbt_size) + AC_HAVE_FUNCS(mktemp mkstemp) CHECK_SIGNALS SubdirLibraryRule([$(OBJS)]) diff --git a/src/util/berk_db/hash/krb5_ndbm.c b/src/util/berk_db/hash/krb5_ndbm.c index 7baa0321c..92e97fa8f 100644 --- a/src/util/berk_db/hash/krb5_ndbm.c +++ b/src/util/berk_db/hash/krb5_ndbm.c @@ -79,6 +79,22 @@ static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94"; #include #include "hash.h" +/* If the two size fields are not equal, then casting between structures will + result in stack garbage being transfered. Has been observed for DEC Alpha + OSF, but will handle the general case. +*/ + +#ifndef SIZEOF_DBT_SIZE +#define SIZEOF_DBT_SIZE 4 +#endif +#ifndef SIZEOF_DATUM_DSIZE +#define SIZEOF_DATUM_DSIZE 4 +#endif + +#if SIZEOF_DBT_SIZE != SIZEOF_DATUM_DSIZE +#define NEED_COPY +#endif + /* * For Kerberos, we make some generalizations about kdb records. We assume * that records are on average KRB5_DBENT_ASIZE in length. @@ -137,8 +153,17 @@ db_dbm_fetch(db, key) { datum retval; int status; +#ifdef NEED_COPY + DBT k, r; + k.data = key.dptr; + k.size = key.dsize; + status = (db->get)(db, &k, &r, 0); + retval.dptr = r.data; + retval.dsize = r.size; +#else status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0); +#endif if (status) { retval.dptr = NULL; retval.dsize = 0; @@ -157,8 +182,15 @@ db_dbm_firstkey(db) { int status; datum retdata, retkey; +#ifdef NEED_COPY + DBT k, r; + status = (db->seq)(db, &k, &r, R_FIRST); + retkey.dptr = k.data; + retkey.dsize = k.size; +#else status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); +#endif if (status) retkey.dptr = NULL; return (retkey); @@ -175,8 +207,15 @@ db_dbm_nextkey(db) { int status; datum retdata, retkey; +#ifdef NEED_COPY + DBT k, r; + status = (db->seq)(db, &k, &r, R_NEXT); + retkey.dptr = k.data; + retkey.dsize = k.size; +#else status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); +#endif if (status) retkey.dptr = NULL; return (retkey); @@ -192,8 +231,16 @@ db_dbm_delete(db, key) datum key; { int status; +#ifdef NEED_COPY + DBT k; + + k.data = key.dptr; + k.size = key.dsize; + status = (db->del)(db, &k, 0); +#else status = (db->del)(db, (DBT *)&key, 0); +#endif if (status) return (-1); else @@ -212,8 +259,19 @@ db_dbm_store(db, key, content, flags) datum key, content; int flags; { +#ifdef NEED_COPY + DBT k, c; + + k.data = key.dptr; + k.size = key.dsize; + c.data = content.dptr; + c.size = content.dsize; + return ((db->put)(db, &k, &c, + (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); +#else return ((db->put)(db, (DBT *)&key, (DBT *)&content, (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); +#endif } extern int -- 2.26.2