diff options
-rw-r--r-- | src/falloc.c | 9 | ||||
-rw-r--r-- | src/gdbm.h.in | 3 | ||||
-rw-r--r-- | src/gdbmdefs.h | 7 | ||||
-rw-r--r-- | src/gdbmerrno.c | 3 | ||||
-rw-r--r-- | src/gdbmopen.c | 4 | ||||
-rw-r--r-- | src/gdbmtool.c | 31 |
6 files changed, 43 insertions, 14 deletions
diff --git a/src/falloc.c b/src/falloc.c index 3f437a6..33a238a 100644 --- a/src/falloc.c +++ b/src/falloc.c | |||
@@ -152,7 +152,7 @@ _gdbm_free (GDBM_FILE dbf, off_t file_adr, int num_bytes) | |||
152 | 152 | ||
153 | 153 | ||
154 | /* Gets the avail block at the top of the stack and loads it into the | 154 | /* Gets the avail block at the top of the stack and loads it into the |
155 | active avail block. It does a "free" for itself! This can (and is) | 155 | active avail block. It does a "free" for itself! This can be (and is) |
156 | now called even when the avail block is not empty, so we must be | 156 | now called even when the avail block is not empty, so we must be |
157 | smart about things. */ | 157 | smart about things. */ |
158 | 158 | ||
@@ -206,6 +206,13 @@ pop_avail_block (GDBM_FILE dbf) | |||
206 | return -1; | 206 | return -1; |
207 | } | 207 | } |
208 | 208 | ||
209 | if (!gdbm_avail_block_valid_p (new_blk)) | ||
210 | { | ||
211 | gdbm_set_errno (dbf, GDBM_BAD_AVAIL, TRUE); | ||
212 | _gdbm_fatal (dbf, gdbm_db_strerror (dbf)); | ||
213 | return -1; | ||
214 | } | ||
215 | |||
209 | /* Add the elements from the new block to the header. */ | 216 | /* Add the elements from the new block to the header. */ |
210 | index = 0; | 217 | index = 0; |
211 | while (index < new_blk->count) | 218 | while (index < new_blk->count) |
diff --git a/src/gdbm.h.in b/src/gdbm.h.in index 3d19de7..61d5707 100644 --- a/src/gdbm.h.in +++ b/src/gdbm.h.in | |||
@@ -221,9 +221,10 @@ extern int gdbm_copy_meta (GDBM_FILE dst, GDBM_FILE src); | |||
221 | # define GDBM_DIR_OVERFLOW 31 | 221 | # define GDBM_DIR_OVERFLOW 31 |
222 | # define GDBM_BAD_BUCKET 32 | 222 | # define GDBM_BAD_BUCKET 32 |
223 | # define GDBM_BAD_HEADER 33 | 223 | # define GDBM_BAD_HEADER 33 |
224 | # define GDBM_BAD_AVAIL 34 | ||
224 | 225 | ||
225 | # define _GDBM_MIN_ERRNO 0 | 226 | # define _GDBM_MIN_ERRNO 0 |
226 | # define _GDBM_MAX_ERRNO GDBM_BAD_HEADER | 227 | # define _GDBM_MAX_ERRNO GDBM_BAD_AVAIL |
227 | 228 | ||
228 | /* This one was never used and will be removed in the future */ | 229 | /* This one was never used and will be removed in the future */ |
229 | # define GDBM_UNKNOWN_UPDATE GDBM_UNKNOWN_ERROR | 230 | # define GDBM_UNKNOWN_UPDATE GDBM_UNKNOWN_ERROR |
diff --git a/src/gdbmdefs.h b/src/gdbmdefs.h index bd104e2..5305b0d 100644 --- a/src/gdbmdefs.h +++ b/src/gdbmdefs.h | |||
@@ -51,6 +51,13 @@ typedef struct | |||
51 | avail_elem av_table[1]; /* The table. Make it look like an array. */ | 51 | avail_elem av_table[1]; /* The table. Make it look like an array. */ |
52 | } avail_block; | 52 | } avail_block; |
53 | 53 | ||
54 | /* Return true if avail_block is valid */ | ||
55 | static int inline | ||
56 | gdbm_avail_block_valid_p (avail_block const *av) | ||
57 | { | ||
58 | return (av->size >= 0 && av->count >= 0 && av->count <= av->size); | ||
59 | } | ||
60 | |||
54 | /* The dbm file header keeps track of the current location of the hash | 61 | /* The dbm file header keeps track of the current location of the hash |
55 | directory and the free space in the file. */ | 62 | directory and the free space in the file. */ |
56 | 63 | ||
diff --git a/src/gdbmerrno.c b/src/gdbmerrno.c index 7124b3a..896bf70 100644 --- a/src/gdbmerrno.c +++ b/src/gdbmerrno.c | |||
@@ -133,7 +133,8 @@ const char * const gdbm_errlist[_GDBM_MAX_ERRNO+1] = { | |||
133 | [GDBM_BACKUP_FAILED] = N_("Failed to create backup copy"), | 133 | [GDBM_BACKUP_FAILED] = N_("Failed to create backup copy"), |
134 | [GDBM_DIR_OVERFLOW] = N_("Bucket directory overflow"), | 134 | [GDBM_DIR_OVERFLOW] = N_("Bucket directory overflow"), |
135 | [GDBM_BAD_BUCKET] = N_("Malformed bucket header"), | 135 | [GDBM_BAD_BUCKET] = N_("Malformed bucket header"), |
136 | [GDBM_BAD_HEADER] = N_("Malformed database file header") | 136 | [GDBM_BAD_HEADER] = N_("Malformed database file header"), |
137 | [GDBM_BAD_AVAIL] = N_("Malforemd avail_block") | ||
137 | }; | 138 | }; |
138 | 139 | ||
139 | const char * | 140 | const char * |
diff --git a/src/gdbmopen.c b/src/gdbmopen.c index 5d59f65..b84ad63 100644 --- a/src/gdbmopen.c +++ b/src/gdbmopen.c | |||
@@ -109,6 +109,10 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st) | |||
109 | if (hdr->bucket_elems != bucket_element_count (hdr)) | 109 | if (hdr->bucket_elems != bucket_element_count (hdr)) |
110 | return GDBM_BAD_HEADER; | 110 | return GDBM_BAD_HEADER; |
111 | 111 | ||
112 | /* Validate the avail block */ | ||
113 | if (!gdbm_avail_block_valid_p (&hdr->avail)) | ||
114 | return GDBM_BAD_HEADER; | ||
115 | |||
112 | return 0; | 116 | return 0; |
113 | } | 117 | } |
114 | 118 | ||
diff --git a/src/gdbmtool.c b/src/gdbmtool.c index c522ad0..18d0e10 100644 --- a/src/gdbmtool.c +++ b/src/gdbmtool.c | |||
@@ -225,9 +225,12 @@ _gdbm_avail_list_size (GDBM_FILE dbf, size_t min_size) | |||
225 | break; | 225 | break; |
226 | } | 226 | } |
227 | 227 | ||
228 | if (gdbm_avail_block_valid_p (av_stk)) | ||
229 | { | ||
228 | lines += av_stk->count; | 230 | lines += av_stk->count; |
229 | if (lines > min_size) | 231 | if (lines > min_size) |
230 | break; | 232 | break; |
233 | } | ||
231 | temp = av_stk->next_block; | 234 | temp = av_stk->next_block; |
232 | } | 235 | } |
233 | free (av_stk); | 236 | free (av_stk); |
@@ -235,6 +238,18 @@ _gdbm_avail_list_size (GDBM_FILE dbf, size_t min_size) | |||
235 | return lines; | 238 | return lines; |
236 | } | 239 | } |
237 | 240 | ||
241 | static void | ||
242 | av_table_display (avail_elem *av_table, int count, FILE *fp) | ||
243 | { | ||
244 | int i; | ||
245 | |||
246 | for (i = 0; i < count; i++) | ||
247 | { | ||
248 | fprintf (fp, " %15d %10lu \n", | ||
249 | av_table[i].av_size, (unsigned long) av_table[i].av_adr); | ||
250 | } | ||
251 | } | ||
252 | |||
238 | void | 253 | void |
239 | _gdbm_print_avail_list (FILE *fp, GDBM_FILE dbf) | 254 | _gdbm_print_avail_list (FILE *fp, GDBM_FILE dbf) |
240 | { | 255 | { |
@@ -246,12 +261,7 @@ _gdbm_print_avail_list (FILE *fp, GDBM_FILE dbf) | |||
246 | /* Print the the header avail block. */ | 261 | /* Print the the header avail block. */ |
247 | fprintf (fp, _("\nheader block\nsize = %d\ncount = %d\n"), | 262 | fprintf (fp, _("\nheader block\nsize = %d\ncount = %d\n"), |
248 | dbf->header->avail.size, dbf->header->avail.count); | 263 | dbf->header->avail.size, dbf->header->avail.count); |
249 | for (temp = 0; temp < dbf->header->avail.count; temp++) | 264 | av_table_display (dbf->header->avail.av_table, dbf->header->avail.count, fp); |
250 | { | ||
251 | fprintf (fp, " %15d %10lu \n", | ||
252 | dbf->header->avail.av_table[temp].av_size, | ||
253 | (unsigned long) dbf->header->avail.av_table[temp].av_adr); | ||
254 | } | ||
255 | 265 | ||
256 | /* Initialize the variables for a pass throught the avail stack. */ | 266 | /* Initialize the variables for a pass throught the avail stack. */ |
257 | temp = dbf->header->avail.next_block; | 267 | temp = dbf->header->avail.next_block; |
@@ -280,11 +290,10 @@ _gdbm_print_avail_list (FILE *fp, GDBM_FILE dbf) | |||
280 | /* Print the block! */ | 290 | /* Print the block! */ |
281 | fprintf (fp, _("\nblock = %d\nsize = %d\ncount = %d\n"), temp, | 291 | fprintf (fp, _("\nblock = %d\nsize = %d\ncount = %d\n"), temp, |
282 | av_stk->size, av_stk->count); | 292 | av_stk->size, av_stk->count); |
283 | for (temp = 0; temp < av_stk->count; temp++) | 293 | if (gdbm_avail_block_valid_p (av_stk)) |
284 | { | 294 | av_table_display (av_stk->av_table, av_stk->count, fp); |
285 | fprintf (fp, " %15d %10lu \n", av_stk->av_table[temp].av_size, | 295 | else |
286 | (unsigned long) av_stk->av_table[temp].av_adr); | 296 | terror (_("invalid avail_block")); |
287 | } | ||
288 | temp = av_stk->next_block; | 297 | temp = av_stk->next_block; |
289 | } | 298 | } |
290 | free (av_stk); | 299 | free (av_stk); |