diff options
Diffstat (limited to 'src/posix.c')
-rw-r--r-- | src/posix.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/src/posix.c b/src/posix.c index debd8d2c8..bf764ae6b 100644 --- a/src/posix.c +++ b/src/posix.c @@ -238,6 +238,9 @@ int git__mmap_alignment(size_t *alignment) int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset) { + const char *ptr; + size_t remaining_len; + GIT_MMAP_VALIDATE(out, len, prot, flags); /* writes cannot be emulated without handling pagefaults since write happens by @@ -248,15 +251,30 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset return -1; } + if (!git__is_ssizet(len)) { + errno = EINVAL; + return -1; + } + out->len = 0; out->data = git__malloc(len); GIT_ERROR_CHECK_ALLOC(out->data); - if (!git__is_ssizet(len) || - (p_lseek(fd, offset, SEEK_SET) < 0) || - (p_read(fd, out->data, len) != (ssize_t)len)) { - git_error_set(GIT_ERROR_OS, "mmap emulation failed"); - return -1; + remaining_len = len; + ptr = (const char *)out->data; + while (remaining_len > 0) { + ssize_t nb; + HANDLE_EINTR(nb, p_pread(fd, (void *)ptr, remaining_len, offset)); + if (nb <= 0) { + git_error_set(GIT_ERROR_OS, "mmap emulation failed"); + git__free(out->data); + out->data = NULL; + return -1; + } + + ptr += nb; + offset += nb; + remaining_len -= nb; } out->len = len; @@ -268,6 +286,10 @@ int p_munmap(git_map *map) GIT_ASSERT_ARG(map); git__free(map->data); + /* Initializing will help debug use-after-free */ + map->len = 0; + map->data = NULL; + return 0; } |