diff options
author | Edward Thomson <ethomson@microsoft.com> | 2015-02-09 23:41:13 -0500 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2015-02-12 22:54:46 -0500 |
commit | 392702ee2c88d7d8aaff25f7a84acb73606f9094 (patch) | |
tree | 97a66fe6e488797c6a9c2680ccb31964f61fe340 /src/path.c | |
parent | d24a5312d8ab6d3cdb259e450ec9f1e2e6f3399d (diff) | |
download | libgit2-392702ee2c88d7d8aaff25f7a84acb73606f9094.tar.gz |
allocations: test for overflow of requested size
Introduce some helper macros to test integer overflow from arithmetic
and set error message appropriately.
Diffstat (limited to 'src/path.c')
-rw-r--r-- | src/path.c | 64 |
1 files changed, 50 insertions, 14 deletions
diff --git a/src/path.c b/src/path.c index 58d71921b..3dbd7187b 100644 --- a/src/path.c +++ b/src/path.c @@ -622,7 +622,9 @@ static bool _check_dir_contents( size_t sub_size = strlen(sub); /* leave base valid even if we could not make space for subdir */ - if (git_buf_try_grow(dir, dir_size + sub_size + 2, false, false) < 0) + if (GIT_ALLOC_OVERFLOW_ADD(dir_size, sub_size) || + GIT_ALLOC_OVERFLOW_ADD(dir_size + sub_size, 2) || + git_buf_try_grow(dir, dir_size + sub_size + 2, false, false) < 0) return false; /* save excursion */ @@ -822,6 +824,9 @@ int git_path_make_relative(git_buf *path, const char *parent) for (; (q = strchr(q, '/')) && *(q + 1); q++) depth++; + GITERR_CHECK_ALLOC_MULTIPLY(depth, 3); + GITERR_CHECK_ALLOC_ADD(depth * 3, plen); + GITERR_CHECK_ALLOC_ADD(depth * 3, 1); newlen = (depth * 3) + plen; /* save the offset as we might realllocate the pointer */ @@ -881,6 +886,7 @@ int git_path_iconv(git_path_iconv_t *ic, char **in, size_t *inlen) git_buf_clear(&ic->buf); while (1) { + GITERR_CHECK_ALLOC_ADD(wantlen, 1); if (git_buf_grow(&ic->buf, wantlen + 1) < 0) return -1; @@ -1057,6 +1063,45 @@ int git_path_direach( return error; } +static int entry_path_alloc( + char **out, + const char *path, + size_t path_len, + const char *de_path, + size_t de_len, + size_t alloc_extra) +{ + int need_slash = (path_len > 0 && path[path_len-1] != '/') ? 1 : 0; + size_t alloc_size = path_len; + char *entry_path; + + GITERR_CHECK_ALLOC_ADD(alloc_size, de_len); + alloc_size += de_len; + + GITERR_CHECK_ALLOC_ADD(alloc_size, need_slash); + alloc_size += need_slash; + + GITERR_CHECK_ALLOC_ADD(alloc_size, 1); + alloc_size++; + + GITERR_CHECK_ALLOC_ADD(alloc_size, alloc_extra); + alloc_size += alloc_extra; + + entry_path = git__calloc(1, alloc_size); + GITERR_CHECK_ALLOC(entry_path); + + if (path_len) + memcpy(entry_path, path, path_len); + + if (need_slash) + entry_path[path_len] = '/'; + + memcpy(&entry_path[path_len + need_slash], de_path, de_len); + + *out = entry_path; + return 0; +} + int git_path_dirload( const char *path, size_t prefix_len, @@ -1064,7 +1109,7 @@ int git_path_dirload( unsigned int flags, git_vector *contents) { - int error, need_slash; + int error; DIR *dir; size_t path_len; path_dirent_data de_data; @@ -1096,11 +1141,10 @@ int git_path_dirload( path += prefix_len; path_len -= prefix_len; - need_slash = (path_len > 0 && path[path_len-1] != '/') ? 1 : 0; while ((error = p_readdir_r(dir, de_buf, &de)) == 0 && de != NULL) { char *entry_path, *de_path = de->d_name; - size_t alloc_size, de_len = strlen(de_path); + size_t de_len = strlen(de_path); if (git_path_is_dot_or_dotdot(de_path)) continue; @@ -1110,17 +1154,9 @@ int git_path_dirload( break; #endif - alloc_size = path_len + need_slash + de_len + 1 + alloc_extra; - if ((entry_path = git__calloc(alloc_size, 1)) == NULL) { - error = -1; + if ((error = entry_path_alloc(&entry_path, + path, path_len, de_path, de_len, alloc_extra)) < 0) break; - } - - if (path_len) - memcpy(entry_path, path, path_len); - if (need_slash) - entry_path[path_len] = '/'; - memcpy(&entry_path[path_len + need_slash], de_path, de_len); if ((error = git_vector_insert(contents, entry_path)) < 0) { git__free(entry_path); |