Skip to content

Commit d4b3d11

Browse files
peffgitster
authored andcommitted
write_loose_object: convert to strbuf
When creating a loose object tempfile, we use a fixed PATH_MAX-sized buffer, and strcpy directly into it. This isn't buggy, because we do a rough check of the size, but there's no verification that our guesstimate of the required space is enough (in fact, it's several bytes too big for the current naming scheme). Let's switch to a strbuf, which makes this much easier to verify. The allocation overhead should be negligible, since we are replacing a static buffer with a static strbuf, and we'll only need to allocate on the first call. While we're here, we can also document a subtle interaction with mkstemp that would be easy to overlook. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4635768 commit d4b3d11

File tree

1 file changed

+22
-20
lines changed

1 file changed

+22
-20
lines changed

sha1_file.c

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3011,29 +3011,31 @@ static inline int directory_size(const char *filename)
30113011
* We want to avoid cross-directory filename renames, because those
30123012
* can have problems on various filesystems (FAT, NFS, Coda).
30133013
*/
3014-
static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)
3014+
static int create_tmpfile(struct strbuf *tmp, const char *filename)
30153015
{
30163016
int fd, dirlen = directory_size(filename);
30173017

3018-
if (dirlen + 20 > bufsiz) {
3019-
errno = ENAMETOOLONG;
3020-
return -1;
3021-
}
3022-
memcpy(buffer, filename, dirlen);
3023-
strcpy(buffer + dirlen, "tmp_obj_XXXXXX");
3024-
fd = git_mkstemp_mode(buffer, 0444);
3018+
strbuf_reset(tmp);
3019+
strbuf_add(tmp, filename, dirlen);
3020+
strbuf_addstr(tmp, "tmp_obj_XXXXXX");
3021+
fd = git_mkstemp_mode(tmp->buf, 0444);
30253022
if (fd < 0 && dirlen && errno == ENOENT) {
3026-
/* Make sure the directory exists */
3027-
memcpy(buffer, filename, dirlen);
3028-
buffer[dirlen-1] = 0;
3029-
if (mkdir(buffer, 0777) && errno != EEXIST)
3023+
/*
3024+
* Make sure the directory exists; note that the contents
3025+
* of the buffer are undefined after mkstemp returns an
3026+
* error, so we have to rewrite the whole buffer from
3027+
* scratch.
3028+
*/
3029+
strbuf_reset(tmp);
3030+
strbuf_add(tmp, filename, dirlen - 1);
3031+
if (mkdir(tmp->buf, 0777) && errno != EEXIST)
30303032
return -1;
3031-
if (adjust_shared_perm(buffer))
3033+
if (adjust_shared_perm(tmp->buf))
30323034
return -1;
30333035

30343036
/* Try again */
3035-
strcpy(buffer + dirlen - 1, "/tmp_obj_XXXXXX");
3036-
fd = git_mkstemp_mode(buffer, 0444);
3037+
strbuf_addstr(tmp, "/tmp_obj_XXXXXX");
3038+
fd = git_mkstemp_mode(tmp->buf, 0444);
30373039
}
30383040
return fd;
30393041
}
@@ -3046,10 +3048,10 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
30463048
git_zstream stream;
30473049
git_SHA_CTX c;
30483050
unsigned char parano_sha1[20];
3049-
static char tmp_file[PATH_MAX];
3051+
static struct strbuf tmp_file = STRBUF_INIT;
30503052
const char *filename = sha1_file_name(sha1);
30513053

3052-
fd = create_tmpfile(tmp_file, sizeof(tmp_file), filename);
3054+
fd = create_tmpfile(&tmp_file, filename);
30533055
if (fd < 0) {
30543056
if (errno == EACCES)
30553057
return error("insufficient permission for adding an object to repository database %s", get_object_directory());
@@ -3098,12 +3100,12 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
30983100
struct utimbuf utb;
30993101
utb.actime = mtime;
31003102
utb.modtime = mtime;
3101-
if (utime(tmp_file, &utb) < 0)
3103+
if (utime(tmp_file.buf, &utb) < 0)
31023104
warning("failed utime() on %s: %s",
3103-
tmp_file, strerror(errno));
3105+
tmp_file.buf, strerror(errno));
31043106
}
31053107

3106-
return finalize_object_file(tmp_file, filename);
3108+
return finalize_object_file(tmp_file.buf, filename);
31073109
}
31083110

31093111
static int freshen_loose_object(const unsigned char *sha1)

0 commit comments

Comments
 (0)