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.