Skip to content

Commit 7c3d15f

Browse files
committed
Merge branch 'jk/snprintf-truncation'
Avoid unchecked snprintf() to make future code auditing easier. * jk/snprintf-truncation: fmt_with_err: add a comment that truncation is OK shorten_unambiguous_ref: use xsnprintf fsmonitor: use internal argv_array of struct child_process log_write_email_headers: use strbufs http: use strbufs instead of fixed buffers
2 parents b2fd659 + ac4896f commit 7c3d15f

File tree

6 files changed

+55
-50
lines changed

6 files changed

+55
-50
lines changed

fsmonitor.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,13 @@ void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
9797
static int query_fsmonitor(int version, uint64_t last_update, struct strbuf *query_result)
9898
{
9999
struct child_process cp = CHILD_PROCESS_INIT;
100-
char ver[64];
101-
char date[64];
102-
const char *argv[4];
103100

104-
if (!(argv[0] = core_fsmonitor))
101+
if (!core_fsmonitor)
105102
return -1;
106103

107-
snprintf(ver, sizeof(ver), "%d", version);
108-
snprintf(date, sizeof(date), "%" PRIuMAX, (uintmax_t)last_update);
109-
argv[1] = ver;
110-
argv[2] = date;
111-
argv[3] = NULL;
112-
cp.argv = argv;
104+
argv_array_push(&cp.args, core_fsmonitor);
105+
argv_array_pushf(&cp.args, "%d", version);
106+
argv_array_pushf(&cp.args, "%" PRIuMAX, (uintmax_t)last_update);
113107
cp.use_shell = 1;
114108
cp.dir = get_git_work_tree();
115109

http.c

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2083,6 +2083,7 @@ void release_http_pack_request(struct http_pack_request *preq)
20832083
preq->packfile = NULL;
20842084
}
20852085
preq->slot = NULL;
2086+
strbuf_release(&preq->tmpfile);
20862087
free(preq->url);
20872088
free(preq);
20882089
}
@@ -2105,27 +2106,27 @@ int finish_http_pack_request(struct http_pack_request *preq)
21052106
lst = &((*lst)->next);
21062107
*lst = (*lst)->next;
21072108

2108-
if (!strip_suffix(preq->tmpfile, ".pack.temp", &len))
2109+
if (!strip_suffix(preq->tmpfile.buf, ".pack.temp", &len))
21092110
BUG("pack tmpfile does not end in .pack.temp?");
2110-
tmp_idx = xstrfmt("%.*s.idx.temp", (int)len, preq->tmpfile);
2111+
tmp_idx = xstrfmt("%.*s.idx.temp", (int)len, preq->tmpfile.buf);
21112112

21122113
argv_array_push(&ip.args, "index-pack");
21132114
argv_array_pushl(&ip.args, "-o", tmp_idx, NULL);
2114-
argv_array_push(&ip.args, preq->tmpfile);
2115+
argv_array_push(&ip.args, preq->tmpfile.buf);
21152116
ip.git_cmd = 1;
21162117
ip.no_stdin = 1;
21172118
ip.no_stdout = 1;
21182119

21192120
if (run_command(&ip)) {
2120-
unlink(preq->tmpfile);
2121+
unlink(preq->tmpfile.buf);
21212122
unlink(tmp_idx);
21222123
free(tmp_idx);
21232124
return -1;
21242125
}
21252126

21262127
unlink(sha1_pack_index_name(p->sha1));
21272128

2128-
if (finalize_object_file(preq->tmpfile, sha1_pack_name(p->sha1))
2129+
if (finalize_object_file(preq->tmpfile.buf, sha1_pack_name(p->sha1))
21292130
|| finalize_object_file(tmp_idx, sha1_pack_index_name(p->sha1))) {
21302131
free(tmp_idx);
21312132
return -1;
@@ -2144,19 +2145,19 @@ struct http_pack_request *new_http_pack_request(
21442145
struct http_pack_request *preq;
21452146

21462147
preq = xcalloc(1, sizeof(*preq));
2148+
strbuf_init(&preq->tmpfile, 0);
21472149
preq->target = target;
21482150

21492151
end_url_with_slash(&buf, base_url);
21502152
strbuf_addf(&buf, "objects/pack/pack-%s.pack",
21512153
sha1_to_hex(target->sha1));
21522154
preq->url = strbuf_detach(&buf, NULL);
21532155

2154-
snprintf(preq->tmpfile, sizeof(preq->tmpfile), "%s.temp",
2155-
sha1_pack_name(target->sha1));
2156-
preq->packfile = fopen(preq->tmpfile, "a");
2156+
strbuf_addf(&preq->tmpfile, "%s.temp", sha1_pack_name(target->sha1));
2157+
preq->packfile = fopen(preq->tmpfile.buf, "a");
21572158
if (!preq->packfile) {
21582159
error("Unable to open local file %s for pack",
2159-
preq->tmpfile);
2160+
preq->tmpfile.buf);
21602161
goto abort;
21612162
}
21622163

@@ -2183,6 +2184,7 @@ struct http_pack_request *new_http_pack_request(
21832184
return preq;
21842185

21852186
abort:
2187+
strbuf_release(&preq->tmpfile);
21862188
free(preq->url);
21872189
free(preq);
21882190
return NULL;
@@ -2233,48 +2235,49 @@ struct http_object_request *new_http_object_request(const char *base_url,
22332235
{
22342236
char *hex = sha1_to_hex(sha1);
22352237
struct strbuf filename = STRBUF_INIT;
2236-
char prevfile[PATH_MAX];
2238+
struct strbuf prevfile = STRBUF_INIT;
22372239
int prevlocal;
22382240
char prev_buf[PREV_BUF_SIZE];
22392241
ssize_t prev_read = 0;
22402242
off_t prev_posn = 0;
22412243
struct http_object_request *freq;
22422244

22432245
freq = xcalloc(1, sizeof(*freq));
2246+
strbuf_init(&freq->tmpfile, 0);
22442247
hashcpy(freq->sha1, sha1);
22452248
freq->localfile = -1;
22462249

22472250
sha1_file_name(the_repository, &filename, sha1);
2248-
snprintf(freq->tmpfile, sizeof(freq->tmpfile),
2249-
"%s.temp", filename.buf);
2251+
strbuf_addf(&freq->tmpfile, "%s.temp", filename.buf);
22502252

2251-
snprintf(prevfile, sizeof(prevfile), "%s.prev", filename.buf);
2252-
unlink_or_warn(prevfile);
2253-
rename(freq->tmpfile, prevfile);
2254-
unlink_or_warn(freq->tmpfile);
2253+
strbuf_addf(&prevfile, "%s.prev", filename.buf);
2254+
unlink_or_warn(prevfile.buf);
2255+
rename(freq->tmpfile.buf, prevfile.buf);
2256+
unlink_or_warn(freq->tmpfile.buf);
22552257
strbuf_release(&filename);
22562258

22572259
if (freq->localfile != -1)
22582260
error("fd leakage in start: %d", freq->localfile);
2259-
freq->localfile = open(freq->tmpfile,
2261+
freq->localfile = open(freq->tmpfile.buf,
22602262
O_WRONLY | O_CREAT | O_EXCL, 0666);
22612263
/*
22622264
* This could have failed due to the "lazy directory creation";
22632265
* try to mkdir the last path component.
22642266
*/
22652267
if (freq->localfile < 0 && errno == ENOENT) {
2266-
char *dir = strrchr(freq->tmpfile, '/');
2268+
char *dir = strrchr(freq->tmpfile.buf, '/');
22672269
if (dir) {
22682270
*dir = 0;
2269-
mkdir(freq->tmpfile, 0777);
2271+
mkdir(freq->tmpfile.buf, 0777);
22702272
*dir = '/';
22712273
}
2272-
freq->localfile = open(freq->tmpfile,
2274+
freq->localfile = open(freq->tmpfile.buf,
22732275
O_WRONLY | O_CREAT | O_EXCL, 0666);
22742276
}
22752277

22762278
if (freq->localfile < 0) {
2277-
error_errno("Couldn't create temporary file %s", freq->tmpfile);
2279+
error_errno("Couldn't create temporary file %s",
2280+
freq->tmpfile.buf);
22782281
goto abort;
22792282
}
22802283

@@ -2288,7 +2291,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
22882291
* If a previous temp file is present, process what was already
22892292
* fetched.
22902293
*/
2291-
prevlocal = open(prevfile, O_RDONLY);
2294+
prevlocal = open(prevfile.buf, O_RDONLY);
22922295
if (prevlocal != -1) {
22932296
do {
22942297
prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE);
@@ -2305,7 +2308,8 @@ struct http_object_request *new_http_object_request(const char *base_url,
23052308
} while (prev_read > 0);
23062309
close(prevlocal);
23072310
}
2308-
unlink_or_warn(prevfile);
2311+
unlink_or_warn(prevfile.buf);
2312+
strbuf_release(&prevfile);
23092313

23102314
/*
23112315
* Reset inflate/SHA1 if there was an error reading the previous temp
@@ -2320,7 +2324,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
23202324
lseek(freq->localfile, 0, SEEK_SET);
23212325
if (ftruncate(freq->localfile, 0) < 0) {
23222326
error_errno("Couldn't truncate temporary file %s",
2323-
freq->tmpfile);
2327+
freq->tmpfile.buf);
23242328
goto abort;
23252329
}
23262330
}
@@ -2350,6 +2354,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
23502354
return freq;
23512355

23522356
abort:
2357+
strbuf_release(&prevfile);
23532358
free(freq->url);
23542359
free(freq);
23552360
return NULL;
@@ -2377,32 +2382,32 @@ int finish_http_object_request(struct http_object_request *freq)
23772382
if (freq->http_code == 416) {
23782383
warning("requested range invalid; we may already have all the data.");
23792384
} else if (freq->curl_result != CURLE_OK) {
2380-
if (stat(freq->tmpfile, &st) == 0)
2385+
if (stat(freq->tmpfile.buf, &st) == 0)
23812386
if (st.st_size == 0)
2382-
unlink_or_warn(freq->tmpfile);
2387+
unlink_or_warn(freq->tmpfile.buf);
23832388
return -1;
23842389
}
23852390

23862391
git_inflate_end(&freq->stream);
23872392
git_SHA1_Final(freq->real_sha1, &freq->c);
23882393
if (freq->zret != Z_STREAM_END) {
2389-
unlink_or_warn(freq->tmpfile);
2394+
unlink_or_warn(freq->tmpfile.buf);
23902395
return -1;
23912396
}
23922397
if (hashcmp(freq->sha1, freq->real_sha1)) {
2393-
unlink_or_warn(freq->tmpfile);
2398+
unlink_or_warn(freq->tmpfile.buf);
23942399
return -1;
23952400
}
23962401
sha1_file_name(the_repository, &filename, freq->sha1);
2397-
freq->rename = finalize_object_file(freq->tmpfile, filename.buf);
2402+
freq->rename = finalize_object_file(freq->tmpfile.buf, filename.buf);
23982403
strbuf_release(&filename);
23992404

24002405
return freq->rename;
24012406
}
24022407

24032408
void abort_http_object_request(struct http_object_request *freq)
24042409
{
2405-
unlink_or_warn(freq->tmpfile);
2410+
unlink_or_warn(freq->tmpfile.buf);
24062411

24072412
release_http_object_request(freq);
24082413
}
@@ -2422,4 +2427,5 @@ void release_http_object_request(struct http_object_request *freq)
24222427
release_active_slot(freq->slot);
24232428
freq->slot = NULL;
24242429
}
2430+
strbuf_release(&freq->tmpfile);
24252431
}

http.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ struct http_pack_request {
207207
struct packed_git *target;
208208
struct packed_git **lst;
209209
FILE *packfile;
210-
char tmpfile[PATH_MAX];
210+
struct strbuf tmpfile;
211211
struct active_request_slot *slot;
212212
};
213213

@@ -219,7 +219,7 @@ extern void release_http_pack_request(struct http_pack_request *preq);
219219
/* Helpers for fetching object */
220220
struct http_object_request {
221221
char *url;
222-
char tmpfile[PATH_MAX];
222+
struct strbuf tmpfile;
223223
int localfile;
224224
CURLcode curl_result;
225225
char errorstr[CURL_ERROR_SIZE];

log-tree.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -387,11 +387,15 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
387387
graph_show_oneline(opt->graph);
388388
}
389389
if (opt->mime_boundary && maybe_multipart) {
390-
static char subject_buffer[1024];
391-
static char buffer[1024];
390+
static struct strbuf subject_buffer = STRBUF_INIT;
391+
static struct strbuf buffer = STRBUF_INIT;
392392
struct strbuf filename = STRBUF_INIT;
393393
*need_8bit_cte_p = -1; /* NEVER */
394-
snprintf(subject_buffer, sizeof(subject_buffer) - 1,
394+
395+
strbuf_reset(&subject_buffer);
396+
strbuf_reset(&buffer);
397+
398+
strbuf_addf(&subject_buffer,
395399
"%s"
396400
"MIME-Version: 1.0\n"
397401
"Content-Type: multipart/mixed;"
@@ -406,13 +410,13 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
406410
extra_headers ? extra_headers : "",
407411
mime_boundary_leader, opt->mime_boundary,
408412
mime_boundary_leader, opt->mime_boundary);
409-
extra_headers = subject_buffer;
413+
extra_headers = subject_buffer.buf;
410414

411415
if (opt->numbered_files)
412416
strbuf_addf(&filename, "%d", opt->nr);
413417
else
414418
fmt_output_commit(&filename, commit, opt);
415-
snprintf(buffer, sizeof(buffer) - 1,
419+
strbuf_addf(&buffer,
416420
"\n--%s%s\n"
417421
"Content-Type: text/x-patch;"
418422
" name=\"%s\"\n"
@@ -423,7 +427,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
423427
filename.buf,
424428
opt->no_inline ? "attachment" : "inline",
425429
filename.buf);
426-
opt->diffopt.stat_sep = buffer;
430+
opt->diffopt.stat_sep = buffer.buf;
427431
strbuf_release(&filename);
428432
}
429433
*extra_headers_p = extra_headers;

refs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,8 +1162,8 @@ char *shorten_unambiguous_ref(const char *refname, int strict)
11621162
for (i = 0; i < nr_rules; i++) {
11631163
assert(offset < total_len);
11641164
scanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset;
1165-
offset += snprintf(scanf_fmts[i], total_len - offset,
1166-
ref_rev_parse_rules[i], 2, "%s") + 1;
1165+
offset += xsnprintf(scanf_fmts[i], total_len - offset,
1166+
ref_rev_parse_rules[i], 2, "%s") + 1;
11671167
}
11681168
}
11691169

usage.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ static const char *fmt_with_err(char *buf, int n, const char *fmt)
148148
}
149149
}
150150
str_error[j] = 0;
151+
/* Truncation is acceptable here */
151152
snprintf(buf, n, "%s: %s", fmt, str_error);
152153
return buf;
153154
}

0 commit comments

Comments
 (0)