diff --git a/src/fileops.c b/src/fileops.c index eb24013e8..420ed70a2 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -127,6 +127,11 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len) git_buf_clear(buf); + if (!git__is_ssizet(len)) { + giterr_set(GITERR_INVALID, "Read too large."); + return -1; + } + GITERR_CHECK_ALLOC_ADD(len, 1); if (git_buf_grow(buf, len + 1) < 0) return -1; diff --git a/src/posix.c b/src/posix.c index d5e6875b5..8d86aa8bf 100644 --- a/src/posix.c +++ b/src/posix.c @@ -155,6 +155,14 @@ ssize_t p_read(git_file fd, void *buf, size_t cnt) { char *b = buf; + if (!git__is_ssizet(cnt)) { +#ifdef GIT_WIN32 + SetLastError(ERROR_INVALID_PARAMETER); +#endif + errno = EINVAL; + return -1; + } + while (cnt) { ssize_t r; #ifdef GIT_WIN32 @@ -229,7 +237,9 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs out->data = malloc(len); GITERR_CHECK_ALLOC(out->data); - if ((p_lseek(fd, offset, SEEK_SET) < 0) || ((size_t)p_read(fd, out->data, len) != len)) { + if (!git__is_ssizet(len) || + (p_lseek(fd, offset, SEEK_SET) < 0) || + (p_read(fd, out->data, len) != (ssize_t)len)) { giterr_set(GITERR_OS, "mmap emulation failed"); return -1; } diff --git a/src/util.h b/src/util.h index 40e06976d..dcdaf4363 100644 --- a/src/util.h +++ b/src/util.h @@ -153,6 +153,13 @@ GIT_INLINE(int) git__is_sizet(git_off_t p) return p == (git_off_t)r; } +/** @return true if p fits into the range of an ssize_t */ +GIT_INLINE(int) git__is_ssizet(size_t p) +{ + ssize_t r = (ssize_t)p; + return p == (size_t)r; +} + /** @return true if p fits into the range of a uint32_t */ GIT_INLINE(int) git__is_uint32(size_t p) {