From f57c1c8e2a3b4d084816e904005ffbd71e2dec86 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 11 Jul 2014 13:23:30 +0100 Subject: [PATCH] fix GC-cooperation bug in `vector->values` The `vector->values` function set up multiple return values badly in the case that the given vector is chaperoned. The problem could lead to NULL as results for `vector->values`. Merge to v6.1 --- .../racket-test/tests/racket/chaperone.rktl | 8 +++++++ racket/src/racket/src/vector.c | 23 +++++++++++-------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/pkgs/racket-pkgs/racket-test/tests/racket/chaperone.rktl b/pkgs/racket-pkgs/racket-test/tests/racket/chaperone.rktl index 960941897b..385a2616bc 100644 --- a/pkgs/racket-pkgs/racket-test/tests/racket/chaperone.rktl +++ b/pkgs/racket-pkgs/racket-test/tests/racket/chaperone.rktl @@ -199,6 +199,14 @@ (test #f vector-ref b 0) (test #f vector-ref b2 0))) +;; check interaction of chaperones and vector->values: +(let ([b (vector 1 2 3)]) + (let ([b2 (impersonate-vector b + (lambda (b i v) (collect-garbage) v) + (lambda (b i v) #f))]) + (define-values (a b c) (vector->values b2)) + (test '(1 2 3) list a b c))) + ;; ---------------------------------------- (test #t chaperone?/impersonator (chaperone-procedure (lambda (x) x) (lambda (y) y))) diff --git a/racket/src/racket/src/vector.c b/racket/src/racket/src/vector.c index 981f572deb..7c7c771b90 100644 --- a/racket/src/racket/src/vector.c +++ b/racket/src/racket/src/vector.c @@ -771,7 +771,7 @@ static Scheme_Object *vector_to_immutable (int argc, Scheme_Object *argv[]) static Scheme_Object *vector_to_values (int argc, Scheme_Object *argv[]) { Scheme_Thread *p; - Scheme_Object *vec, **a; + Scheme_Object *vec, **a, *plain_vec; intptr_t len, start, finish, i; vec = argv[0]; @@ -807,6 +807,16 @@ static Scheme_Object *vector_to_values (int argc, Scheme_Object *argv[]) return SCHEME_VEC_ELS(vec)[start]; } + if (!SAME_OBJ(vec, argv[0])) { + plain_vec = scheme_make_vector(len, NULL); + for (i = 0; i < len; i++) { + vec = scheme_chaperone_vector_ref(argv[0], start + i); + SCHEME_VEC_ELS(plain_vec)[i] = vec; + } + vec = plain_vec; + start = 0; + } + p = scheme_current_thread; if (p->values_buffer && (p->values_buffer_size >= len)) a = p->values_buffer; @@ -819,15 +829,8 @@ static Scheme_Object *vector_to_values (int argc, Scheme_Object *argv[]) p->ku.multiple.array = a; p->ku.multiple.count = len; - if (!SAME_OBJ(vec, argv[0])) { - for (i = 0; i < len; i++) { - vec = scheme_chaperone_vector_ref(argv[0], start + i); - a[i] = vec; - } - } else { - for (i = 0; i < len; i++) { - a[i] = SCHEME_VEC_ELS(vec)[start + i]; - } + for (i = 0; i < len; i++) { + a[i] = SCHEME_VEC_ELS(vec)[start + i]; } return SCHEME_MULTIPLE_VALUES;