summaryrefslogtreecommitdiffabout
path: root/src/findkey.c
Side-by-side diff
Diffstat (limited to 'src/findkey.c') (more/less context) (ignore whitespace changes)
-rw-r--r--src/findkey.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/src/findkey.c b/src/findkey.c
index 7638b04..bd9fd83 100644
--- a/src/findkey.c
+++ b/src/findkey.c
@@ -1,65 +1,85 @@
/* findkey.c - The routine that finds a key entry in the file. */
/* This file is part of GDBM, the GNU data base manager.
Copyright (C) 1990-1991, 1993, 2007, 2011, 2013, 2016-2018 Free
Software Foundation, Inc.
GDBM is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GDBM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDBM. If not, see <http://www.gnu.org/licenses/>. */
/* Include system configuration before all else. */
#include "autoconf.h"
#include "gdbmdefs.h"
-
+int
+gdbm_bucket_element_valid_p (GDBM_FILE dbf, int elem_loc)
+{
+ return
+ elem_loc < dbf->header->bucket_elems
+ && dbf->bucket->h_table[elem_loc].hash_value != -1
+ && dbf->bucket->h_table[elem_loc].key_size >= 0
+ && off_t_sum_ok (dbf->bucket->h_table[elem_loc].data_pointer,
+ dbf->bucket->h_table[elem_loc].key_size)
+ && dbf->bucket->h_table[elem_loc].data_size >= 0
+ && off_t_sum_ok (dbf->bucket->h_table[elem_loc].data_pointer
+ + dbf->bucket->h_table[elem_loc].key_size,
+ dbf->bucket->h_table[elem_loc].data_size);
+}
+
/* Read the data found in bucket entry ELEM_LOC in file DBF and
return a pointer to it. Also, cache the read value. */
char *
_gdbm_read_entry (GDBM_FILE dbf, int elem_loc)
{
int rc;
int key_size;
int data_size;
off_t file_pos;
data_cache_elem *data_ca;
-
+
/* Is it already in the cache? */
if (dbf->cache_entry->ca_data.elem_loc == elem_loc)
return dbf->cache_entry->ca_data.dptr;
+ if (!gdbm_bucket_element_valid_p (dbf, elem_loc))
+ {
+ GDBM_SET_ERRNO (dbf, GDBM_BAD_HASH_TABLE, TRUE);
+ return NULL;
+ }
+
/* Set sizes and pointers. */
key_size = dbf->bucket->h_table[elem_loc].key_size;
data_size = dbf->bucket->h_table[elem_loc].data_size;
data_ca = &dbf->cache_entry->ca_data;
/* Set up the cache. */
if (data_ca->dptr != NULL) free (data_ca->dptr);
data_ca->key_size = key_size;
data_ca->data_size = data_size;
data_ca->elem_loc = elem_loc;
data_ca->hash_val = dbf->bucket->h_table[elem_loc].hash_value;
if (GDBM_DEBUG_HOOK ("_gdbm_read_entry:malloc-failure"))
data_ca->dptr = NULL;
else if (key_size + data_size == 0)
data_ca->dptr = (char *) malloc (1);
else
data_ca->dptr = (char *) malloc (key_size + data_size);
if (data_ca->dptr == NULL)
{
GDBM_SET_ERRNO2 (dbf, GDBM_MALLOC_ERROR, FALSE, GDBM_DEBUG_LOOKUP);
_gdbm_fatal (dbf, _("malloc error"));
return NULL;
}

Return to:

Send suggestions and report system problems to the System administrator.