p_read: ensure requested len is ssize_t Ensure that the given length to `p_read` is of ssize_t and ensure that callers test the return as if it were an `ssize_t`.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
diff --git a/src/fileops.c b/src/fileops.c
index eb24013..420ed70 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 d5e6875..8d86aa8 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 40e0697..dcdaf43 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)
{