[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Chicken-janitors] #1005: pointer data structures don't overflow rel
From: |
Chicken Trac |
Subject: |
Re: [Chicken-janitors] #1005: pointer data structures don't overflow reliably, also this does not catch mmap error situations |
Date: |
Thu, 25 Apr 2013 04:44:51 -0000 |
#1005: pointer data structures don't overflow reliably, also this does not catch
mmap error situations
----------------------+-----------------------------------------------------
Reporter: ckeen | Owner:
Type: defect | Status: new
Priority: major | Milestone: someday
Component: unknown | Version: 4.8.x
Resolution: | Keywords: mmap ffi pointer suckage
----------------------+-----------------------------------------------------
Comment(by jrapdx):
The following module implements a plausible way to handle the mmap
error return value within "mmap-file-to-memory". Basically, the
system mmap function return is cast to C_word, defined (in chicken.h)
as a signed 32 or 64 bit value. If -1, an error is raised, otherwise
the return value is cast to an unsigned C_word and then to void*.
This solves the problem of inconsistent 32/64 bit behavior. In
addition, when mmap returns an error result, it seems sensible to
raise an exception rather than simply letting the program crash or
keep going despite illogical, useless (and user-confusing) values.
{{{
(module mm (map-file-to-mem)
(import scheme chicken foreign lolevel)
;; prot: PROT_READ 1, WRITE 2, EXEC 3, NONE 0
;; flag: MAP_FILE 0, ANON #x20, SHARED 1, PRIVATE 2,
;; FIXED #x10 (exact addr)
(define mmap-cword
(foreign-lambda* long ((c-pointer addr) (integer len) (int prot)
(int flag) (int fd)
(integer offset))
#<<EOP
#include <sys/mman.h>
void *r = mmap (addr, len, prot, flag, fd, offset);
C_word n = (C_word) r;
C_return(n);
EOP
))
;; Chicken's 'long' is 32 or 64 bit per system architecture
(define long->ptr (foreign-lambda* c-pointer ((long r))
"C_return((void*)(C_uword)r);" ))
(define (map-file-to-mem addr len prot flag fd #!optional (off 0))
(let ((addr-1 (mmap-cword addr len prot flag fd off)))
(if (= addr-1 -1)
;; do something with error, eg: (errno is 2 with flag = 0)
(error (format "mmap-cword errno: ~a (\"~a\")" (errno)
"no such file/directory"))
(##sys#make-structure 'mmap (long->ptr addr-1) len))))
)
}}}
Though the above "map-file-to-mem" lacks the error checking, etc.,
found in posix-unix.scm, it's functionally a drop-in replacement for
the original procedure.
Running this (modified) excerpt from "posix-tests.scm":
{{{
(let ((tnpfilpn (create-temporary-file)))
(let ((tmpfilno (file-open tnpfilpn (+ open/rdwr open/creat)))
(data "abcde")
(size 5))
(file-write tmpfilno data)
(let* ((mmap (map-file-to-mem #f size prot/read (+ map/file
map/private)
tmpfilno))
(str (make-string size))
(mptr (memory-mapped-file-pointer mmap)))
(print "mmap => " mmap " mptr => " mptr)
(move-memory! mptr str size)
(print "(string=? str data) => " (string=? str data))
(assert (blob=? (string->blob data) (string->blob str)))
(unmap-file-from-memory mmap))))
}}}
prints:
{{{
mmap => #<mmap> mptr => #<pointer 0x7f3160588000>
(string=? str data) => #t
}}}
However, with the "map/private" flag removed, mmap -> -1 and the
result is:
{{{
Error: mmap-cword errno: 2 ("no such file/directory")
Call history:
mmap-test-err.scm:5: load
mmap-test-err.scm:8: print
mmap-test-err.scm:10: create-temporary-file
mmap-test-err.scm:11: file-open
mmap-test-err.scm:14: file-write
mmap-test-err.scm:15: mm#map-file-to-mem
mmap.scm:32: error <--
}}}
I hope this idea helps resolve the issue with mmap.
Thanks,
Jules Altfas.
--
Ticket URL: <http://bugs.call-cc.org/ticket/1005#comment:2>
Chicken Scheme <http://www.call-with-current-continuation.org/>
Chicken Scheme is a compiler for the Scheme programming language.