convert trivial sprintf / strcpy calls to xsnprintf
We sometimes sprintf into fixed-size buffers when we know that the buffer is large enough to fit the input (either because it's a constant, or because it's numeric input that is bounded in size). Likewise with strcpy of constant strings. However, these sites make it hard to audit sprintf and strcpy calls for buffer overflows, as a reader has to cross-reference the size of the array with the input. Let's use xsnprintf instead, which communicates to a reader that we don't expect this to overflow (and catches the mistake in case we do). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Sep 24, 2015 at 17:06 UTC
5096d4909f9b13c7a650d9dbb7c9702ea7413566
20 files changed
+52
-47
archive-tar.c
+1
-1
@@ -301,7 +301,7 @@ static int write_global_extended_header(struct archiver_args *args)
301
memset(&header, 0, sizeof(header));
302
*header.typeflag = TYPEFLAG_GLOBAL_HEADER;
303
mode = 0100666;
304
- strcpy(header.name, "pax_global_header");
304
+ xsnprintf(header.name, sizeof(header.name), "pax_global_header");
305
prepare_header(args, &header, mode, ext_header.len);
306
write_blocked(&header, sizeof(header));
307
write_blocked(ext_header.buf, ext_header.len);
builtin/gc.c
+1
-1
@@ -194,7 +194,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
194
return NULL;
195
196
if (gethostname(my_host, sizeof(my_host)))
197
- strcpy(my_host, "unknown");
197
+ xsnprintf(my_host, sizeof(my_host), "unknown");
198
199
pidfile_path = git_pathdup("gc.pid");
200
fd = hold_lock_file_for_update(&lock, pidfile_path,
builtin/init-db.c
+6
-5
@@ -262,7 +262,8 @@ static int create_default_files(const char *template_path)
262
}
263
264
/* This forces creation of new config file */
265
- sprintf(repo_version_string, "%d", GIT_REPO_VERSION);
265
+ xsnprintf(repo_version_string, sizeof(repo_version_string),
266
+ "%d", GIT_REPO_VERSION);
267
git_config_set("core.repositoryformatversion", repo_version_string);
268
269
path[len] = 0;
@@ -414,13 +415,13 @@ int init_db(const char *template_dir, unsigned int flags)
415
*/
416
if (shared_repository < 0)
417
/* force to the mode value */
417
- sprintf(buf, "0%o", -shared_repository);
418
+ xsnprintf(buf, sizeof(buf), "0%o", -shared_repository);
419
else if (shared_repository == PERM_GROUP)
419
- sprintf(buf, "%d", OLD_PERM_GROUP);
420
+ xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP);
421
else if (shared_repository == PERM_EVERYBODY)
421
- sprintf(buf, "%d", OLD_PERM_EVERYBODY);
422
+ xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY);
423
else
423
- die("oops");
424
+ die("BUG: invalid value for shared_repository");
425
git_config_set("core.sharedrepository", buf);
426
git_config_set("receive.denyNonFastforwards", "true");
427
}
builtin/ls-tree.c
+5
-4
@@ -96,12 +96,13 @@ static int show_tree(const unsigned char *sha1, struct strbuf *base,
96
if (!strcmp(type, blob_type)) {
97
unsigned long size;
98
if (sha1_object_info(sha1, &size) == OBJ_BAD)
99
- strcpy(size_text, "BAD");
99
+ xsnprintf(size_text, sizeof(size_text),
100
+ "BAD");
101
else
101
- snprintf(size_text, sizeof(size_text),
102
- "%lu", size);
102
+ xsnprintf(size_text, sizeof(size_text),
103
+ "%lu", size);
104
} else
104
- strcpy(size_text, "-");
105
+ xsnprintf(size_text, sizeof(size_text), "-");
106
printf("%06o %s %s %7s\t", mode, type,
107
find_unique_abbrev(sha1, abbrev),
108
size_text);
builtin/merge-index.c
+1
-1
@@ -23,7 +23,7 @@ static int merge_entry(int pos, const char *path)
23
break;
24
found++;
25
strcpy(hexbuf[stage], sha1_to_hex(ce->sha1));
26
- sprintf(ownbuf[stage], "%o", ce->ce_mode);
26
+ xsnprintf(ownbuf[stage], sizeof(ownbuf[stage]), "%o", ce->ce_mode);
27
arguments[stage] = hexbuf[stage];
28
arguments[stage + 4] = ownbuf[stage];
29
} while (++pos < active_nr);
builtin/merge-recursive.c
+1
-1
@@ -14,7 +14,7 @@ static const char *better_branch_name(const char *branch)
14
15
if (strlen(branch) != 40)
16
return branch;
17
- sprintf(githead_env, "GITHEAD_%s", branch);
17
+ xsnprintf(githead_env, sizeof(githead_env), "GITHEAD_%s", branch);
18
name = getenv(githead_env);
19
return name ? name : branch;
20
}
builtin/read-tree.c
+1
-1
@@ -90,7 +90,7 @@ static int debug_merge(const struct cache_entry * const *stages,
90
debug_stage("index", stages[0], o);
91
for (i = 1; i <= o->merge_size; i++) {
92
char buf[24];
93
- sprintf(buf, "ent#%d", i);
93
+ xsnprintf(buf, sizeof(buf), "ent#%d", i);
94
debug_stage(buf, stages[i], o);
95
}
96
return 0;
builtin/unpack-file.c
+1
-1
@@ -12,7 +12,7 @@ static char *create_temp_file(unsigned char *sha1)
12
if (!buf || type != OBJ_BLOB)
13
die("unable to read blob object %s", sha1_to_hex(sha1));
14
15
- strcpy(path, ".merge_file_XXXXXX");
15
+ xsnprintf(path, sizeof(path), ".merge_file_XXXXXX");
16
fd = xmkstemp(path);
17
if (write_in_full(fd, buf, size) != size)
18
die_errno("unable to write temp-file");
compat/mingw.c
+5
-3
@@ -2133,9 +2133,11 @@ int uname(struct utsname *buf)
2133
{
2134
DWORD v = GetVersion();
2135
memset(buf, 0, sizeof(*buf));
2136
- strcpy(buf->sysname, "Windows");
2137
- sprintf(buf->release, "%u.%u", v & 0xff, (v >> 8) & 0xff);
2136
+ xsnprintf(buf->sysname, sizeof(buf->sysname), "Windows");
2137
+ xsnprintf(buf->release, sizeof(buf->release),
2138
+ "%u.%u", v & 0xff, (v >> 8) & 0xff);
2139
/* assuming NT variants only.. */
2139
- sprintf(buf->version, "%u", (v >> 16) & 0x7fff);
2140
+ xsnprintf(buf->version, sizeof(buf->version),
2141
+ "%u", (v >> 16) & 0x7fff);
2142
return 0;
2143
}
compat/winansi.c
+1
-1
@@ -539,7 +539,7 @@ void winansi_init(void)
539
return;
540
541
/* create a named pipe to communicate with the console thread */
542
- sprintf(name, "\\\\.\\pipe\\winansi%lu", GetCurrentProcessId());
542
+ xsnprintf(name, sizeof(name), "\\\\.\\pipe\\winansi%lu", GetCurrentProcessId());
543
hwrite = CreateNamedPipe(name, PIPE_ACCESS_OUTBOUND,
544
PIPE_TYPE_BYTE | PIPE_WAIT, 1, BUFFER_SIZE, 0, 0, NULL);
545
if (hwrite == INVALID_HANDLE_VALUE)
connect.c
+1
-1
@@ -332,7 +332,7 @@ static const char *ai_name(const struct addrinfo *ai)
332
static char addr[NI_MAXHOST];
333
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, sizeof(addr), NULL, 0,
334
NI_NUMERICHOST) != 0)
335
- strcpy(addr, "(unknown)");
335
+ xsnprintf(addr, sizeof(addr), "(unknown)");
336
337
return addr;
338
}
convert.c
+2
-1
@@ -1289,7 +1289,8 @@ static struct stream_filter *ident_filter(const unsigned char *sha1)
1289
{
1290
struct ident_filter *ident = xmalloc(sizeof(*ident));
1291
1292
- sprintf(ident->ident, ": %s $", sha1_to_hex(sha1));
1292
+ xsnprintf(ident->ident, sizeof(ident->ident),
1293
+ ": %s $", sha1_to_hex(sha1));
1294
strbuf_init(&ident->left, 0);
1295
ident->filter.vtbl = &ident_vtbl;
1296
ident->state = 0;
daemon.c
+2
-2
@@ -901,7 +901,7 @@ static const char *ip2str(int family, struct sockaddr *sin, socklen_t len)
901
inet_ntop(family, &((struct sockaddr_in*)sin)->sin_addr, ip, len);
902
break;
903
default:
904
- strcpy(ip, "<unknown>");
904
+ xsnprintf(ip, sizeof(ip), "<unknown>");
905
}
906
return ip;
907
}
@@ -916,7 +916,7 @@ static int setup_named_sock(char *listen_addr, int listen_port, struct socketlis
916
int gai;
917
long flags;
918
919
- sprintf(pbuf, "%d", listen_port);
919
+ xsnprintf(pbuf, sizeof(pbuf), "%d", listen_port);
920
memset(&hints, 0, sizeof(hints));
921
hints.ai_family = AF_UNSPEC;
922
hints.ai_socktype = SOCK_STREAM;
diff.c
+6
-6
@@ -2880,7 +2880,7 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
2880
temp->name = get_tempfile_path(&temp->tempfile);
2881
strcpy(temp->hex, sha1_to_hex(sha1));
2882
temp->hex[40] = 0;
2883
- sprintf(temp->mode, "%06o", mode);
2883
+ xsnprintf(temp->mode, sizeof(temp->mode), "%06o", mode);
2884
strbuf_release(&buf);
2885
strbuf_release(&template);
2886
free(path_dup);
@@ -2897,8 +2897,8 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
2897
* a '+' entry produces this for file-1.
2898
*/
2899
temp->name = "/dev/null";
2900
- strcpy(temp->hex, ".");
2901
- strcpy(temp->mode, ".");
2900
+ xsnprintf(temp->hex, sizeof(temp->hex), ".");
2901
+ xsnprintf(temp->mode, sizeof(temp->mode), ".");
2902
return temp;
2903
}
2904
@@ -2935,7 +2935,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
2935
* !(one->sha1_valid), as long as
2936
* DIFF_FILE_VALID(one).
2937
*/
2938
- sprintf(temp->mode, "%06o", one->mode);
2938
+ xsnprintf(temp->mode, sizeof(temp->mode), "%06o", one->mode);
2939
}
2940
return temp;
2941
}
@@ -4081,9 +4081,9 @@ const char *diff_unique_abbrev(const unsigned char *sha1, int len)
4081
if (abblen < 37) {
4082
static char hex[41];
4083
if (len < abblen && abblen <= len + 2)
4084
- sprintf(hex, "%s%.*s", abbrev, len+3-abblen, "..");
4084
+ xsnprintf(hex, sizeof(hex), "%s%.*s", abbrev, len+3-abblen, "..");
4085
else
4086
- sprintf(hex, "%s...", abbrev);
4086
+ xsnprintf(hex, sizeof(hex), "%s...", abbrev);
4087
return hex;
4088
}
4089
return sha1_to_hex(sha1);
http-push.c
+1
-1
@@ -881,7 +881,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
881
strbuf_addf(&out_buffer.buf, LOCK_REQUEST, escaped);
882
free(escaped);
883
884
- sprintf(timeout_header, "Timeout: Second-%ld", timeout);
884
+ xsnprintf(timeout_header, sizeof(timeout_header), "Timeout: Second-%ld", timeout);
885
dav_headers = curl_slist_append(dav_headers, timeout_header);
886
dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
887
http.c
+3
-3
@@ -1104,7 +1104,7 @@ static void write_accept_language(struct strbuf *buf)
1104
decimal_places++, max_q *= 10)
1105
;
1106
1107
- sprintf(q_format, ";q=0.%%0%dd", decimal_places);
1107
+ xsnprintf(q_format, sizeof(q_format), ";q=0.%%0%dd", decimal_places);
1108
1109
strbuf_addstr(buf, "Accept-Language: ");
1110
@@ -1601,7 +1601,7 @@ struct http_pack_request *new_http_pack_request(
1601
fprintf(stderr,
1602
"Resuming fetch of pack %s at byte %ld\n",
1603
sha1_to_hex(target->sha1), prev_posn);
1604
- sprintf(range, "Range: bytes=%ld-", prev_posn);
1604
+ xsnprintf(range, sizeof(range), "Range: bytes=%ld-", prev_posn);
1605
preq->range_header = curl_slist_append(NULL, range);
1606
curl_easy_setopt(preq->slot->curl, CURLOPT_HTTPHEADER,
1607
preq->range_header);
@@ -1761,7 +1761,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
1761
fprintf(stderr,
1762
"Resuming fetch of object %s at byte %ld\n",
1763
hex, prev_posn);
1764
- sprintf(range, "Range: bytes=%ld-", prev_posn);
1764
+ xsnprintf(range, sizeof(range), "Range: bytes=%ld-", prev_posn);
1765
range_header = curl_slist_append(range_header, range);
1766
curl_easy_setopt(freq->slot->curl,
1767
CURLOPT_HTTPHEADER, range_header);
ll-merge.c
+6
-6
@@ -142,11 +142,11 @@ static struct ll_merge_driver ll_merge_drv[] = {
142
{ "union", "built-in union merge", ll_union_merge },
143
};
144
145
-static void create_temp(mmfile_t *src, char *path)
145
+static void create_temp(mmfile_t *src, char *path, size_t len)
146
{
147
int fd;
148
149
- strcpy(path, ".merge_file_XXXXXX");
149
+ xsnprintf(path, len, ".merge_file_XXXXXX");
150
fd = xmkstemp(path);
151
if (write_in_full(fd, src->ptr, src->size) != src->size)
152
die_errno("unable to write temp-file");
@@ -187,10 +187,10 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
187
188
result->ptr = NULL;
189
result->size = 0;
190
- create_temp(orig, temp[0]);
191
- create_temp(src1, temp[1]);
192
- create_temp(src2, temp[2]);
193
- sprintf(temp[3], "%d", marker_size);
190
+ create_temp(orig, temp[0], sizeof(temp[0]));
191
+ create_temp(src1, temp[1], sizeof(temp[1]));
192
+ create_temp(src2, temp[2], sizeof(temp[2]));
193
+ xsnprintf(temp[3], sizeof(temp[3]), "%d", marker_size);
194
195
strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict);
196
refs.c
+4
-4
@@ -3326,10 +3326,10 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,
3326
msglen = msg ? strlen(msg) : 0;
3327
maxlen = strlen(committer) + msglen + 100;
3328
logrec = xmalloc(maxlen);
3329
- len = sprintf(logrec, "%s %s %s\n",
3330
- sha1_to_hex(old_sha1),
3331
- sha1_to_hex(new_sha1),
3332
- committer);
3329
+ len = xsnprintf(logrec, maxlen, "%s %s %s\n",
3330
+ sha1_to_hex(old_sha1),
3331
+ sha1_to_hex(new_sha1),
3332
+ committer);
3333
if (msglen)
3334
len += copy_msg(logrec + len - 1, msg) - 1;
3335
sideband.c
+2
-2
@@ -137,11 +137,11 @@ ssize_t send_sideband(int fd, int band, const char *data, ssize_t sz, int packet
137
if (packet_max - 5 < n)
138
n = packet_max - 5;
139
if (0 <= band) {
140
- sprintf(hdr, "%04x", n + 5);
140
+ xsnprintf(hdr, sizeof(hdr), "%04x", n + 5);
141
hdr[4] = band;
142
write_or_die(fd, hdr, 5);
143
} else {
144
- sprintf(hdr, "%04x", n + 4);
144
+ xsnprintf(hdr, sizeof(hdr), "%04x", n + 4);
145
write_or_die(fd, hdr, 4);
146
}
147
write_or_die(fd, p, n);
strbuf.c
+2
-2
@@ -245,8 +245,8 @@ void strbuf_add_commented_lines(struct strbuf *out, const char *buf, size_t size
245
static char prefix2[2];
246
247
if (prefix1[0] != comment_line_char) {
248
- sprintf(prefix1, "%c ", comment_line_char);
249
- sprintf(prefix2, "%c", comment_line_char);
248
+ xsnprintf(prefix1, sizeof(prefix1), "%c ", comment_line_char);
249
+ xsnprintf(prefix2, sizeof(prefix2), "%c", comment_line_char);
250
}
251
add_lines(out, prefix1, prefix2, buf, size);
252
}