aboutsummaryrefslogtreecommitdiff
path: root/src/gdbmstore.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-05-26 22:17:10 +0200
committerSergey Poznyakoff <gray@gnu.org>2018-05-27 17:16:03 +0200
commit4011b4ce9a4c4fa505843381d43a1157cf0c782e (patch)
tree3b12f036a9dabd412a0ada3d6e0c07f44a2dfc91 /src/gdbmstore.c
parentd100aa7a304913fa1692abaa2818418409f3668a (diff)
downloadgdbm-4011b4ce9a4c4fa505843381d43a1157cf0c782e.tar.gz
gdbm-4011b4ce9a4c4fa505843381d43a1157cf0c782e.tar.bz2
Additional validation of avail_table.
Verify that avail_table is sorted by size and that each element's size falls within allowed range. * src/bucket.c (gdbm_get_bucket): Fix bucket validation. Validate bucket_avail. (_gdbm_split_bucket): Check return from _gdbm_free. * src/falloc.c (adjust_bucket_avail,_gdbm_free): Return error code. All uses updated. (pop_avail_block): Fix eventual memory leak. Use gdbm_avail_block_validate. * src/gdbmdefs.h (gdbm_avail_table_valid_p): Change signature. * src/gdbmopen.c (gdbm_avail_table_valid_p): Traverse the array verifying address and size of each element. (gdbm_avail_block_validate) (gdbm_bucket_avail_table_validate): New functions. (validate_header): Remove call to gdbm_avail_block_valid_p. Avail_block is validated later, after it's been loaded. Bail out if header->next_block does not equal the file size. (gdbm_fd_open): Validate avail_block. * src/gdbmstore.c (_gdbm_store): Check return from _gdbm_free. Avoid endless loop in case of inconsistent h_table. * src/gdbmtool.c (_gdbm_print_avail_list): Use gdbm_avail_block_validate. * src/proto.h: Update. * tests/gtload.c: Improve error diagnostics.
Diffstat (limited to 'src/gdbmstore.c')
-rw-r--r--src/gdbmstore.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/src/gdbmstore.c b/src/gdbmstore.c
index 7b2ed04..2ed1616 100644
--- a/src/gdbmstore.c
+++ b/src/gdbmstore.c
@@ -28,12 +28,13 @@
28 before returning from this procedure. The FLAGS define the action to 28 before returning from this procedure. The FLAGS define the action to
29 take when the KEY is already in the database. The value GDBM_REPLACE 29 take when the KEY is already in the database. The value GDBM_REPLACE
30 asks that the old data be replaced by the new CONTENT. The value 30 asks that the old data be replaced by the new CONTENT. The value
31 GDBM_INSERT asks that an error be returned and no action taken. A 31 GDBM_INSERT asks that an error be returned and no action taken.
32 return value of 0 means no errors. A return value of -1 means that 32
33 the item was not stored in the data base because the caller was not an 33 On success (the item was stored), 0 is returned. If the item could
34 official writer. A return value of 0 means that the item was not stored 34 not be stored because a matching key already exists and GDBM_REPLACE
35 because the argument FLAGS was GDBM_INSERT and the KEY was already in 35 was not given, 1 is returned and gdbm_errno (as well as the database
36 the database. */ 36 errno value) is set to GDBM_CANNOT_REPLACE. Otherwise, if another
37 error occurred, -1 is returned. */
37 38
38int 39int
39gdbm_store (GDBM_FILE dbf, datum key, datum content, int flags) 40gdbm_store (GDBM_FILE dbf, datum key, datum content, int flags)
@@ -91,7 +92,8 @@ gdbm_store (GDBM_FILE dbf, datum key, datum content, int flags)
91 + dbf->bucket->h_table[elem_loc].data_size; 92 + dbf->bucket->h_table[elem_loc].data_size;
92 if (free_size != new_size) 93 if (free_size != new_size)
93 { 94 {
94 _gdbm_free (dbf, free_adr, free_size); 95 if (_gdbm_free (dbf, free_adr, free_size))
96 return -1;
95 } 97 }
96 else 98 else
97 { 99 {
@@ -123,6 +125,8 @@ gdbm_store (GDBM_FILE dbf, datum key, datum content, int flags)
123 /* If this is a new entry in the bucket, we need to do special things. */ 125 /* If this is a new entry in the bucket, we need to do special things. */
124 if (elem_loc == -1) 126 if (elem_loc == -1)
125 { 127 {
128 int start_loc;
129
126 if (dbf->bucket->count == dbf->header->bucket_elems) 130 if (dbf->bucket->count == dbf->header->bucket_elems)
127 { 131 {
128 /* Split the current bucket. */ 132 /* Split the current bucket. */
@@ -131,10 +135,17 @@ gdbm_store (GDBM_FILE dbf, datum key, datum content, int flags)
131 } 135 }
132 136
133 /* Find space to insert into bucket and set elem_loc to that place. */ 137 /* Find space to insert into bucket and set elem_loc to that place. */
134 elem_loc = new_hash_val % dbf->header->bucket_elems; 138 elem_loc = start_loc = new_hash_val % dbf->header->bucket_elems;
135 while (dbf->bucket->h_table[elem_loc].hash_value != -1) 139 while (dbf->bucket->h_table[elem_loc].hash_value != -1)
136 elem_loc = (elem_loc + 1) % dbf->header->bucket_elems; 140 {
137 141 elem_loc = (elem_loc + 1) % dbf->header->bucket_elems;
142 if (elem_loc == start_loc)
143 {
144 GDBM_SET_ERRNO (dbf, GDBM_BAD_HASH_TABLE, TRUE);
145 return -1;
146 }
147 }
148
138 /* We now have another element in the bucket. Add the new information.*/ 149 /* We now have another element in the bucket. Add the new information.*/
139 dbf->bucket->count++; 150 dbf->bucket->count++;
140 dbf->bucket->h_table[elem_loc].hash_value = new_hash_val; 151 dbf->bucket->h_table[elem_loc].hash_value = new_hash_val;

Return to:

Send suggestions and report system problems to the System administrator.