diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2021-09-19 09:15:48 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2021-09-19 09:15:48 +0300 |
commit | ca7194987388a825f57fdebd73eb9c491a8749b0 (patch) | |
tree | e430121a0f27c2de1a9709231d4bf43a946c6b0a | |
parent | 8952f7fd7cebffbe4ecf8c232e4435c5de72678a (diff) | |
download | gdbm-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.c | 15 | ||||
-rw-r--r-- | src/gdbmseq.c | 7 | ||||
-rw-r--r-- | src/proto.h | 16 |
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); |