Skip to content

Commit 02e8ca0

Browse files
mhaggerpeff
authored andcommitted
parse_dirstat_params(): use string_list to split comma-separated string
Use string_list_split_in_place() to split the comma-separated parameters string. This simplifies the code and also fixes a bug: the old code made calls like memcmp(p, "lines", p_len) which needn't work if p_len is different than the length of the constant string (and could illegally access memory if p_len is larger than the length of the constant string). When p_len was less than the length of the constant string, the old code would have allowed some abbreviations to be accepted (e.g., "cha" for "changes") but this seems to have been a bug rather than a feature, because (1) it is not documented; (2) no attempt was made to handle ambiguous abbreviations, like "c" for "changes" vs "cumulative". Signed-off-by: Michael Haggerty <[email protected]> Signed-off-by: Jeff King <[email protected]>
1 parent 7e20105 commit 02e8ca0

File tree

1 file changed

+21
-19
lines changed

1 file changed

+21
-19
lines changed

diff.c

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "sigchain.h"
1616
#include "submodule.h"
1717
#include "ll-merge.h"
18+
#include "string-list.h"
1819

1920
#ifdef NO_FAST_WORKING_DIRECTORY
2021
#define FAST_WORKING_DIRECTORY 0
@@ -68,26 +69,30 @@ static int parse_diff_color_slot(const char *var, int ofs)
6869
return -1;
6970
}
7071

71-
static int parse_dirstat_params(struct diff_options *options, const char *params,
72+
static int parse_dirstat_params(struct diff_options *options, const char *params_string,
7273
struct strbuf *errmsg)
7374
{
74-
const char *p = params;
75-
int p_len, ret = 0;
75+
char *params_copy = xstrdup(params_string);
76+
struct string_list params = STRING_LIST_INIT_NODUP;
77+
int ret = 0;
78+
int i;
7679

77-
while (*p) {
78-
p_len = strchrnul(p, ',') - p;
79-
if (!memcmp(p, "changes", p_len)) {
80+
if (*params_copy)
81+
string_list_split_in_place(&params, params_copy, ',', -1);
82+
for (i = 0; i < params.nr; i++) {
83+
const char *p = params.items[i].string;
84+
if (!strcmp(p, "changes")) {
8085
DIFF_OPT_CLR(options, DIRSTAT_BY_LINE);
8186
DIFF_OPT_CLR(options, DIRSTAT_BY_FILE);
82-
} else if (!memcmp(p, "lines", p_len)) {
87+
} else if (!strcmp(p, "lines")) {
8388
DIFF_OPT_SET(options, DIRSTAT_BY_LINE);
8489
DIFF_OPT_CLR(options, DIRSTAT_BY_FILE);
85-
} else if (!memcmp(p, "files", p_len)) {
90+
} else if (!strcmp(p, "files")) {
8691
DIFF_OPT_CLR(options, DIRSTAT_BY_LINE);
8792
DIFF_OPT_SET(options, DIRSTAT_BY_FILE);
88-
} else if (!memcmp(p, "noncumulative", p_len)) {
93+
} else if (!strcmp(p, "noncumulative")) {
8994
DIFF_OPT_CLR(options, DIRSTAT_CUMULATIVE);
90-
} else if (!memcmp(p, "cumulative", p_len)) {
95+
} else if (!strcmp(p, "cumulative")) {
9196
DIFF_OPT_SET(options, DIRSTAT_CUMULATIVE);
9297
} else if (isdigit(*p)) {
9398
char *end;
@@ -99,24 +104,21 @@ static int parse_dirstat_params(struct diff_options *options, const char *params
99104
while (isdigit(*++end))
100105
; /* nothing */
101106
}
102-
if (end - p == p_len)
107+
if (!*end)
103108
options->dirstat_permille = permille;
104109
else {
105-
strbuf_addf(errmsg, _(" Failed to parse dirstat cut-off percentage '%.*s'\n"),
106-
p_len, p);
110+
strbuf_addf(errmsg, _(" Failed to parse dirstat cut-off percentage '%s'\n"),
111+
p);
107112
ret++;
108113
}
109114
} else {
110-
strbuf_addf(errmsg, _(" Unknown dirstat parameter '%.*s'\n"),
111-
p_len, p);
115+
strbuf_addf(errmsg, _(" Unknown dirstat parameter '%s'\n"), p);
112116
ret++;
113117
}
114118

115-
p += p_len;
116-
117-
if (*p)
118-
p++; /* more parameters, swallow separator */
119119
}
120+
string_list_clear(&params, 0);
121+
free(params_copy);
120122
return ret;
121123
}
122124

0 commit comments

Comments
 (0)