Skip to content

Commit 662384c

Browse files
committed
Merge branch 'rs/pickaxe'
* rs/pickaxe: pickaxe: factor out pickaxe pickaxe: give diff_grep the same signature as has_changes pickaxe: pass diff_options to contains and has_changes pickaxe: factor out has_changes pickaxe: plug regex/kws leak pickaxe: plug regex leak pickaxe: plug diff filespec leak with empty needle
2 parents 541b9cf + 8a94151 commit 662384c

File tree

1 file changed

+70
-108
lines changed

1 file changed

+70
-108
lines changed

diffcore-pickaxe.c

Lines changed: 70 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,46 @@
88
#include "xdiff-interface.h"
99
#include "kwset.h"
1010

11+
typedef int (*pickaxe_fn)(struct diff_filepair *p, struct diff_options *o, regex_t *regexp, kwset_t kws);
12+
13+
static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
14+
regex_t *regexp, kwset_t kws, pickaxe_fn fn)
15+
{
16+
int i;
17+
struct diff_queue_struct outq;
18+
19+
DIFF_QUEUE_CLEAR(&outq);
20+
21+
if (o->pickaxe_opts & DIFF_PICKAXE_ALL) {
22+
/* Showing the whole changeset if needle exists */
23+
for (i = 0; i < q->nr; i++) {
24+
struct diff_filepair *p = q->queue[i];
25+
if (fn(p, o, regexp, kws))
26+
return; /* do not munge the queue */
27+
}
28+
29+
/*
30+
* Otherwise we will clear the whole queue by copying
31+
* the empty outq at the end of this function, but
32+
* first clear the current entries in the queue.
33+
*/
34+
for (i = 0; i < q->nr; i++)
35+
diff_free_filepair(q->queue[i]);
36+
} else {
37+
/* Showing only the filepairs that has the needle */
38+
for (i = 0; i < q->nr; i++) {
39+
struct diff_filepair *p = q->queue[i];
40+
if (fn(p, o, regexp, kws))
41+
diff_q(&outq, p);
42+
else
43+
diff_free_filepair(p);
44+
}
45+
}
46+
47+
free(q->queue);
48+
*q = outq;
49+
}
50+
1151
struct diffgrep_cb {
1252
regex_t *regexp;
1353
int hit;
@@ -45,7 +85,8 @@ static void fill_one(struct diff_filespec *one,
4585
}
4686
}
4787

48-
static int diff_grep(struct diff_filepair *p, regex_t *regexp, struct diff_options *o)
88+
static int diff_grep(struct diff_filepair *p, struct diff_options *o,
89+
regex_t *regexp, kwset_t kws)
4990
{
5091
regmatch_t regmatch;
5192
struct userdiff_driver *textconv_one = NULL;
@@ -95,12 +136,8 @@ static int diff_grep(struct diff_filepair *p, regex_t *regexp, struct diff_optio
95136

96137
static void diffcore_pickaxe_grep(struct diff_options *o)
97138
{
98-
struct diff_queue_struct *q = &diff_queued_diff;
99-
int i, has_changes, err;
139+
int err;
100140
regex_t regex;
101-
struct diff_queue_struct outq;
102-
outq.queue = NULL;
103-
outq.nr = outq.alloc = 0;
104141

105142
err = regcomp(&regex, o->pickaxe, REG_EXTENDED | REG_NEWLINE);
106143
if (err) {
@@ -110,51 +147,21 @@ static void diffcore_pickaxe_grep(struct diff_options *o)
110147
die("invalid log-grep regex: %s", errbuf);
111148
}
112149

113-
if (o->pickaxe_opts & DIFF_PICKAXE_ALL) {
114-
/* Showing the whole changeset if needle exists */
115-
for (i = has_changes = 0; !has_changes && i < q->nr; i++) {
116-
struct diff_filepair *p = q->queue[i];
117-
if (diff_grep(p, &regex, o))
118-
has_changes++;
119-
}
120-
if (has_changes)
121-
return; /* do not munge the queue */
122-
123-
/*
124-
* Otherwise we will clear the whole queue by copying
125-
* the empty outq at the end of this function, but
126-
* first clear the current entries in the queue.
127-
*/
128-
for (i = 0; i < q->nr; i++)
129-
diff_free_filepair(q->queue[i]);
130-
} else {
131-
/* Showing only the filepairs that has the needle */
132-
for (i = 0; i < q->nr; i++) {
133-
struct diff_filepair *p = q->queue[i];
134-
if (diff_grep(p, &regex, o))
135-
diff_q(&outq, p);
136-
else
137-
diff_free_filepair(p);
138-
}
139-
}
150+
pickaxe(&diff_queued_diff, o, &regex, NULL, diff_grep);
140151

141152
regfree(&regex);
142-
143-
free(q->queue);
144-
*q = outq;
145153
return;
146154
}
147155

148-
static unsigned int contains(struct diff_filespec *one,
149-
const char *needle, unsigned long len,
156+
static unsigned int contains(struct diff_filespec *one, struct diff_options *o,
150157
regex_t *regexp, kwset_t kws)
151158
{
152159
unsigned int cnt;
153160
unsigned long sz;
154161
const char *data;
155-
if (diff_populate_filespec(one, 0))
162+
if (!o->pickaxe[0])
156163
return 0;
157-
if (!len)
164+
if (diff_populate_filespec(one, 0))
158165
return 0;
159166

160167
sz = one->size;
@@ -176,32 +183,47 @@ static unsigned int contains(struct diff_filespec *one,
176183

177184
} else { /* Classic exact string match */
178185
while (sz) {
179-
size_t offset = kwsexec(kws, data, sz, NULL);
186+
struct kwsmatch kwsm;
187+
size_t offset = kwsexec(kws, data, sz, &kwsm);
180188
const char *found;
181189
if (offset == -1)
182190
break;
183191
else
184192
found = data + offset;
185-
sz -= found - data + len;
186-
data = found + len;
193+
sz -= found - data + kwsm.size[0];
194+
data = found + kwsm.size[0];
187195
cnt++;
188196
}
189197
}
190198
diff_free_filespec_data(one);
191199
return cnt;
192200
}
193201

202+
static int has_changes(struct diff_filepair *p, struct diff_options *o,
203+
regex_t *regexp, kwset_t kws)
204+
{
205+
if (!DIFF_FILE_VALID(p->one)) {
206+
if (!DIFF_FILE_VALID(p->two))
207+
return 0; /* ignore unmerged */
208+
/* created */
209+
return contains(p->two, o, regexp, kws) != 0;
210+
}
211+
if (!DIFF_FILE_VALID(p->two))
212+
return contains(p->one, o, regexp, kws) != 0;
213+
if (!diff_unmodified_pair(p)) {
214+
return contains(p->one, o, regexp, kws) !=
215+
contains(p->two, o, regexp, kws);
216+
}
217+
return 0;
218+
}
219+
194220
static void diffcore_pickaxe_count(struct diff_options *o)
195221
{
196222
const char *needle = o->pickaxe;
197223
int opts = o->pickaxe_opts;
198-
struct diff_queue_struct *q = &diff_queued_diff;
199224
unsigned long len = strlen(needle);
200-
int i, has_changes;
201225
regex_t regex, *regexp = NULL;
202226
kwset_t kws = NULL;
203-
struct diff_queue_struct outq;
204-
DIFF_QUEUE_CLEAR(&outq);
205227

206228
if (opts & DIFF_PICKAXE_REGEX) {
207229
int err;
@@ -220,72 +242,12 @@ static void diffcore_pickaxe_count(struct diff_options *o)
220242
kwsprep(kws);
221243
}
222244

223-
if (opts & DIFF_PICKAXE_ALL) {
224-
/* Showing the whole changeset if needle exists */
225-
for (i = has_changes = 0; !has_changes && i < q->nr; i++) {
226-
struct diff_filepair *p = q->queue[i];
227-
if (!DIFF_FILE_VALID(p->one)) {
228-
if (!DIFF_FILE_VALID(p->two))
229-
continue; /* ignore unmerged */
230-
/* created */
231-
if (contains(p->two, needle, len, regexp, kws))
232-
has_changes++;
233-
}
234-
else if (!DIFF_FILE_VALID(p->two)) {
235-
if (contains(p->one, needle, len, regexp, kws))
236-
has_changes++;
237-
}
238-
else if (!diff_unmodified_pair(p) &&
239-
contains(p->one, needle, len, regexp, kws) !=
240-
contains(p->two, needle, len, regexp, kws))
241-
has_changes++;
242-
}
243-
if (has_changes)
244-
return; /* not munge the queue */
245-
246-
/* otherwise we will clear the whole queue
247-
* by copying the empty outq at the end of this
248-
* function, but first clear the current entries
249-
* in the queue.
250-
*/
251-
for (i = 0; i < q->nr; i++)
252-
diff_free_filepair(q->queue[i]);
253-
}
254-
else
255-
/* Showing only the filepairs that has the needle */
256-
for (i = 0; i < q->nr; i++) {
257-
struct diff_filepair *p = q->queue[i];
258-
has_changes = 0;
259-
if (!DIFF_FILE_VALID(p->one)) {
260-
if (!DIFF_FILE_VALID(p->two))
261-
; /* ignore unmerged */
262-
/* created */
263-
else if (contains(p->two, needle, len, regexp,
264-
kws))
265-
has_changes = 1;
266-
}
267-
else if (!DIFF_FILE_VALID(p->two)) {
268-
if (contains(p->one, needle, len, regexp, kws))
269-
has_changes = 1;
270-
}
271-
else if (!diff_unmodified_pair(p) &&
272-
contains(p->one, needle, len, regexp, kws) !=
273-
contains(p->two, needle, len, regexp, kws))
274-
has_changes = 1;
275-
276-
if (has_changes)
277-
diff_q(&outq, p);
278-
else
279-
diff_free_filepair(p);
280-
}
245+
pickaxe(&diff_queued_diff, o, regexp, kws, has_changes);
281246

282247
if (opts & DIFF_PICKAXE_REGEX)
283248
regfree(&regex);
284249
else
285250
kwsfree(kws);
286-
287-
free(q->queue);
288-
*q = outq;
289251
return;
290252
}
291253

0 commit comments

Comments
 (0)