aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gdbm.h.in4
-rw-r--r--src/gdbmerrno.c3
-rw-r--r--src/gdbmseq.c21
3 files changed, 25 insertions, 3 deletions
diff --git a/src/gdbm.h.in b/src/gdbm.h.in
index 621abf4..8ed4f13 100644
--- a/src/gdbm.h.in
+++ b/src/gdbm.h.in
@@ -227,9 +227,9 @@ extern int gdbm_copy_meta (GDBM_FILE dst, GDBM_FILE src);
# define GDBM_FILE_CLOSE_ERROR 37
# define GDBM_FILE_SYNC_ERROR 38
# define GDBM_FILE_TRUNCATE_ERROR 39
-
+# define GDBM_BAD_HASH_ENTRY 40
# define _GDBM_MIN_ERRNO 0
-# define _GDBM_MAX_ERRNO GDBM_FILE_TRUNCATE_ERROR
+# define _GDBM_MAX_ERRNO GDBM_BAD_HASH_ENTRY
/* This one was never used and will be removed in the future */
# define GDBM_UNKNOWN_UPDATE GDBM_UNKNOWN_ERROR
diff --git a/src/gdbmerrno.c b/src/gdbmerrno.c
index 0fa667a..309ebbc 100644
--- a/src/gdbmerrno.c
+++ b/src/gdbmerrno.c
@@ -139,7 +139,8 @@ const char * const gdbm_errlist[_GDBM_MAX_ERRNO+1] = {
[GDBM_BAD_DIR_ENTRY] = N_("Invalid directory entry"),
[GDBM_FILE_CLOSE_ERROR] = N_("Error closing file"),
[GDBM_FILE_SYNC_ERROR] = N_("Error synchronizing file"),
- [GDBM_FILE_TRUNCATE_ERROR] = N_("Error truncating file")
+ [GDBM_FILE_TRUNCATE_ERROR] = N_("Error truncating file"),
+ [GDBM_BAD_HASH_ENTRY] = N_("Malformed bucket hash entry")
};
const char *
diff --git a/src/gdbmseq.c b/src/gdbmseq.c
index b655238..ef40c40 100644
--- a/src/gdbmseq.c
+++ b/src/gdbmseq.c
@@ -21,6 +21,22 @@
#include "gdbmdefs.h"
+static inline int
+gdbm_valid_key_p (GDBM_FILE dbf, char *key_ptr, int key_size, int elem_loc)
+{
+ datum key;
+ int hash, bucket, offset;
+
+ key.dptr = key_ptr;
+ key.dsize = key_size;
+ _gdbm_hash_key (dbf, key, &hash, &bucket, &offset);
+ if (hash == dbf->bucket->h_table[elem_loc].hash_value &&
+ dbf->dir[bucket] == dbf->dir[dbf->bucket_dir])
+ return 1;
+ GDBM_SET_ERRNO (dbf, GDBM_BAD_HASH_ENTRY, TRUE);
+ return 0;
+}
+
/* Find and read the next entry in the hash structure for DBF starting
at ELEM_LOC of the current bucket and using RETURN_VAL as the place to
put the data that is found.
@@ -75,6 +91,11 @@ get_next_key (GDBM_FILE dbf, int elem_loc, datum *return_val)
find_data = _gdbm_read_entry (dbf, elem_loc);
if (!find_data)
return;
+ /* Verify if computed hash and bucket address for the key match the
+ actual ones. Bail out if not. */
+ if (!gdbm_valid_key_p (dbf, find_data,
+ dbf->bucket->h_table[elem_loc].key_size, elem_loc))
+ return;
return_val->dsize = dbf->bucket->h_table[elem_loc].key_size;
if (return_val->dsize == 0)
return_val->dptr = (char *) malloc (1);

Return to:

Send suggestions and report system problems to the System administrator.