use xmallocz to avoid size arithmetic
We frequently allocate strings as xmalloc(len + 1), where the extra 1 is for the NUL terminator. This can be done more simply with xmallocz, which also checks for integer overflow. There's no case where switching xmalloc(n+1) to xmallocz(n) is wrong; the result is the same length, and malloc made no guarantees about what was in the buffer anyway. But in some cases, we can stop manually placing NUL at the end of the allocated buffer. But that's only safe if it's clear that the contents will always fill the buffer. In each case where this patch does so, I manually examined the control flow, and I tried to err on the side of caution. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Feb 22, 2016 at 17:44 UTC
3733e6946465d4a3a1d89026a5ec911d3af339ab
15 files changed
+17
-25
builtin/check-ref-format.c
+1
-1
@@ -20,7 +20,7 @@ static const char builtin_check_ref_format_usage[] =
20
*/
21
static char *collapse_slashes(const char *refname)
22
{
23
- char *ret = xmalloc(strlen(refname) + 1);
23
+ char *ret = xmallocz(strlen(refname));
24
char ch;
25
char prev = '/';
26
char *cp = ret;
builtin/merge-tree.c
+1
-1
@@ -174,7 +174,7 @@ static struct merge_list *create_entry(unsigned stage, unsigned mode, const unsi
174
175
static char *traverse_path(const struct traverse_info *info, const struct name_entry *n)
176
{
177
- char *path = xmalloc(traverse_path_len(info, n) + 1);
177
+ char *path = xmallocz(traverse_path_len(info, n));
178
return make_traverse_path(path, info, n);
179
}
180
builtin/worktree.c
+1
-1
@@ -52,7 +52,7 @@ static int prune_worktree(const char *id, struct strbuf *reason)
52
return 1;
53
}
54
len = st.st_size;
55
- path = xmalloc(len + 1);
55
+ path = xmallocz(len);
56
read_in_full(fd, path, len);
57
close(fd);
58
while (len && (path[len - 1] == '\n' || path[len - 1] == '\r'))
column.c
+1
-2
@@ -173,9 +173,8 @@ static void display_table(const struct string_list *list,
173
if (colopts & COL_DENSE)
174
shrink_columns(&data);
175
176
- empty_cell = xmalloc(initial_width + 1);
176
+ empty_cell = xmallocz(initial_width);
177
memset(empty_cell, ' ', initial_width);
178
- empty_cell[initial_width] = '\0';
178
for (y = 0; y < data.rows; y++) {
179
for (x = 0; x < data.cols; x++)
180
if (display_cell(&data, initial_width, empty_cell, x, y))
combine-diff.c
+1
-3
@@ -1043,7 +1043,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
1043
elem->mode = canon_mode(S_IFLNK);
1044
1045
result_size = len;
1046
- result = xmalloc(len + 1);
1046
+ result = xmallocz(len);
1047
1048
done = read_in_full(fd, result, len);
1049
if (done < 0)
@@ -1051,8 +1051,6 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
1051
else if (done < len)
1052
die("early EOF '%s'", elem->path);
1053
1054
- result[len] = 0;
1055
-
1054
/* If not a fake symlink, apply filters, e.g. autocrlf */
1055
if (is_file) {
1056
struct strbuf buf = STRBUF_INIT;
config.c
+1
-3
@@ -1878,7 +1878,7 @@ static int git_config_parse_key_1(const char *key, char **store_key, int *basele
1878
* Validate the key and while at it, lower case it for matching.
1879
*/
1880
if (store_key)
1881
- *store_key = xmalloc(strlen(key) + 1);
1881
+ *store_key = xmallocz(strlen(key));
1882
1883
dot = 0;
1884
for (i = 0; key[i]; i++) {
@@ -1902,8 +1902,6 @@ static int git_config_parse_key_1(const char *key, char **store_key, int *basele
1902
if (store_key)
1903
(*store_key)[i] = c;
1904
}
1905
- if (store_key)
1906
- (*store_key)[i] = 0;
1905
1906
return 0;
1907
dir.c
+1
-1
@@ -711,7 +711,7 @@ static int add_excludes(const char *fname, const char *base, int baselen,
711
close(fd);
712
return 0;
713
}
714
- buf = xmalloc(size+1);
714
+ buf = xmallocz(size);
715
if (read_in_full(fd, buf, size) != size) {
716
free(buf);
717
close(fd);
entry.c
+1
-1
@@ -6,7 +6,7 @@
6
static void create_directories(const char *path, int path_len,
7
const struct checkout *state)
8
{
9
- char *buf = xmalloc(path_len + 1);
9
+ char *buf = xmallocz(path_len);
10
int len = 0;
11
12
while (len < path_len) {
grep.c
+1
-2
@@ -1741,7 +1741,7 @@ static int grep_source_load_file(struct grep_source *gs)
1741
i = open(filename, O_RDONLY);
1742
if (i < 0)
1743
goto err_ret;
1744
- data = xmalloc(size + 1);
1744
+ data = xmallocz(size);
1745
if (st.st_size != read_in_full(i, data, size)) {
1746
error(_("'%s': short read %s"), filename, strerror(errno));
1747
close(i);
@@ -1749,7 +1749,6 @@ static int grep_source_load_file(struct grep_source *gs)
1749
return -1;
1750
}
1751
close(i);
1752
- data[size] = 0;
1752
1753
gs->buf = data;
1754
gs->size = size;
imap-send.c
+2
-3
@@ -892,12 +892,11 @@ static char *cram(const char *challenge_64, const char *user, const char *pass)
892
response = xstrfmt("%s %s", user, hex);
893
resp_len = strlen(response) + 1;
894
895
- response_64 = xmalloc(ENCODED_SIZE(resp_len) + 1);
895
+ response_64 = xmallocz(ENCODED_SIZE(resp_len));
896
encoded_len = EVP_EncodeBlock((unsigned char *)response_64,
897
(unsigned char *)response, resp_len);
898
if (encoded_len < 0)
899
die("EVP_EncodeBlock error");
900
- response_64[encoded_len] = '\0';
900
return (char *)response_64;
901
}
902
@@ -1188,7 +1187,7 @@ static void lf_to_crlf(struct strbuf *msg)
1187
j++;
1188
}
1189
1191
- new = xmalloc(j + 1);
1190
+ new = xmallocz(j);
1191
1192
/*
1193
* Second pass: write the new string. Note that this loop is
ll-merge.c
+1
-1
@@ -205,7 +205,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
205
if (fstat(fd, &st))
206
goto close_bad;
207
result->size = st.st_size;
208
- result->ptr = xmalloc(result->size + 1);
208
+ result->ptr = xmallocz(result->size);
209
if (read_in_full(fd, result->ptr, result->size) != result->size) {
210
free(result->ptr);
211
result->ptr = NULL;
progress.c
+1
-1
@@ -247,7 +247,7 @@ void stop_progress_msg(struct progress **p_progress, const char *msg)
247
size_t len = strlen(msg) + 5;
248
struct throughput *tp = progress->throughput;
249
250
- bufp = (len < sizeof(buf)) ? buf : xmalloc(len + 1);
250
+ bufp = (len < sizeof(buf)) ? buf : xmallocz(len);
251
if (tp) {
252
unsigned int rate = !tp->avg_misecs ? 0 :
253
tp->avg_bytes / tp->avg_misecs;
refs.c
+1
-1
@@ -124,7 +124,7 @@ int refname_is_safe(const char *refname)
124
char *buf;
125
int result;
126
127
- buf = xmalloc(strlen(refname) + 1);
127
+ buf = xmallocz(strlen(refname));
128
/*
129
* Does the refname try to escape refs/?
130
* For example: refs/foo/../bar is safe but refs/foo/../../bar
setup.c
+2
-3
@@ -88,7 +88,7 @@ char *prefix_path_gently(const char *prefix, int len,
88
const char *orig = path;
89
char *sanitized;
90
if (is_absolute_path(orig)) {
91
- sanitized = xmalloc(strlen(path) + 1);
91
+ sanitized = xmallocz(strlen(path));
92
if (remaining_prefix)
93
*remaining_prefix = 0;
94
if (normalize_path_copy_len(sanitized, path, remaining_prefix)) {
@@ -499,14 +499,13 @@ const char *read_gitfile_gently(const char *path, int *return_error_code)
499
error_code = READ_GITFILE_ERR_OPEN_FAILED;
500
goto cleanup_return;
501
}
502
- buf = xmalloc(st.st_size + 1);
502
+ buf = xmallocz(st.st_size);
503
len = read_in_full(fd, buf, st.st_size);
504
close(fd);
505
if (len != st.st_size) {
506
error_code = READ_GITFILE_ERR_READ_FAILED;
507
goto cleanup_return;
508
}
509
- buf[len] = '\0';
509
if (!starts_with(buf, "gitdir: ")) {
510
error_code = READ_GITFILE_ERR_INVALID_FORMAT;
511
goto cleanup_return;
strbuf.c
+1
-1
@@ -685,7 +685,7 @@ char *xstrdup_tolower(const char *string)
685
size_t len, i;
686
687
len = strlen(string);
688
- result = xmalloc(len + 1);
688
+ result = xmallocz(len);
689
for (i = 0; i < len; i++)
690
result[i] = tolower(string[i]);
691
result[i] = '\0';