diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-05-19 17:19:20 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-05-19 17:28:35 +0300 |
commit | 2ed5403c82833c8977171972b6779ec92bcc086f (patch) | |
tree | d7c4b170b8ecc08e32e46653e07f45643c929669 /src | |
parent | d228fddf791187b44839b8d8c40478f3577812a2 (diff) | |
download | gdbm-2ed5403c82833c8977171972b6779ec92bcc086f.tar.gz gdbm-2ed5403c82833c8977171972b6779ec92bcc086f.tar.bz2 |
Improve error checking
* src/bucket.c (_gdbm_get_bucket): Improve validation.
* src/fullio.c (_gdbm_full_read,_gdbm_full_write): Don't overwrite
an already set error.
* src/gdbm.h.in (GDBM_WRONG_OFF_T): Merge with GDBM_BAD_FILE_OFFSET.
(GDBM_BAD_HEADER): New error code.
* src/gdbmdump.c (_gdbm_dump_ascii): Check for database error code.
* src/gdbmerrno.c (gdbm_errlist): Add GDBM_BAD_HEADER
* src/gdbmopen.c (validate_header: Imporve logic.
(_gdbm_init_cache): Initialize bucket_cache
* src/gdbmseq.c (gdbm_firstkey): Check return value
from _gdbm_get_bucket.
* src/mmap.c (_gdbm_mapped_remap): Bail out if current position is bigger
than file size.
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 @@ -74,4 +74,2 @@ _gdbm_get_bucket (GDBM_FILE dbf, int dir_index) { - size_t max_bucket_elts; - /* Look in the cache. */ @@ -122,9 +120,6 @@ _gdbm_get_bucket (GDBM_FILE dbf, int dir_index) /* 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)) { diff --git a/src/fullio.c b/src/fullio.c index edff89c..bdb51cb 100644 --- a/src/fullio.c +++ b/src/fullio.c @@ -34,3 +34,4 @@ _gdbm_full_read (GDBM_FILE dbf, void *buffer, size_t size) 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; @@ -61,3 +62,4 @@ _gdbm_full_write (GDBM_FILE dbf, void *buffer, size_t size) 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; 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 @@ -222,6 +222,6 @@ extern int gdbm_copy_meta (GDBM_FILE dst, GDBM_FILE src); # 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 diff --git a/src/gdbmdump.c b/src/gdbmdump.c index 42ed1d3..4b8b041 100644 --- a/src/gdbmdump.c +++ b/src/gdbmdump.c @@ -112,4 +112,5 @@ _gdbm_dump_ascii (GDBM_FILE dbf, FILE *fp) - if (rc == 0) + if (rc == 0 && (rc = gdbm_last_errno (dbf)) == 0) { + /* FIXME: Something like that won't hurt, although load does not diff --git a/src/gdbmerrno.c b/src/gdbmerrno.c index 0c8c8e5..7124b3a 100644 --- a/src/gdbmerrno.c +++ b/src/gdbmerrno.c @@ -124,3 +124,3 @@ const char * const gdbm_errlist[_GDBM_MAX_ERRNO+1] = { [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"), @@ -135,3 +135,3 @@ const char * const gdbm_errlist[_GDBM_MAX_ERRNO+1] = { [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") }; diff --git a/src/gdbmopen.c b/src/gdbmopen.c index 669f8fb..9b214ad 100644 --- a/src/gdbmopen.c +++ b/src/gdbmopen.c @@ -51,2 +51,9 @@ compute_directory_size (GDBM_FILE dbf, blksize_t block_size, +static inline int +bucket_element_count (gdbm_file_header const *hdr) +{ + return (hdr->block_size - sizeof (hash_bucket)) + / sizeof (bucket_element) + 1; +} + static int @@ -70,3 +77,3 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st) case GDBM_MAGIC64: - return GDBM_WRONG_OFF_T; + return GDBM_BAD_FILE_OFFSET; @@ -77,3 +84,4 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st) - 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) >= @@ -89,7 +97,10 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st) && 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; @@ -293,5 +304,3 @@ gdbm_fd_open (int fd, const char *file_name, int 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; @@ -559,3 +568,3 @@ _gdbm_init_cache (GDBM_FILE dbf, size_t size) 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) diff --git a/src/gdbmseq.c b/src/gdbmseq.c index 417bc75..e74d78d 100644 --- a/src/gdbmseq.c +++ b/src/gdbmseq.c @@ -113,11 +113,12 @@ gdbm_firstkey (GDBM_FILE dbf) /* 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); + } @@ -235,3 +235,8 @@ _gdbm_mapped_remap (GDBM_FILE dbf, off_t size, int flag) } - + if (pos > file_size) + { + errno = EINVAL; + GDBM_SET_ERRNO (dbf, GDBM_FILE_SEEK_ERROR, TRUE); + return -1; + } return _gdbm_internal_remap (dbf, size); @@ -273,2 +278,6 @@ _gdbm_mapped_read (GDBM_FILE dbf, void *buffer, size_t len) + if (dbf->need_recovery) + return -1; + + /* Disable memory mapping and retry */ dbf->memory_mapping = FALSE; @@ -323,2 +332,5 @@ _gdbm_mapped_write (GDBM_FILE dbf, void *buffer, size_t len) + if (dbf->need_recovery) + return -1; + dbf->memory_mapping = FALSE; |