diff options
-rw-r--r-- | src/falloc.c | 2 | ||||
-rw-r--r-- | src/gdbmdefs.h | 5 | ||||
-rw-r--r-- | src/gdbmopen.c | 15 | ||||
-rw-r--r-- | src/gdbmtool.c | 6 |
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")); |