diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bucket.c | 9 | ||||
-rw-r--r-- | src/fullio.c | 6 | ||||
-rw-r--r-- | src/gdbm.h.in | 6 | ||||
-rw-r--r-- | src/gdbmdump.c | 3 | ||||
-rw-r--r-- | src/gdbmerrno.c | 4 | ||||
-rw-r--r-- | src/gdbmopen.c | 27 | ||||
-rw-r--r-- | src/gdbmseq.c | 19 | ||||
-rw-r--r-- | src/mmap.c | 14 |
8 files changed, 54 insertions, 34 deletions
diff --git a/src/bucket.c b/src/bucket.c index 6def504..ce1915a 100644 --- a/src/bucket.c +++ b/src/bucket.c @@ -72,8 +72,6 @@ _gdbm_get_bucket (GDBM_FILE dbf, int dir_index) /* Is that one is not already current, we must find it. */ if (dbf->cache_entry->ca_adr != bucket_adr) { - size_t max_bucket_elts; - /* Look in the cache. */ for (index = 0; index < dbf->cache_size; index++) { @@ -120,13 +118,10 @@ _gdbm_get_bucket (GDBM_FILE dbf, int dir_index) return -1; } /* Validate the bucket */ - max_bucket_elts = - (dbf->header->bucket_size - sizeof(hash_bucket)) - / sizeof(bucket_element) + 1; if (!(dbf->bucket->count >= 0 && dbf->bucket->av_count >= 0 - && dbf->bucket->count <= max_bucket_elts - && dbf->bucket->av_count <= max_bucket_elts)) + && dbf->bucket->count <= dbf->header->bucket_elems + && dbf->bucket->av_count <= dbf->header->bucket_elems)) { GDBM_SET_ERRNO (dbf, GDBM_BAD_BUCKET, TRUE); return -1; diff --git a/src/fullio.c b/src/fullio.c index edff89c..bdb51cb 100644 --- a/src/fullio.c +++ b/src/fullio.c @@ -32,7 +32,8 @@ _gdbm_full_read (GDBM_FILE dbf, void *buffer, size_t size) { if (errno == EINTR) continue; - GDBM_SET_ERRNO (dbf, GDBM_FILE_READ_ERROR, FALSE); + if (gdbm_last_errno (dbf) == GDBM_NO_ERROR) + GDBM_SET_ERRNO (dbf, GDBM_FILE_READ_ERROR, FALSE); return -1; } if (rdbytes == 0) @@ -59,7 +60,8 @@ _gdbm_full_write (GDBM_FILE dbf, void *buffer, size_t size) { if (errno == EINTR) continue; - GDBM_SET_ERRNO (dbf, GDBM_FILE_WRITE_ERROR, TRUE); + if (gdbm_last_errno (dbf) == GDBM_NO_ERROR) + GDBM_SET_ERRNO (dbf, GDBM_FILE_WRITE_ERROR, TRUE); return -1; } if (wrbytes == 0) diff --git a/src/gdbm.h.in b/src/gdbm.h.in index 6e5fa96..3d19de7 100644 --- a/src/gdbm.h.in +++ b/src/gdbm.h.in @@ -220,10 +220,10 @@ extern int gdbm_copy_meta (GDBM_FILE dst, GDBM_FILE src); # define GDBM_BACKUP_FAILED 30 # define GDBM_DIR_OVERFLOW 31 # define GDBM_BAD_BUCKET 32 -# define GDBM_WRONG_OFF_T 33 - +# define GDBM_BAD_HEADER 33 + # define _GDBM_MIN_ERRNO 0 -# define _GDBM_MAX_ERRNO GDBM_WRONG_OFF_T +# define _GDBM_MAX_ERRNO GDBM_BAD_HEADER /* This one was never used and will be removed in the future */ # define GDBM_UNKNOWN_UPDATE GDBM_UNKNOWN_ERROR diff --git a/src/gdbmdump.c b/src/gdbmdump.c index 42ed1d3..4b8b041 100644 --- a/src/gdbmdump.c +++ b/src/gdbmdump.c @@ -110,8 +110,9 @@ _gdbm_dump_ascii (GDBM_FILE dbf, FILE *fp) count++; } - if (rc == 0) + if (rc == 0 && (rc = gdbm_last_errno (dbf)) == 0) { + /* FIXME: Something like that won't hurt, although load does not use it currently. */ fprintf (fp, "#:count=%lu\n", (unsigned long) count); diff --git a/src/gdbmerrno.c b/src/gdbmerrno.c index 0c8c8e5..7124b3a 100644 --- a/src/gdbmerrno.c +++ b/src/gdbmerrno.c @@ -122,7 +122,7 @@ const char * const gdbm_errlist[_GDBM_MAX_ERRNO+1] = { [GDBM_OPT_ALREADY_SET] = N_("Option already set"), [GDBM_OPT_ILLEGAL] = N_("Illegal option"), [GDBM_BYTE_SWAPPED] = N_("Byte-swapped file"), - [GDBM_BAD_FILE_OFFSET] = N_("Wrong file offset"), + [GDBM_BAD_FILE_OFFSET] = N_("File header assumes wrong off_t size"), [GDBM_BAD_OPEN_FLAGS] = N_("Bad file flags"), [GDBM_FILE_STAT_ERROR] = N_("Cannot stat file"), [GDBM_FILE_EOF] = N_("Unexpected end of file"), @@ -133,7 +133,7 @@ const char * const gdbm_errlist[_GDBM_MAX_ERRNO+1] = { [GDBM_BACKUP_FAILED] = N_("Failed to create backup copy"), [GDBM_DIR_OVERFLOW] = N_("Bucket directory overflow"), [GDBM_BAD_BUCKET] = N_("Malformed bucket header"), - [GDBM_WRONG_OFF_T] = N_("File header assumes wrong off_t size") + [GDBM_BAD_HEADER] = N_("Malformed database file header") }; const char * diff --git a/src/gdbmopen.c b/src/gdbmopen.c index 669f8fb..9b214ad 100644 --- a/src/gdbmopen.c +++ b/src/gdbmopen.c @@ -49,6 +49,13 @@ compute_directory_size (GDBM_FILE dbf, blksize_t block_size, *ret_dir_bits = dir_bits; } +static inline int +bucket_element_count (gdbm_file_header const *hdr) +{ + return (hdr->block_size - sizeof (hash_bucket)) + / sizeof (bucket_element) + 1; +} + static int validate_header (gdbm_file_header const *hdr, struct stat const *st) { @@ -68,14 +75,15 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st) case GDBM_MAGIC32: case GDBM_MAGIC64: - return GDBM_WRONG_OFF_T; + return GDBM_BAD_FILE_OFFSET; default: return GDBM_BAD_MAGIC_NUMBER; } } - if (!(hdr->block_size > sizeof (gdbm_file_header) + if (!(hdr->block_size > 0 + && hdr->block_size > sizeof (gdbm_file_header) && hdr->block_size - sizeof (gdbm_file_header) >= sizeof(hdr->avail.av_table[0]))) { @@ -87,11 +95,14 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st) && hdr->dir < st->st_size && hdr->dir_size > 0 && hdr->dir + hdr->dir_size < st->st_size)) - return GDBM_BAD_FILE_OFFSET; + return GDBM_BAD_HEADER; - if (!(hdr->bucket_size > sizeof(hash_bucket))) - return GDBM_BAD_MAGIC_NUMBER; + if (!(hdr->bucket_size > 0 && hdr->bucket_size > sizeof(hash_bucket))) + return GDBM_BAD_HEADER; + if (hdr->bucket_elems != bucket_element_count (hdr)) + return GDBM_BAD_HEADER; + return 0; } @@ -291,9 +302,7 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, dbf->header->dir = dbf->header->block_size; /* Create the first and only hash bucket. */ - dbf->header->bucket_elems = - (dbf->header->block_size - sizeof (hash_bucket)) - / sizeof (bucket_element) + 1; + dbf->header->bucket_elems = bucket_element_count (dbf->header); dbf->header->bucket_size = dbf->header->block_size; dbf->bucket = calloc (1, dbf->header->bucket_size); if (dbf->bucket == NULL) @@ -557,7 +566,7 @@ _gdbm_init_cache (GDBM_FILE dbf, size_t size) if (dbf->bucket_cache == NULL) { dbf->bucket_cache = GDBM_DEBUG_ALLOC ("_gdbm_init_cache:malloc-failure", - malloc (sizeof(cache_elem) * size)); + calloc (size, sizeof(cache_elem))); if (dbf->bucket_cache == NULL) { GDBM_SET_ERRNO (dbf, GDBM_MALLOC_ERROR, TRUE); diff --git a/src/gdbmseq.c b/src/gdbmseq.c index 417bc75..e74d78d 100644 --- a/src/gdbmseq.c +++ b/src/gdbmseq.c @@ -111,15 +111,16 @@ gdbm_firstkey (GDBM_FILE dbf) gdbm_set_errno (dbf, GDBM_NO_ERROR, FALSE); /* Get the first bucket. */ - _gdbm_get_bucket (dbf, 0); - - /* Look for first entry. */ - get_next_key (dbf, -1, &return_val); - - if (return_val.dptr) - GDBM_DEBUG_DATUM (GDBM_DEBUG_READ, return_val, "%s: found", dbf->name); - else - GDBM_DEBUG (GDBM_DEBUG_READ, "%s: key not found", dbf->name); + if (_gdbm_get_bucket (dbf, 0) == 0) + { + /* Look for first entry. */ + get_next_key (dbf, -1, &return_val); + + if (return_val.dptr) + GDBM_DEBUG_DATUM (GDBM_DEBUG_READ, return_val, "%s: found", dbf->name); + else + GDBM_DEBUG (GDBM_DEBUG_READ, "%s: key not found", dbf->name); + } return return_val; } @@ -233,7 +233,12 @@ _gdbm_mapped_remap (GDBM_FILE dbf, off_t size, int flag) dbf->mapped_pos += dbf->mapped_off; dbf->mapped_off = 0; } - + if (pos > file_size) + { + errno = EINVAL; + GDBM_SET_ERRNO (dbf, GDBM_FILE_SEEK_ERROR, TRUE); + return -1; + } return _gdbm_internal_remap (dbf, size); } @@ -271,6 +276,10 @@ _gdbm_mapped_read (GDBM_FILE dbf, void *buffer, size_t len) { int rc; + if (dbf->need_recovery) + return -1; + + /* Disable memory mapping and retry */ dbf->memory_mapping = FALSE; if (lseek (dbf->desc, pos, SEEK_SET) != pos) return total > 0 ? total : -1; @@ -321,6 +330,9 @@ _gdbm_mapped_write (GDBM_FILE dbf, void *buffer, size_t len) { int rc; + if (dbf->need_recovery) + return -1; + dbf->memory_mapping = FALSE; if (lseek (dbf->desc, pos, SEEK_SET) != pos) return total > 0 ? total : -1; |