summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-09-19 09:15:48 +0300
committerSergey Poznyakoff <gray@gnu.org>2021-09-19 09:15:48 +0300
commitca7194987388a825f57fdebd73eb9c491a8749b0 (patch)
treee430121a0f27c2de1a9709231d4bf43a946c6b0a
parent8952f7fd7cebffbe4ecf8c232e4435c5de72678a (diff)
downloadgdbm-ca7194987388a825f57fdebd73eb9c491a8749b0.tar.gz
Fix key verification in sequential access.
This fixes https://oss-fuzz.com/testcase-detail/6317999997452288 and improves 4046a0af. * src/bucket.c (gdbm_dir_entry_valid_p): Move to proto. * src/proto.h (gdbm_dir_entry_valid_p): New inline function. * src/gdbmseq.c (gdbm_valid_key_p): Use gdbm_dir_entry_valid_p to validate the buffer index. Reorder the checks.
-rw-r--r--src/bucket.c15
-rw-r--r--src/gdbmseq.c7
-rw-r--r--src/proto.h16
3 files changed, 20 insertions, 18 deletions
diff --git a/src/bucket.c b/src/bucket.c
index dd72954..4a5a04c 100644
--- a/src/bucket.c
+++ b/src/bucket.c
@@ -41,21 +41,6 @@ _gdbm_new_bucket (GDBM_FILE dbf, hash_bucket *bucket, int bits)
bucket->h_table[index].hash_value = -1;
}
-/* Return true if the directory entry at DIR_INDEX can be considered
- valid. This means that DIR_INDEX is in the valid range for addressing
- the dir array, and the offset stored in dir[DIR_INDEX] points past
- first two blocks in file. This does not necessarily mean that there's
- a valid bucket or data block at that offset. All this implies is that
- it is safe to use the offset for look up in the bucket cache and to
- attempt to read a block at that offset. */
-static inline int
-gdbm_dir_entry_valid_p (GDBM_FILE dbf, int dir_index)
-{
- return dir_index >= 0
- && dir_index < GDBM_DIR_COUNT (dbf)
- && dbf->dir[dir_index] >= dbf->header->block_size;
-}
-
static void
set_cache_entry (GDBM_FILE dbf, cache_elem *elem)
{
diff --git a/src/gdbmseq.c b/src/gdbmseq.c
index ef40c40..956ba2b 100644
--- a/src/gdbmseq.c
+++ b/src/gdbmseq.c
@@ -26,12 +26,13 @@ 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])
+ if (gdbm_dir_entry_valid_p (dbf, bucket) &&
+ dbf->dir[bucket] == dbf->dir[dbf->bucket_dir] &&
+ hash == dbf->bucket->h_table[elem_loc].hash_value)
return 1;
GDBM_SET_ERRNO (dbf, GDBM_BAD_HASH_ENTRY, TRUE);
return 0;
diff --git a/src/proto.h b/src/proto.h
index 56e7daa..a5d6d10 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -28,6 +28,22 @@ int _gdbm_cache_init (GDBM_FILE, size_t);
void _gdbm_cache_free (GDBM_FILE dbf);
int _gdbm_cache_flush (GDBM_FILE dbf);
+/* Return true if the directory entry at DIR_INDEX can be considered
+ valid. This means that DIR_INDEX is in the valid range for addressing
+ the dir array, and the offset stored in dir[DIR_INDEX] points past
+ first two blocks in file. This does not necessarily mean that there's
+ a valid bucket or data block at that offset. All this implies is that
+ it is safe to use the offset for look up in the bucket cache and to
+ attempt to read a block at that offset. */
+static inline int
+gdbm_dir_entry_valid_p (GDBM_FILE dbf, int dir_index)
+{
+ return dir_index >= 0
+ && dir_index < GDBM_DIR_COUNT (dbf)
+ && dbf->dir[dir_index] >= dbf->header->block_size;
+}
+
+
/* From falloc.c */
off_t _gdbm_alloc (GDBM_FILE, int);
int _gdbm_free (GDBM_FILE, off_t, int);