aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-06-23 12:18:41 +0300
committerSergey Poznyakoff <gray@gnu.org>2018-06-23 12:18:41 +0300
commita5f5662d3919580b7a7b0760a935358bca81174a (patch)
tree90058fe8dee84dd6b2bc64dc1b02f9703b1aee94 /src
parent9b7336575bf6bfa4b2683289308fea2670dfa3e3 (diff)
downloadgdbm-a5f5662d3919580b7a7b0760a935358bca81174a.tar.gz
gdbm-a5f5662d3919580b7a7b0760a935358bca81174a.tar.bz2
Silently restore sorting order of avail array when checking it.
* src/gdbmdefs.h (gdbm_avail_table_valid_p): Remove const qualifier from the AV parameter. * src/gdbmopen.c (gdbm_avail_table_valid_p): Don't insist on proper ordering of the array. Restore it if neccessary.
Diffstat (limited to 'src')
-rw-r--r--src/gdbmdefs.h6
-rw-r--r--src/gdbmopen.c39
2 files changed, 38 insertions, 7 deletions
diff --git a/src/gdbmdefs.h b/src/gdbmdefs.h
index af6f09c..9740b16 100644
--- a/src/gdbmdefs.h
+++ b/src/gdbmdefs.h
@@ -74,9 +74,9 @@ gdbm_avail_block_valid_p (avail_block const *av)
74 return (av->size > 1 && av->count >= 0 && av->count <= av->size); 74 return (av->size > 1 && av->count >= 0 && av->count <= av->size);
75} 75}
76 76
77/* Return true if both AV and the size of AV->av_table are valid */ 77/* Return true if both AV and the size of AV->av_table are valid.
78extern int gdbm_avail_table_valid_p (GDBM_FILE dbf, 78 See comment to this function in gdbmopen.c */
79 avail_elem const *av, int count); 79extern int gdbm_avail_table_valid_p (GDBM_FILE dbf, avail_elem *av, int count);
80 80
81/* The dbm file header keeps track of the current location of the hash 81/* The dbm file header keeps track of the current location of the hash
82 directory and the free space in the file. */ 82 directory and the free space in the file. */
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index 677f1cf..9747517 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -56,21 +56,52 @@ bucket_element_count (size_t bucket_size)
56 return (bucket_size - sizeof (hash_bucket)) / sizeof (bucket_element) + 1; 56 return (bucket_size - sizeof (hash_bucket)) / sizeof (bucket_element) + 1;
57} 57}
58 58
59static int
60avail_comp (void const *a, void const *b)
61{
62 avail_elem const *ava = a;
63 avail_elem const *avb = b;
64 return ava->av_size - avb->av_size;
65}
66
67/* Returns true if the avail array AV[0]@COUNT is valid.
68
69 As a side effect, ensures the array is sorted by element size
70 in increasing order and restores the ordering if necessary.
71
72 The proper ordering could have been clobbered in versions of GDBM<=1.14,
73 by a call to _gdbm_put_av_elem with the can_merge parameter set to
74 TRUE. This happened in two cases: either because the GDBM_COALESCEBLKS
75 was set, and (quite unfortunately) when _gdbm_put_av_elem was called
76 from pop_avail_block in falloc.c. The latter case is quite common,
77 which means that there can be lots of existing databases with broken
78 ordering of avail arrays. Thus, restoring of the proper ordering
79 is essential for people to be able to use their existing databases.
80*/
59int 81int
60gdbm_avail_table_valid_p (GDBM_FILE dbf, avail_elem const *av, int count) 82gdbm_avail_table_valid_p (GDBM_FILE dbf, avail_elem *av, int count)
61{ 83{
62 off_t prev = 0; 84 off_t prev = 0;
63 int i; 85 int i;
64 86 int needs_sorting = 0;
87
65 prev = 0; 88 prev = 0;
66 for (i = 0; i < count; i++, av++) 89 for (i = 0; i < count; i++, av++)
67 { 90 {
68 if (!(av->av_size >= prev 91 if (!(av->av_adr >= dbf->header->bucket_size
69 && av->av_adr >= dbf->header->bucket_size
70 && av->av_adr + av->av_size <= dbf->header->next_block)) 92 && av->av_adr + av->av_size <= dbf->header->next_block))
71 return 0; 93 return 0;
94 if (av->av_size < prev)
95 needs_sorting = 1;
72 prev = av->av_size; 96 prev = av->av_size;
73 } 97 }
98
99 if (needs_sorting && dbf->read_write)
100 {
101 GDBM_DEBUG (GDBM_DEBUG_ERR, "restoring sort order");
102 qsort (av, count, sizeof av[0], avail_comp);
103 }
104
74 return 1; 105 return 1;
75} 106}
76 107

Return to:

Send suggestions and report system problems to the System administrator.