summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/falloc.c13
-rw-r--r--src/gdbm.h.in3
-rw-r--r--src/gdbmdefs.h7
-rw-r--r--src/gdbmerrno.c3
-rw-r--r--src/gdbmopen.c4
-rw-r--r--src/gdbmtool.c37
6 files changed, 48 insertions, 19 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,12 +206,19 @@ 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)
212 { 219 {
213 while(index < new_blk->count 220 while (index < new_blk->count
214 && dbf->header->avail.count < dbf->header->avail.size) 221 && dbf->header->avail.count < dbf->header->avail.size)
215 { 222 {
216 /* With luck, this will merge a lot of blocks! */ 223 /* With luck, this will merge a lot of blocks! */
217 _gdbm_put_av_elem (new_blk->av_table[index], 224 _gdbm_put_av_elem (new_blk->av_table[index],
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_ERRNO0 226 # define _GDBM_MIN_ERRNO0
226 # define _GDBM_MAX_ERRNOGDBM_BAD_HEADER 227 # define _GDBM_MAX_ERRNOGDBM_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 */
55static int inline
56gdbm_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
139const char * 140const char *
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index 5d59f65..b84ad63 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -108,6 +108,10 @@ validate_header (gdbm_file_header const *hdr, struct stat const *st)
108 108
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
112 /* Validate the avail block */
113 if (!gdbm_avail_block_valid_p (&hdr->avail))
114 return GDBM_BAD_HEADER;
111 115
112 return 0; 116 return 0;
113} 117}
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 lines += av_stk->count; 228 if (gdbm_avail_block_valid_p (av_stk))
229 if (lines > min_size) 229 {
230 break; 230 lines += av_stk->count;
231 if (lines > min_size)
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
241static void
242av_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
238void 253void
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);

Return to:

Send suggestions and report system problems to the System administrator.