aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-05-19 17:19:20 +0300
committerSergey Poznyakoff <gray@gnu.org>2018-05-19 17:28:35 +0300
commit2ed5403c82833c8977171972b6779ec92bcc086f (patch)
treed7c4b170b8ecc08e32e46653e07f45643c929669 /src
parentd228fddf791187b44839b8d8c40478f3577812a2 (diff)
downloadgdbm-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.c9
-rw-r--r--src/fullio.c6
-rw-r--r--src/gdbm.h.in6
-rw-r--r--src/gdbmdump.c3
-rw-r--r--src/gdbmerrno.c4
-rw-r--r--src/gdbmopen.c27
-rw-r--r--src/gdbmseq.c19
-rw-r--r--src/mmap.c14
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);
+ }
diff --git a/src/mmap.c b/src/mmap.c
index fd8a72b..9a7d400 100644
--- a/src/mmap.c
+++ b/src/mmap.c
@@ -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;

Return to:

Send suggestions and report system problems to the System administrator.