aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-03-17 09:01:30 +0200
committerSergey Poznyakoff <gray@gnu.org>2021-03-17 09:12:44 +0200
commit7011ecbaf12a07f912eaf1b3ed6d3a528cefc7ad (patch)
tree30efe45d1513c18f1f98bef815014d7f9030e622
parent2dc9267a91a98733a18ebb3b8488da8016539f83 (diff)
downloadgdbm-7011ecbaf12a07f912eaf1b3ed6d3a528cefc7ad.tar.gz
gdbm-7011ecbaf12a07f912eaf1b3ed6d3a528cefc7ad.tar.bz2
Follow-up fixes to fd5cf245ea.
These address https://puszcza.gnu.org.ua/bugs/?503 * src/gdbmdefs.h (gdbm_avail_block_valid_p): Remove. * src/gdbmopen.c (gdbm_avail_block_validate): Use inline conditional instead of gdbm_avail_block_valid_p. (gdbm_fd_open): Revert to reading master avail_block in two passes (as was before fd5cf245ea). (validate_header): Add back master avail block consistency check. * src/gdbmtool.c (_gdbm_avail_list_size): Use _gdbm_avail_block_read. * src/recover.c (_gdbm_finish_transfer): Reset dbf->file_size.
-rw-r--r--src/gdbmdefs.h7
-rw-r--r--src/gdbmopen.c34
-rw-r--r--src/gdbmtool.c20
-rw-r--r--src/recover.c2
4 files changed, 32 insertions, 31 deletions
diff --git a/src/gdbmdefs.h b/src/gdbmdefs.h
index 4259815..0929e37 100644
--- a/src/gdbmdefs.h
+++ b/src/gdbmdefs.h
@@ -66,13 +66,6 @@ typedef struct
avail_elem av_table[1]; /* The table. Make it look like an array. */
} avail_block;
-/* Return true if avail_block is valid */
-static int inline
-gdbm_avail_block_valid_p (avail_block const *av)
-{
- 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.
See comment to this function in gdbmopen.c */
extern int gdbm_avail_table_valid_p (GDBM_FILE dbf, avail_elem *av, int count);
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index 3ae93a1..21f8e95 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -108,8 +108,9 @@ gdbm_avail_table_valid_p (GDBM_FILE dbf, avail_elem *av, int count)
int
gdbm_avail_block_validate (GDBM_FILE dbf, avail_block *avblk, size_t size)
{
- if (!(((size - sizeof (avail_block)) / sizeof (avail_elem) + 1) >= avblk->count
- && gdbm_avail_block_valid_p (avblk)
+ if (!(size > sizeof (avail_block)
+ && (avblk->size > 1 && avblk->count >= 0 && avblk->count <= avblk->size)
+ && ((size - sizeof (avail_block)) / sizeof (avail_elem) + 1) >= avblk->count
&& gdbm_avail_table_valid_p (dbf, avblk->av_table, avblk->count)))
{
GDBM_SET_ERRNO (dbf, GDBM_BAD_AVAIL, TRUE);
@@ -198,17 +199,15 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st)
if (hdr->bucket_elems != bucket_element_count (hdr->bucket_size))
return GDBM_BAD_HEADER;
+ if (((hdr->block_size - sizeof (gdbm_file_header)) / sizeof(avail_elem) + 1)
+ != hdr->avail.size)
+ return GDBM_BAD_HEADER;
+
return result;
}
-/*
- * GDBM file header is read in two chunks: first, all fields up to avail,
- * then the avail block. PARTIAL_HEADER_SIZE is the size of the first
- * chunk, and HEADER_AVAIL_SIZE(dbf) gives the size of the second one.
- */
-#define PARTIAL_HEADER_SIZE (offsetof (gdbm_file_header, avail))
#define HEADER_AVAIL_SIZE(dbf) \
- ((dbf)->header->block_size - PARTIAL_HEADER_SIZE)
+ ((dbf)->header->block_size - offsetof (gdbm_file_header, avail))
int
_gdbm_validate_header (GDBM_FILE dbf)
@@ -540,7 +539,7 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
int rc;
/* Read the partial file header. */
- if (_gdbm_full_read (dbf, &partial_header, PARTIAL_HEADER_SIZE))
+ if (_gdbm_full_read (dbf, &partial_header, sizeof (partial_header)))
{
GDBM_DEBUG (GDBM_DEBUG_ERR|GDBM_DEBUG_OPEN,
"%s: error reading partial header: %s",
@@ -577,9 +576,9 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
return NULL;
}
- memcpy (dbf->header, &partial_header, PARTIAL_HEADER_SIZE);
- if (_gdbm_avail_block_read (dbf, &dbf->header->avail,
- HEADER_AVAIL_SIZE (dbf)))
+ memcpy (dbf->header, &partial_header, sizeof (partial_header));
+ if (_gdbm_full_read (dbf, &dbf->header->avail.av_table[1],
+ dbf->header->block_size - sizeof (gdbm_file_header)))
{
if (!(flags & GDBM_CLOERROR))
dbf->desc = -1;
@@ -587,6 +586,15 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
return NULL;
}
+ if (gdbm_avail_block_validate (dbf, &dbf->header->avail,
+ HEADER_AVAIL_SIZE (dbf)))
+ {
+ if (!(flags & GDBM_CLOERROR))
+ dbf->desc = -1;
+ SAVE_ERRNO (gdbm_close (dbf));
+ return NULL;
+ }
+
/* Allocate space for the hash table directory. */
dbf->dir = malloc (dbf->header->dir_size);
if (dbf->dir == NULL)
diff --git a/src/gdbmtool.c b/src/gdbmtool.c
index 1c473c9..e0030e1 100644
--- a/src/gdbmtool.c
+++ b/src/gdbmtool.c
@@ -240,19 +240,17 @@ _gdbm_avail_list_size (GDBM_FILE dbf, size_t min_size)
terror ("lseek: %s", strerror (errno));
break;
}
-
- if (_gdbm_full_read (dbf, av_stk, size))
+
+ if (_gdbm_avail_block_read (dbf, av_stk, size))
{
terror ("read: %s", gdbm_db_strerror (dbf));
break;
}
- if (gdbm_avail_block_valid_p (av_stk))
- {
- lines += av_stk->count;
- if (lines > min_size)
- break;
- }
+ lines += av_stk->count;
+ if (lines > min_size)
+ break;
+
temp = av_stk->next_block;
}
free (av_stk);
@@ -276,7 +274,7 @@ void
_gdbm_print_avail_list (FILE *fp, GDBM_FILE dbf)
{
int temp;
- int size;
+ size_t size;
avail_block *av_stk;
/* Print the the header avail block. */
@@ -286,8 +284,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 - 1) * sizeof (avail_elem))
- + sizeof (avail_block);
+ size = (((size_t)dbf->header->avail.size - 1) * sizeof (avail_elem))
+ + sizeof (avail_block);
av_stk = emalloc (size);
/* Print the stack. */
diff --git a/src/recover.c b/src/recover.c
index 9623fae..45de923 100644
--- a/src/recover.c
+++ b/src/recover.c
@@ -168,6 +168,8 @@ _gdbm_finish_transfer (GDBM_FILE dbf, GDBM_FILE new_dbf,
dbf->directory_changed = new_dbf->directory_changed;
dbf->bucket_changed = new_dbf->bucket_changed;
dbf->second_changed = new_dbf->second_changed;
+
+ dbf->file_size = -1;
free (new_dbf->name);
free (new_dbf);

Return to:

Send suggestions and report system problems to the System administrator.