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: /
Date: Sat, 12 Oct 2019 12:47:53
Message-Id: 1570884199.b9eca954b9f0518916f390039b43eff46f0ee67e.grobian@gentoo
1 commit: b9eca954b9f0518916f390039b43eff46f0ee67e
2 Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
3 AuthorDate: Sat Oct 12 12:43:19 2019 +0000
4 Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
5 CommitDate: Sat Oct 12 12:43:19 2019 +0000
6 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=b9eca954
7
8 qfile: fix matching of full paths, bug #697094
9
10 - properly handle trailing slashes, this is necessary because we use a
11 custom basename that doesn't strip it
12 - fix bug in creating realpath of dirname, resulting in one path
13 component short
14 - cleanup some match conditions
15
16 Bug: https://bugs.gentoo.org/697094
17 Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
18
19 qfile.c | 72 ++++++++++++++++++++++++++++++++---------------------------------
20 1 file changed, 36 insertions(+), 36 deletions(-)
21
22 diff --git a/qfile.c b/qfile.c
23 index 63b47da..8fa6eb4 100644
24 --- a/qfile.c
25 +++ b/qfile.c
26 @@ -171,6 +171,7 @@ static int qfile_cb(tree_pkg_ctx *pkg_ctx, void *priv)
27 short *non_orphans = args->non_orphans;
28 int *results = args->results;
29 int found = 0;
30 + size_t len;
31
32 /* If exclude_pkg is not NULL, check it. We are looking for files
33 * collisions, and must exclude one package. */
34 @@ -223,23 +224,22 @@ static int qfile_cb(tree_pkg_ctx *pkg_ctx, void *priv)
35 if (non_orphans != NULL && non_orphans[i])
36 continue;
37
38 - /* For optimization of qfile(), we also give it an array of
39 - * the first char of each basename. This way we avoid
40 - * numerous strcmp() calls. */
41 + /* Try to avoid numerous strcmp() calls. */
42 if (base[0] != base_names[i][0] || strcmp(base, base_names[i]) != 0)
43 continue;
44
45 path_ok = false;
46
47 - if (dir_names[i] &&
48 - strncmp(e->name, dir_names[i], dirname_len) == 0 &&
49 - dir_names[i][dirname_len] == '\0')
50 + if (dir_names[i] && (len = strlen(dir_names[i])) > 0 &&
51 + len == dirname_len &&
52 + memcmp(e->name, dir_names[i], len) == 0)
53 {
54 /* dir_name == dirname(CONTENTS) */
55 path_ok = true;
56 } else if (real_dir_names[i] &&
57 - strncmp(e->name, real_dir_names[i], dirname_len) == 0 &&
58 - real_dir_names[i][dirname_len] == '\0')
59 + (len = strlen(real_dir_names[i])) > 0 &&
60 + len == dirname_len &&
61 + memcmp(e->name, real_dir_names[i], len) == 0)
62 {
63 /* real_dir_name == dirname(CONTENTS) */
64 path_ok = true;
65 @@ -276,19 +276,19 @@ static int qfile_cb(tree_pkg_ctx *pkg_ctx, void *priv)
66 }
67 }
68
69 - if (!path_ok && state->basename) {
70 + if (!path_ok && state->basename)
71 path_ok = true;
72 - }
73
74 if (!path_ok && state->pwd && dir_names[i] == NULL) {
75 /* try to match file in current directory */
76 - if (strncmp(e->name, state->pwd, dirname_len) == 0 &&
77 - state->pwd[dirname_len] == '\0')
78 + if ((len = strlen(state->pwd)) > 0 &&
79 + len == dirname_len &&
80 + memcmp(e->name, state->pwd, len) == 0)
81 path_ok = true;
82 }
83
84 if (!path_ok && dir_names[i] == NULL && real_dir_names[i] == NULL) {
85 - /* try basename match */
86 + /* basename match */
87 if (e->type != CONTENTS_DIR)
88 path_ok = true;
89 }
90 @@ -357,7 +357,7 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st
91 char **realdirnames = NULL;
92 int *results = NULL;
93 char tmppath[_Q_PATH_MAX];
94 - char abspath[_Q_PATH_MAX];
95 + char abspath[_Q_PATH_MAX * 2];
96
97 /* For each argument, we store its basename, its absolute dirname,
98 * and the realpath of its dirname. Dirnames and their realpaths
99 @@ -370,11 +370,15 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st
100 results = xcalloc(argc, sizeof(int));
101
102 for (i = 0; i < argc; ++i) {
103 - /* Record basename, but if it is ".", ".." or "/" */
104 - /* copy so that "argv" can be "const" */
105 - snprintf(tmppath, sizeof(tmppath), "%s", argv[i]);
106 + /* copy so that "argv" can be "const", but skip trailing /
107 + * because our basename doesn't modify its input */
108 + len = strlen(argv[i]);
109 + if (len > 1 && argv[i][len - 1] == '/')
110 + len--;
111 + snprintf(tmppath, sizeof(tmppath), "%.*s", (int)len, argv[i]);
112 p = basename(tmppath);
113 - len = strlen(p);
114 +
115 + /* record basename, but if it is ".", ".." or "/" */
116 if ((len > 2) ||
117 (strncmp(tmppath, "..", len) != 0 &&
118 strncmp(tmppath, "/", len) != 0))
119 @@ -388,15 +392,15 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st
120
121 /* Make sure we have an absolute path available (with
122 * "realpath(ROOT)" prefix) */
123 - if (argv[i][0] == '/') {
124 + if (tmppath[0] == '/') {
125 snprintf(abspath, sizeof(abspath), "%s%s",
126 - state->assume_root_prefix ? "" : real_root, argv[i]);
127 + state->assume_root_prefix ? "" : real_root, tmppath);
128 } else if (pwd) {
129 if (state->assume_root_prefix)
130 - snprintf(abspath, sizeof(abspath), "%s/%s", pwd, argv[i]);
131 + snprintf(abspath, sizeof(abspath), "%s/%s", pwd, tmppath);
132 else
133 snprintf(abspath, sizeof(abspath), "%s%s/%s",
134 - real_root, pwd, argv[i]);
135 + real_root, pwd, tmppath);
136 } else {
137 warn("$PWD was not found in environment, "
138 "or is not an absolute path");
139 @@ -424,11 +428,8 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st
140 tmppath, abspath);
141 goto skip_query_item;
142 }
143 - snprintf(tmppath, sizeof(tmppath), "%s%s",
144 - dirname(abspath),
145 - abspath[real_root_len] == '\0' ? "/" : "");
146 - if (strcmp(dirnames[i], tmppath + real_root_len))
147 - realdirnames[i] = xstrdup(tmppath + real_root_len);
148 + if (strcmp(dirnames[i], abspath + real_root_len))
149 + realdirnames[i] = xstrdup(abspath + real_root_len);
150 } else {
151 /* No basename means we are looking for something like "/foo/bar/.."
152 * Dirname is meaningless here, we can only get realpath of the full
153 @@ -442,8 +443,7 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st
154 abspath, tmppath);
155 goto skip_query_item;
156 }
157 - snprintf(abspath, sizeof(abspath), "%s", tmppath);
158 - basenames[i] = xstrdup(basename(abspath));
159 + basenames[i] = xstrdup(basename(tmppath));
160 snprintf(abspath, sizeof(abspath), "%s%s",
161 dirname(tmppath),
162 tmppath[real_root_len] == '\0' ? "/" : "");
163 @@ -451,13 +451,13 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st
164 }
165 continue;
166
167 - skip_query_item:
168 - --nb_of_queries;
169 - warn("Skipping query item \"%s\".", argv[i]);
170 - free(basenames[i]);
171 - free(dirnames[i]);
172 - free(realdirnames[i]);
173 - basenames[i] = dirnames[i] = realdirnames[i] = NULL;
174 + skip_query_item:
175 + --nb_of_queries;
176 + warn("Skipping query item \"%s\".", argv[i]);
177 + free(basenames[i]);
178 + free(dirnames[i]);
179 + free(realdirnames[i]);
180 + basenames[i] = dirnames[i] = realdirnames[i] = NULL;
181 }
182
183 args->basenames = basenames;