ffi/unsafe: fix make-sized-byte-string on a #f argument

In particular, a #f argument can make sense if the length is 0.
Technically, a byte string's byte array is supposed to be nul-terminated,
but many uses of byte strings get away without that terminator. I've
adjust the documentation to note that `bytes-copy` will work with a
non-terminated byte string.

Merge to v6.1.1
This commit is contained in:
Matthew Flatt 2014-10-14 05:59:35 -06:00
parent da98d60f99
commit 1cc86d3cea
4 changed files with 21 additions and 10 deletions

View File

@ -389,6 +389,12 @@ Returns a byte string made of the given pointer and the given length.
No copying is done. This can be used as an alternative to make No copying is done. This can be used as an alternative to make
pointer values accessible in Racket when the size is known. pointer values accessible in Racket when the size is known.
Beware that the representation of a Racket byte string normally
requires a nul terminator at the end of the byte string (after
@racket[length] bytes), but some function work with a byte-string
representation that has no such terminator---notably
@racket[bytes-copy].
If @racket[cptr] is an offset pointer created by @racket[ptr-add], the If @racket[cptr] is an offset pointer created by @racket[ptr-add], the
offset is immediately added to the pointer. Thus, this function cannot offset is immediately added to the pointer. Thus, this function cannot
be used with @racket[ptr-add] to create a substring of a Racket byte be used with @racket[ptr-add] to create a substring of a Racket byte

View File

@ -15,6 +15,8 @@
(test #f malloc 0 _int) (test #f malloc 0 _int)
(test #f malloc _int 0) (test #f malloc _int 0)
(test 0 bytes-length (make-sized-byte-string #f 0))
;; Check integer-range checking: ;; Check integer-range checking:
(let () (let ()
(define (try-int-boundary N _int _uint) (define (try-int-boundary N _int _uint)

View File

@ -3178,9 +3178,7 @@ static Scheme_Object *foreign_make_sized_byte_string(int argc, Scheme_Object *ar
scheme_wrong_contract(MYNAME, "cpointer?", 0, argc, argv); scheme_wrong_contract(MYNAME, "cpointer?", 0, argc, argv);
if (!scheme_get_int_val(argv[1],&len)) if (!scheme_get_int_val(argv[1],&len))
wrong_intptr(MYNAME, 1, argc, argv); wrong_intptr(MYNAME, 1, argc, argv);
if (SCHEME_FALSEP(cp)) return scheme_false; return scheme_make_sized_byte_string(SCHEME_FFIANYPTR_OFFSETVAL(cp),
else return
scheme_make_sized_byte_string(SCHEME_FFIANYPTR_OFFSETVAL(cp),
len, 0); len, 0);
} }
#undef MYNAME #undef MYNAME

View File

@ -2346,9 +2346,7 @@ static Scheme_Object *do_memop(const char *who, int mode,
scheme_wrong_contract(MYNAME, "cpointer?", 0, argc, argv); scheme_wrong_contract(MYNAME, "cpointer?", 0, argc, argv);
if (!scheme_get_int_val(argv[1],&len)) if (!scheme_get_int_val(argv[1],&len))
wrong_intptr(MYNAME, 1, argc, argv); wrong_intptr(MYNAME, 1, argc, argv);
if (SCHEME_FALSEP(cp)) return scheme_false; return scheme_make_sized_byte_string(SCHEME_FFIANYPTR_OFFSETVAL(cp),
else return
scheme_make_sized_byte_string(SCHEME_FFIANYPTR_OFFSETVAL(cp),
len, 0); len, 0);
} }
@ -2415,6 +2413,10 @@ static void ffi_call_in_orig_place(ffi_cif *cif, void *c_func, intptr_t cfoff,
void *sh; void *sh;
int ready; int ready;
if (cached_orig_place_todo) {
todo = cached_orig_place_todo;
cached_orig_place_todo = NULL;
} else
todo = (FFI_Orig_Place_Call *)malloc(sizeof(FFI_Orig_Place_Call)); todo = (FFI_Orig_Place_Call *)malloc(sizeof(FFI_Orig_Place_Call));
sh = scheme_get_signal_handle(); sh = scheme_get_signal_handle();
todo->signal_handle = sh; todo->signal_handle = sh;
@ -2466,6 +2468,9 @@ static void ffi_call_in_orig_place(ffi_cif *cif, void *c_func, intptr_t cfoff,
if (!todo->signal_handle) { if (!todo->signal_handle) {
/* Done */ /* Done */
mzrt_mutex_unlock(orig_place_mutex); mzrt_mutex_unlock(orig_place_mutex);
if (!cached_orig_place_todo)
cached_orig_place_todo = todo;
else
free(todo); free(todo);
break; break;
} else { } else {