Running 32-bit CCL on 64-bit Linux (but it can happen in any setup), I noticed that (osicat-posix:mmap) does not correctly handle return addresses larger than the maximum C "long" value, but instead throws an exception.
In such cases, it means the underlying C mmap() function returned successfully a pointer in the top half of the addressable virtual memory, but the Lisp wrapper for mmap() and mremap() chokes on such pointers.
A patch that solves this problem is attached.
Feedback on the analysis and the solution is welcome :)
Best regards,
Massimiliano Ghilardi
------------------ longer explanation -----------------------------
While invoking
(osicat-posix:mmap (cffi-sys:null-pointer) 4096 (logior osicat-posix:prot-read osicat-posix:prot-write) osicat-posix:map-shared *fd* 0)
with a file descriptor *fd* correctly open on a 4096-byte file, I encountered the error: ------------------------------------------------------------------- The value -143798272 is not of the expected type (UNSIGNED-BYTE 32). [Condition of type TYPE-ERROR]
Restarts: 0: [RETRY] Retry SLIME REPL evaluation request. 1: [*ABORT] Return to SLIME's top level. 2: [ABORT-BREAK] Reset this thread 3: [ABORT] Kill this thread
Backtrace: 0: (CFFI-SYS:MAKE-POINTER -143798272) 1: (CCL::CALL-CHECK-REGS OSICAT-POSIX:MMAP #<A Null Foreign Pointer> 4096 3 1 4 0) 2: (CCL::CHEAP-EVAL (OSICAT-POSIX:MMAP (CFFI-SYS:NULL-POINTER) 4096 (LOGIOR OSICAT-POSIX:PROT-READ OSICAT-POSIX:PROT-WRITE) OSICAT-POSIX:MAP-SHARED *FD* ...)) -------------------------------------------------------------------
A simple analysis (cat /proc/<ccl-pid>/maps) shows that mmap() actually succeeded and returned the value #xf76dd000, which was converted to -143798272 because OSICAT wrapper for mmap() is defined to return a C "long", that is limited to the range -#x80000000 to #x7fffffff, thus converting #xf76dd000 to a C long overflows and gives a negative value.
But calling (cffi-sys:make-pointer) chokes on negative values, at least on CCL.