Gentoo Archives: gentoo-commits

From: Fabian Groffen <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage-utils:master commit in: libq/
Date: Wed, 29 Dec 2021 12:20:10
Message-Id: 1640780252.cea99ce1b9b6d0c9ebb496dcd2f1e77ab9ab1dcd.grobian@gentoo
1 commit: cea99ce1b9b6d0c9ebb496dcd2f1e77ab9ab1dcd
2 Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
3 AuthorDate: Wed Dec 29 12:17:32 2021 +0000
4 Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
5 CommitDate: Wed Dec 29 12:17:32 2021 +0000
6 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=cea99ce1
7
8 libq/tree: avoid nasty realloc magic on tree_pkg_meta
9
10 doing reallocs possibly (hight probability) invalidates previously
11 retrieved pointers, which is really nasty to work with, and error prone,
12 so instead allocate incremental slabs where necessary
13
14 Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
15
16 libq/tree.c | 206 +++++++++++++++++++++++++++++++-----------------------------
17 libq/tree.h | 11 +++-
18 2 files changed, 116 insertions(+), 101 deletions(-)
19
20 diff --git a/libq/tree.c b/libq/tree.c
21 index 87df175..114541d 100644
22 --- a/libq/tree.c
23 +++ b/libq/tree.c
24 @@ -651,6 +651,21 @@ tree_pkg_vdb_eat(
25 return ret;
26 }
27
28 +#define tree_meta_alloc_storage(M,SIZ) { \
29 + struct tree_pkg_meta_ll *blk; \
30 + size_t newlen; \
31 +\
32 + /* calculate new block size, ensuring it covers whatever we \
33 + * need to write this iteration */ \
34 + newlen = ((((SIZ) + 1) / BUFSIZ) + 1) * BUFSIZ; \
35 + blk = xmalloc(sizeof(*blk) + newlen); \
36 + memset(blk, 0, sizeof(*blk)); \
37 + blk->next = M->storage; \
38 + blk->ptr = (char *)blk + sizeof(*blk); \
39 + blk->len = newlen; \
40 + M->storage = blk; \
41 +}
42 +
43 static tree_pkg_meta *
44 tree_read_file_pms(tree_pkg_ctx *pkg_ctx)
45 {
46 @@ -668,8 +683,9 @@ tree_read_file_pms(tree_pkg_ctx *pkg_ctx)
47 goto err;
48
49 len = sizeof(*ret) + s.st_size + 1;
50 - ret = xzalloc(len);
51 - ptr = (char*)ret + sizeof(*ret);
52 + ret = xmalloc(len);
53 + memset(ret, 0, sizeof(*ret));
54 + ptr = (char *)ret + sizeof(*ret);
55 if ((off_t)fread(ptr, 1, s.st_size, f) != s.st_size)
56 goto err;
57 ptr[s.st_size] = '\0';
58 @@ -954,15 +970,15 @@ static void
59 tree_read_file_binpkg_xpak_cb(
60 void *ctx,
61 char *pathname,
62 - int pathname_len,
63 - int data_offset,
64 - int data_len,
65 + int pathname_len,
66 + int data_offset,
67 + int data_len,
68 char *data)
69 {
70 tree_pkg_meta *m = (tree_pkg_meta *)ctx;
71 - char **key;
72 - size_t pos;
73 - size_t len;
74 + char **key;
75 + size_t pos;
76 + size_t len;
77
78 #define match_path(K) \
79 else if (pathname_len == (sizeof(#K) - 1) && strcmp(pathname, #K) == 0) \
80 @@ -994,37 +1010,28 @@ tree_read_file_binpkg_xpak_cb(
81 return;
82 #undef match_path
83
84 - /* hijack unused members */
85 - pos = (size_t)m->Q__eclasses_;
86 - len = (size_t)m->Q__md5_;
87 + /* get current storage block */
88 + if (m->storage != NULL) {
89 + pos = m->storage->pos;
90 + len = m->storage->len;
91 + } else {
92 + pos = 0;
93 + len = 0;
94 + }
95
96 /* trim whitespace (mostly trailing newline) */
97 while (isspace((int)data[data_offset + data_len - 1]))
98 data_len--;
99
100 if (len - pos < (size_t)(data_len + 1)) {
101 - char *old_data = m->Q__data;
102 - len += (((data_len + 1 - (len - pos)) / BUFSIZ) + 1) * BUFSIZ;
103 - m->Q__data = xrealloc(m->Q__data, len);
104 -
105 - /* re-position existing keys */
106 - if (old_data != NULL && m->Q__data != old_data) {
107 - char **newdata = (char **)m;
108 - int elems = sizeof(tree_pkg_meta) / sizeof(char *);
109 - while (elems-- > 1) /* skip Q__data itself */
110 - if (newdata[elems] != NULL)
111 - newdata[elems] = m->Q__data + (newdata[elems] - old_data);
112 - }
113 -
114 - /* set after repositioning! */
115 - m->Q__md5_ = (char *)len;
116 - m->Q__eclasses_ = (char *)pos;
117 + tree_meta_alloc_storage(m, data_len + 1);
118 + len = m->storage->len;
119 + pos = m->storage->pos;
120 }
121
122 - *key = m->Q__data + pos;
123 + *key = m->storage->ptr + pos;
124 snprintf(*key, len - pos, "%.*s", data_len, data + data_offset);
125 - pos += data_len + 1;
126 - m->Q__eclasses_ = (char *)pos;
127 + m->storage->pos += data_len + 1;
128 }
129
130 static tree_pkg_meta *
131 @@ -1042,33 +1049,23 @@ tree_read_file_binpkg(tree_pkg_ctx *pkg_ctx)
132 if (newfd != -1) {
133 size_t fsize;
134 size_t needlen = 40 + 1 + 19 + 1;
135 - size_t pos = (size_t)m->Q__eclasses_;
136 - size_t len = (size_t)m->Q__md5_;
137 + size_t pos = 0;
138 + size_t len = 0;
139
140 - if (len - pos < needlen) {
141 - char *old_data = m->Q__data;
142 - len += (((needlen - (len - pos)) / BUFSIZ) + 1) * BUFSIZ;
143 - m->Q__data = xrealloc(m->Q__data, len);
144 -
145 - /* re-position existing keys */
146 - if (old_data != NULL && m->Q__data != old_data) {
147 - char **newdata = (char **)m;
148 - int elems = sizeof(tree_pkg_meta) / sizeof(char *);
149 - while (elems-- > 1) /* skip Q__data itself */
150 - if (newdata[elems] != NULL)
151 - newdata[elems] =
152 - m->Q__data + (newdata[elems] - old_data);
153 - }
154 + if (m->storage != NULL) {
155 + pos = m->storage->pos;
156 + len = m->storage->len;
157 + }
158
159 - /* set after repositioning! */
160 - m->Q__md5_ = (char *)len;
161 - m->Q__eclasses_ = (char *)pos;
162 + if (len - pos < needlen) {
163 + tree_meta_alloc_storage(m, needlen);
164 + len = m->storage->len;
165 + pos = m->storage->pos;
166 }
167
168 - m->Q_SHA1 = m->Q__data + pos;
169 + m->Q_SHA1 = m->storage->ptr + pos;
170 m->Q_SIZE = m->Q_SHA1 + 40 + 1;
171 - pos += needlen;
172 - m->Q__eclasses_ = (char *)pos;
173 + m->storage->pos += needlen;
174
175 lseek(newfd, 0, SEEK_SET); /* reposition at the whole file */
176 if (hash_multiple_file_fd(newfd, NULL, m->Q_SHA1, NULL, NULL,
177 @@ -1123,13 +1120,48 @@ tree_pkg_read(tree_pkg_ctx *pkg_ctx)
178 return ret;
179 }
180
181 +static tree_pkg_meta *
182 +tree_clone_meta(tree_pkg_meta *m)
183 +{
184 + tree_pkg_meta *ret;
185 + size_t pos = 0;
186 + size_t len = 0;
187 + char **ptr;
188 + char *p;
189 +
190 + /* compute necessary space upfront */
191 + len = sizeof(*ret);
192 + for (ptr = &m->Q__data; ptr <= &m->Q__last; ptr++)
193 + if (*ptr != NULL)
194 + len += strlen(*ptr);
195 +
196 + /* malloc and copy */
197 + ret = xzalloc(len);
198 + p = (char *)ret + sizeof(*ret);
199 + for (ptr = &m->Q__data; ptr <= &m->Q__last; ptr++, pos++) {
200 + if (*ptr == NULL)
201 + continue;
202 + *(&ret->Q__data + pos) = p;
203 + len = strlen(*ptr) + 1;
204 + memcpy(p, *ptr, len);
205 + p += len;
206 + }
207 +
208 + return ret;
209 +}
210 +
211 static void
212 tree_close_meta(tree_pkg_meta *cache)
213 {
214 + struct tree_pkg_meta_ll *blk;
215 +
216 if (cache == NULL)
217 errf("Cache is empty !");
218 - if (cache->Q__data != NULL)
219 - free(cache->Q__data);
220 + while (cache->storage != NULL) {
221 + blk = cache->storage->next;
222 + free(cache->storage);
223 + cache->storage = blk;
224 + }
225 free(cache);
226 }
227
228 @@ -1165,37 +1197,26 @@ tree_pkg_meta_get_int(tree_pkg_ctx *pkg_ctx, size_t offset, const char *keyn)
229 return NULL;
230 }
231
232 - /* hijack unused members */
233 - pos = (size_t)m->Q__eclasses_;
234 - len = (size_t)m->Q__md5_;
235 + if (m->storage != NULL) {
236 + pos = m->storage->pos;
237 + len = m->storage->len;
238 + } else {
239 + pos = 0;
240 + len = 0;
241 + }
242
243 - /* TODO: this is an exact copy from tree_read_file_binpkg_xpak_cb */
244 if (len - pos < (size_t)(s.st_size + 1)) {
245 - p = m->Q__data;
246 - len += (((s.st_size + 1 - (len - pos)) / BUFSIZ) + 1) * BUFSIZ;
247 - m->Q__data = xrealloc(m->Q__data, len);
248 -
249 - /* re-position existing keys */
250 - if (p != NULL && m->Q__data != p) {
251 - char **newdata = (char **)m;
252 - int elems = sizeof(tree_pkg_meta) / sizeof(char *);
253 - while (elems-- > 1) /* skip Q__data itself */
254 - if (newdata[elems] != NULL)
255 - newdata[elems] = m->Q__data + (newdata[elems] - p);
256 - }
257 -
258 - /* set after repositioning! */
259 - m->Q__md5_ = (char *)len;
260 - m->Q__eclasses_ = (char *)pos;
261 + tree_meta_alloc_storage(m, s.st_size + 1);
262 + pos = m->storage->pos;
263 + len = m->storage->len;
264 }
265
266 - p = *key = m->Q__data + pos;
267 + p = *key = m->storage->ptr + pos;
268 if (read(fd, p, s.st_size) == (ssize_t)s.st_size) {
269 p[s.st_size] = '\0';
270 while (s.st_size > 0 && isspace((int)p[s.st_size - 1]))
271 p[--s.st_size] = '\0';
272 - pos += s.st_size + 1;
273 - m->Q__eclasses_ = (char *)pos;
274 + m->storage->pos += s.st_size + 1;
275 }
276 close(fd);
277 }
278 @@ -1692,29 +1713,14 @@ tree_match_atom_cache_populate_cb(tree_pkg_ctx *ctx, void *priv)
279 pkg->repo = tctx->repo != NULL ? xstrdup(tctx->repo) : NULL;
280 if (meta != NULL) {
281 pkg->fd = -2; /* don't try to read, we fill it in here */
282 - pkg->meta = xmalloc(sizeof(*pkg->meta));
283 - memcpy(pkg->meta, meta, sizeof(*pkg->meta));
284 - if (ctx->cat_ctx->ctx->cachetype == CACHE_PACKAGES) {
285 - pkg->meta->Q__data = NULL; /* avoid free here (just to be sure) */
286 - } else { /* CACHE_BINPKG */
287 - char **newdata;
288 - int elems;
289 - size_t datasize = (size_t)meta->Q__eclasses_;
290 -
291 - pkg->meta->Q__data = xmalloc(sizeof(char) * datasize);
292 - memcpy(pkg->meta->Q__data, meta->Q__data, datasize);
293 -
294 - /* re-position keys */
295 - newdata = (char **)pkg->meta;
296 - elems = sizeof(tree_pkg_meta) / sizeof(char *);
297 - while (elems-- > 1) /* skip Q__data itself */
298 - if (newdata[elems] != NULL)
299 - newdata[elems] = pkg->meta->Q__data +
300 - (newdata[elems] - meta->Q__data);
301 -
302 - /* drop garbage used for Q__data admin in original case */
303 - pkg->meta->Q__eclasses_ = NULL;
304 - pkg->meta->Q__md5_ = NULL;
305 + if (tctx->cachetype == CACHE_PACKAGES) {
306 + /* need to copy, source is based on temp space in foreach */
307 + pkg->meta = tree_clone_meta(meta);
308 + } else {
309 + /* BINPKG case, this one is read/allocated separately from
310 + * xpak archive, so can just take it over */
311 + pkg->meta = meta;
312 + ctx->meta = NULL; /* avoid double free */
313 }
314 } else {
315 pkg->meta = NULL;
316
317 diff --git a/libq/tree.h b/libq/tree.h
318 index 052715b..8279281 100644
319 --- a/libq/tree.h
320 +++ b/libq/tree.h
321 @@ -80,7 +80,7 @@ struct tree_pkg_ctx {
322
323 /* Ebuild data */
324 struct tree_pkg_meta {
325 - char *Q__data;
326 +#define Q__data Q_DEPEND /* ptr to first member of the struct */
327 char *Q_DEPEND; /* line 1 */
328 char *Q_RDEPEND;
329 char *Q_SLOT;
330 @@ -111,6 +111,15 @@ struct tree_pkg_meta {
331 /* These are MD5-Cache only */
332 char *Q__eclasses_;
333 char *Q__md5_;
334 +#define Q__last Q__md5_ /* ptr to last data member in struct */
335 +
336 + /* for memory allocations backing the pointers above */
337 + struct tree_pkg_meta_ll {
338 + char *ptr;
339 + size_t len;
340 + size_t pos;
341 + struct tree_pkg_meta_ll *next;
342 + } *storage;
343 };
344
345 /* Metadata.xml */