Browse Source

LibC: Fix negation overflow UB in `sys/mman.cpp`

When the system calls return `NumericLimits<ptrdiff_t>::min()`, negating
the return code would produce `NumericLimits<ptrdiff_t>::max() + 1`
since we are on a two's complement architecture. Because this value
cannot be stored, signed overflow occurs which is UB. This can be fixed
by applying the negation to `EMAXERRNO` since that's known to contain a
relatively small value.

Found when running tests with Clang.
Daniel Bertalan 3 years ago
parent
commit
78e7ff008b
1 changed files with 3 additions and 3 deletions
  1. 3 3
      Userland/Libraries/LibC/sys/mman.cpp

+ 3 - 3
Userland/Libraries/LibC/sys/mman.cpp

@@ -17,7 +17,7 @@ void* serenity_mmap(void* addr, size_t size, int prot, int flags, int fd, off_t
 {
 {
     Syscall::SC_mmap_params params { (uintptr_t)addr, size, alignment, prot, flags, fd, offset, { name, name ? strlen(name) : 0 } };
     Syscall::SC_mmap_params params { (uintptr_t)addr, size, alignment, prot, flags, fd, offset, { name, name ? strlen(name) : 0 } };
     ptrdiff_t rc = syscall(SC_mmap, &params);
     ptrdiff_t rc = syscall(SC_mmap, &params);
-    if (rc < 0 && -rc < EMAXERRNO) {
+    if (rc < 0 && rc > -EMAXERRNO) {
         errno = -rc;
         errno = -rc;
         return MAP_FAILED;
         return MAP_FAILED;
     }
     }
@@ -38,7 +38,7 @@ void* mremap(void* old_address, size_t old_size, size_t new_size, int flags)
 {
 {
     Syscall::SC_mremap_params params { (uintptr_t)old_address, old_size, new_size, flags };
     Syscall::SC_mremap_params params { (uintptr_t)old_address, old_size, new_size, flags };
     ptrdiff_t rc = syscall(SC_mremap, &params);
     ptrdiff_t rc = syscall(SC_mremap, &params);
-    if (rc < 0 && -rc < EMAXERRNO) {
+    if (rc < 0 && rc > -EMAXERRNO) {
         errno = -rc;
         errno = -rc;
         return MAP_FAILED;
         return MAP_FAILED;
     }
     }
@@ -77,7 +77,7 @@ int madvise(void* address, size_t size, int advice)
 void* allocate_tls(const char* initial_data, size_t size)
 void* allocate_tls(const char* initial_data, size_t size)
 {
 {
     ptrdiff_t rc = syscall(SC_allocate_tls, initial_data, size);
     ptrdiff_t rc = syscall(SC_allocate_tls, initial_data, size);
-    if (rc < 0 && -rc < EMAXERRNO) {
+    if (rc < 0 && rc > -EMAXERRNO) {
         errno = -rc;
         errno = -rc;
         return MAP_FAILED;
         return MAP_FAILED;
     }
     }