aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/falloc.c2
-rw-r--r--src/gdbmdefs.h5
-rw-r--r--src/gdbmopen.c15
-rw-r--r--src/gdbmtool.c6
4 files changed, 22 insertions, 6 deletions
diff --git a/src/falloc.c b/src/falloc.c
index e87a5b7..d146dd0 100644
--- a/src/falloc.c
+++ b/src/falloc.c
@@ -206,7 +206,7 @@ pop_avail_block (GDBM_FILE dbf)
return -1;
}
- if (!gdbm_avail_block_valid_p (new_blk))
+ if (!gdbm_avail_table_valid_p (dbf, new_blk))
{
gdbm_set_errno (dbf, GDBM_BAD_AVAIL, TRUE);
_gdbm_fatal (dbf, gdbm_db_strerror (dbf));
diff --git a/src/gdbmdefs.h b/src/gdbmdefs.h
index 1bb519b..37a5637 100644
--- a/src/gdbmdefs.h
+++ b/src/gdbmdefs.h
@@ -71,9 +71,12 @@ typedef struct
static int inline
gdbm_avail_block_valid_p (avail_block const *av)
{
- return (av->size >= 0 && av->count >= 0 && av->count <= av->size);
+ return (av->size > 1 && av->count >= 0 && av->count <= av->size);
}
+/* Return true if both AV and the size of AV->av_table are valid */
+extern int gdbm_avail_table_valid_p (GDBM_FILE dbf, avail_block const *av);
+
/* The dbm file header keeps track of the current location of the hash
directory and the free space in the file. */
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index b84ad63..52b2739 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -56,6 +56,12 @@ bucket_element_count (gdbm_file_header const *hdr)
/ sizeof (bucket_element) + 1;
}
+int
+gdbm_avail_table_valid_p (GDBM_FILE dbf, avail_block const *av)
+{
+ return gdbm_avail_block_valid_p (av) && av->size <= dbf->header->avail.size;
+}
+
static int
validate_header (gdbm_file_header const *hdr, struct stat const *st)
{
@@ -100,7 +106,10 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st)
return GDBM_BAD_HEADER;
compute_directory_size (hdr->block_size, &dir_size, &dir_bits);
- if (hdr->dir_size != dir_size || hdr->dir_bits != dir_bits)
+ if (!(hdr->dir_size >= dir_size))
+ return GDBM_BAD_HEADER;
+ compute_directory_size (hdr->dir_size, &dir_size, &dir_bits);
+ if (hdr->dir_bits != dir_bits)
return GDBM_BAD_HEADER;
if (!(hdr->bucket_size > 0 && hdr->bucket_size > sizeof(hash_bucket)))
@@ -112,6 +121,10 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st)
/* Validate the avail block */
if (!gdbm_avail_block_valid_p (&hdr->avail))
return GDBM_BAD_HEADER;
+
+ if (((hdr->block_size - sizeof (gdbm_file_header)) / sizeof(avail_elem) + 1)
+ != hdr->avail.size)
+ return GDBM_BAD_HEADER;
return 0;
}
diff --git a/src/gdbmtool.c b/src/gdbmtool.c
index 9c6eebe..575b97b 100644
--- a/src/gdbmtool.c
+++ b/src/gdbmtool.c
@@ -259,8 +259,8 @@ _gdbm_print_avail_list (FILE *fp, GDBM_FILE dbf)
/* Initialize the variables for a pass throught the avail stack. */
temp = dbf->header->avail.next_block;
- size = (((dbf->header->avail.size * sizeof (avail_elem)) >> 1)
- + sizeof (avail_block));
+ size = (dbf->header->avail.size * sizeof (avail_elem))
+ + sizeof (avail_block);
av_stk = emalloc (size);
/* Print the stack. */
@@ -281,7 +281,7 @@ _gdbm_print_avail_list (FILE *fp, GDBM_FILE dbf)
/* Print the block! */
fprintf (fp, _("\nblock = %d\nsize = %d\ncount = %d\n"), temp,
av_stk->size, av_stk->count);
- if (gdbm_avail_block_valid_p (av_stk))
+ if (gdbm_avail_table_valid_p (dbf, av_stk))
av_table_display (av_stk->av_table, av_stk->count, fp);
else
terror (_("invalid avail_block"));

Return to:

Send suggestions and report system problems to the System administrator.