summaryrefslogtreecommitdiff
path: root/src/posix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/posix.c')
-rw-r--r--src/posix.c32
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;
}