commit:     4fbeb8ccca1b93da4987b0d58aba24c0901e898d
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sun Jun  7 10:39:40 2020 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sun Jun  7 10:39:40 2020 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=4fbeb8cc

libq/tree: fix metadata cache after realloc

A realloc caused a relocation of pointers, which also changed the value
of Q__md5_ and Q__eclasses_ which are secretly used to store len and
pos, so make sure we reset them to correct values after a relocation
takes place.

While at it, reduce the allocation requirements by only considering the
really needed space (over-allocate less here).

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 libq/tree.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/libq/tree.c b/libq/tree.c
index d8d238c..ad8db47 100644
--- a/libq/tree.c
+++ b/libq/tree.c
@@ -957,9 +957,8 @@ tree_read_file_binpkg_xpak_cb(
 
        if (len - pos < (size_t)(data_len + 1)) {
                char *old_data = m->Q__data;
-               len += (((data_len + 1) / BUFSIZ) + 1) * BUFSIZ;
+               len += (((data_len + 1 - (len - pos)) / BUFSIZ) + 1) * BUFSIZ;
                m->Q__data = xrealloc(m->Q__data, len);
-               m->Q__md5_ = (char *)len;
 
                /* re-position existing keys */
                if (old_data != NULL && m->Q__data != old_data) {
@@ -969,6 +968,10 @@ tree_read_file_binpkg_xpak_cb(
                                if (newdata[elems] != NULL)
                                        newdata[elems] = m->Q__data + 
(newdata[elems] - old_data);
                }
+
+               /* set after repositioning! */
+               m->Q__md5_ = (char *)len;
+               m->Q__eclasses_ = (char *)pos;
        }
 
        *key = m->Q__data + pos;
@@ -997,9 +1000,8 @@ tree_read_file_binpkg(tree_pkg_ctx *pkg_ctx)
 
                if (len - pos < needlen) {
                        char *old_data = m->Q__data;
-                       len += ((needlen / BUFSIZ) + 1) * BUFSIZ;
+                       len += (((needlen - (len - pos)) / BUFSIZ) + 1) * 
BUFSIZ;
                        m->Q__data = xrealloc(m->Q__data, len);
-                       m->Q__md5_ = (char *)len;
 
                        /* re-position existing keys */
                        if (old_data != NULL && m->Q__data != old_data) {
@@ -1010,6 +1012,10 @@ tree_read_file_binpkg(tree_pkg_ctx *pkg_ctx)
                                                newdata[elems] =
                                                        m->Q__data + 
(newdata[elems] - old_data);
                        }
+
+                       /* set after repositioning! */
+                       m->Q__md5_ = (char *)len;
+                       m->Q__eclasses_ = (char *)pos;
                }
 
                m->Q_SHA1 = m->Q__data + pos;
@@ -1112,9 +1118,8 @@ tree_pkg_meta_get_int(tree_pkg_ctx *pkg_ctx, size_t 
offset, const char *keyn)
                        /* TODO: this is an exact copy from 
tree_read_file_binpkg_xpak_cb */
                        if (len - pos < (size_t)(s.st_size + 1)) {
                                p = m->Q__data;
-                               len += (((s.st_size + 1) / BUFSIZ) + 1) * 
BUFSIZ;
+                               len += (((s.st_size + 1 - (len - pos)) / 
BUFSIZ) + 1) * BUFSIZ;
                                m->Q__data = xrealloc(m->Q__data, len);
-                               m->Q__md5_ = (char *)len;
 
                                /* re-position existing keys */
                                if (p != NULL && m->Q__data != p) {
@@ -1124,6 +1129,10 @@ tree_pkg_meta_get_int(tree_pkg_ctx *pkg_ctx, size_t 
offset, const char *keyn)
                                                if (newdata[elems] != NULL)
                                                        newdata[elems] = 
m->Q__data + (newdata[elems] - p);
                                }
+
+                               /* set after repositioning! */
+                               m->Q__md5_ = (char *)len;
+                               m->Q__eclasses_ = (char *)pos;
                        }
 
                        p = *key = m->Q__data + pos;

Reply via email to