summaryrefslogtreecommitdiffabout
path: root/src
authorSergey Poznyakoff <gray@gnu.org>2018-06-23 09:18:41 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2018-06-23 09:18:41 (GMT)
commita5f5662d3919580b7a7b0760a935358bca81174a (patch) (unidiff)
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') (more/less context) (ignore whitespace changes)
-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
@@ -71,15 +71,15 @@ typedef struct
71static int inline 71static int inline
72gdbm_avail_block_valid_p (avail_block const *av) 72gdbm_avail_block_valid_p (avail_block const *av)
73{ 73{
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. */
83 83
84typedef struct 84typedef struct
85{ 85{
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index 677f1cf..9747517 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -53,27 +53,58 @@ compute_directory_size (blksize_t block_size,
53static inline int 53static inline int
54bucket_element_count (size_t bucket_size) 54bucket_element_count (size_t bucket_size)
55{ 55{
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
77int 108int
78gdbm_avail_block_validate (GDBM_FILE dbf, avail_block *avblk) 109gdbm_avail_block_validate (GDBM_FILE dbf, avail_block *avblk)
79{ 110{

Return to:

Send suggestions and report system problems to the System administrator.