Fix segfault on accessing non-present impersonator properties of property-only vector chaperones
Additionally this adds macros that distinguish between the chaperone redirects of prop-only vector chaperones, function chaperones, and structure chaperones since each of these may store a vector in the redirects field.
This commit is contained in:
parent
d3787775f1
commit
87e4bdbec8
|
@ -223,6 +223,65 @@
|
|||
(define-values (a b c) (vector->values b2))
|
||||
(test '(1 2 3) list a b c)))
|
||||
|
||||
(define unsafe-chaperone-vector-name "unsafe-chaperone-vector")
|
||||
(define unsafe-impersonate-vector-name "unsafe-impersonate-vector")
|
||||
(define chaperone-vector*-name "chaperone-vector*")
|
||||
(define impersonate-vector*-name "impersonate-vector*")
|
||||
(define chaperone-vector-name "chaperone-vector")
|
||||
(define impersonate-vector-name "impersonate-vector")
|
||||
|
||||
|
||||
;; properties and chaperones
|
||||
(as-chaperone-or-impersonator
|
||||
([chaperone-vector impersonate-vector]
|
||||
[chaperone-vector* impersonate-vector*]
|
||||
[unsafe-chaperone-vector unsafe-impersonate-vector])
|
||||
(let ()
|
||||
|
||||
(define-values (p1 has1 get1) (make-impersonator-property 'p1))
|
||||
(define-values (p2 has2 get2) (make-impersonator-property 'p2))
|
||||
|
||||
(define v (vector 1 2 3))
|
||||
(define u (vector 7 8 9))
|
||||
(define red (lambda (v i x) x))
|
||||
(define red* (lambda (c v i x) x))
|
||||
|
||||
(define v1 (chaperone-vector v #f #f))
|
||||
(define v2 (chaperone-vector* v #f #f))
|
||||
(define v3 (unsafe-chaperone-vector v u))
|
||||
(define v4 (chaperone-vector v #f #f p2 5))
|
||||
(define v5 (chaperone-vector* v #f #f p2 5))
|
||||
(define v6 (unsafe-chaperone-vector v u p2 5))
|
||||
(define v7 (chaperone-vector v red red))
|
||||
(define v8 (chaperone-vector* v red* red*))
|
||||
(define v9 (chaperone-vector v red red p2 5))
|
||||
(define v10 (chaperone-vector* v red* red* p2 5))
|
||||
|
||||
(test 5 get2 v4)
|
||||
(test 5 get2 v5)
|
||||
(test 5 get2 v6)
|
||||
(test 5 get2 v9)
|
||||
(test 5 get2 v10)
|
||||
|
||||
(define handler
|
||||
(lambda (exn)
|
||||
(test #t
|
||||
regexp-match?
|
||||
"p1-accessor: contract violation"
|
||||
(exn-message exn))))
|
||||
|
||||
(err/rt-test (get1 v1) handler)
|
||||
(err/rt-test (get1 v2) handler)
|
||||
(err/rt-test (get1 v3) handler)
|
||||
(err/rt-test (get1 v4) handler)
|
||||
(err/rt-test (get1 v5) handler)
|
||||
(err/rt-test (get1 v6) handler)
|
||||
(err/rt-test (get1 v7) handler)
|
||||
(err/rt-test (get1 v8) handler)
|
||||
(err/rt-test (get1 v9) handler)
|
||||
(err/rt-test (get1 v10) handler)))
|
||||
|
||||
|
||||
;; check property-only chaperones
|
||||
(as-chaperone-or-impersonator
|
||||
([chaperone-vector impersonate-vector chaperone-vector* impersonate-vector*]
|
||||
|
@ -686,9 +745,6 @@
|
|||
(test '(set p1-prop p2-prop) unbox b)
|
||||
(test 17 vector-ref c2 1))
|
||||
|
||||
(define unsafe-chaperone-vector-name "unsafe-chaperone-vector")
|
||||
(define unsafe-impersonate-vector-name "unsafe-impersonate-vector")
|
||||
|
||||
(as-chaperone-or-impersonator
|
||||
([chaperone-vector impersonate-vector]
|
||||
[chaperone-vector* impersonate-vector*]
|
||||
|
|
|
@ -3084,8 +3084,7 @@ scheme_do_eval(Scheme_Object *obj, int num_rands, Scheme_Object **rands,
|
|||
the chaperone may guard access to the function as a field inside
|
||||
the struct. We'll need to keep track of the original object
|
||||
as we unwrap to discover procedure chaperones. */
|
||||
&& (SCHEME_VECTORP(((Scheme_Chaperone *)obj)->redirects))
|
||||
&& !(SCHEME_VEC_SIZE(((Scheme_Chaperone *)obj)->redirects) & 1))
|
||||
&& SCHEME_REDIRECTS_STRUCTP(((Scheme_Chaperone *) obj)->redirects))
|
||||
/* A raw pair is from scheme_apply_chaperone(), propagating the
|
||||
original object for an applicable structure. */
|
||||
|| (type == scheme_raw_pair_type)) {
|
||||
|
@ -3150,8 +3149,7 @@ scheme_do_eval(Scheme_Object *obj, int num_rands, Scheme_Object **rands,
|
|||
|
||||
goto apply_top;
|
||||
} else {
|
||||
if (SCHEME_VECTORP(((Scheme_Chaperone *)obj)->redirects)
|
||||
&& !(SCHEME_VEC_SIZE(((Scheme_Chaperone *)obj)->redirects) & 1))
|
||||
if (SCHEME_REDIRECTS_STRUCTP(((Scheme_Chaperone *)obj)->redirects))
|
||||
obj = ((Scheme_Chaperone *)obj)->prev;
|
||||
else if (SAME_TYPE(SCHEME_TYPE(((Scheme_Chaperone *)obj)->redirects), scheme_nack_guard_evt_type))
|
||||
/* Chaperone is for evt, not function arguments */
|
||||
|
|
|
@ -3631,7 +3631,7 @@ static Scheme_Object *do_chaperone_procedure(const char *name, const char *whati
|
|||
to pass the self proc along. */
|
||||
for (val = px->prev; SCHEME_P_CHAPERONEP(val); val = ((Scheme_Chaperone *)val)->prev) {
|
||||
px2 = (Scheme_Chaperone *)val;
|
||||
if (SCHEME_VECTORP(px2->redirects) && (SCHEME_VEC_SIZE(px2->redirects) & 0x1)) {
|
||||
if (SCHEME_REDIRECTS_PROCEDUREP(px2->redirects)) {
|
||||
if ((SCHEME_VEC_SIZE(px2->redirects) > 3)
|
||||
|| SCHEME_IMMUTABLEP(px2->redirects))
|
||||
SCHEME_SET_IMMUTABLE(px->redirects);
|
||||
|
|
|
@ -60,8 +60,7 @@ Scheme_Object *PRIM_APPLY_NAME(Scheme_Object *rator,
|
|||
t = _SCHEME_TYPE(rator);
|
||||
|
||||
if ((t == scheme_proc_chaperone_type)
|
||||
&& SCHEME_VECTORP(((Scheme_Chaperone *)rator)->redirects)
|
||||
&& (SCHEME_VEC_SIZE(((Scheme_Chaperone *)rator)->redirects) & 0x1)
|
||||
&& SCHEME_REDIRECTS_PROCEDUREP((((Scheme_Chaperone *)rator)->redirects))
|
||||
&& (SCHEME_CHAPERONE_FLAGS((Scheme_Chaperone *)rator) == SCHEME_PROC_CHAPERONE_CALL_DIRECT)) {
|
||||
if (SCHEME_FALSEP(SCHEME_VEC_ELS(((Scheme_Chaperone *)rator)->redirects)[1])
|
||||
|| SCHEME_INT_VAL(SCHEME_VEC_ELS(((Scheme_Chaperone *)rator)->redirects)[1]) == argc) {
|
||||
|
|
|
@ -1170,6 +1170,15 @@ so we can safely reuse the bit.
|
|||
#define SCHEME_P_CHAPERONEP(obj) (SAME_TYPE(SCHEME_TYPE(obj), scheme_proc_chaperone_type))
|
||||
#define SCHEME_NP_CHAPERONEP(obj) (SAME_TYPE(SCHEME_TYPE(obj), scheme_chaperone_type))
|
||||
|
||||
/* Does the shape of the redirects field match the pattern for particular chaperone types */
|
||||
#define SCHEME_REDIRECTS_PROCEDUREP(red) (SCHEME_VECTORP(red) \
|
||||
&& (SCHEME_VEC_SIZE(red) & 1))
|
||||
#define SCHEME_REDIRECTS_STRUCTP(red) (SCHEME_VECTORP(red) \
|
||||
&& SCHEME_VEC_SIZE(red) \
|
||||
&& !(SCHEME_VEC_SIZE(red) & 1))
|
||||
#define SCHEME_REDIRECTS_PROP_ONLY_VECTORP(red) (SCHEME_VECTORP(red) \
|
||||
&& !(SCHEME_VEC_SIZE(red)))
|
||||
|
||||
#define SCHEME_CHAPERONE_VECTORP(obj) (SCHEME_VECTORP(obj) \
|
||||
|| (SCHEME_NP_CHAPERONEP(obj) && SCHEME_VECTORP(SCHEME_CHAPERONE_VAL(obj))))
|
||||
#define SCHEME_CHAPERONE_BOXP(obj) (SCHEME_BOXP(obj) \
|
||||
|
|
|
@ -1182,9 +1182,8 @@ static Scheme_Object *do_chaperone_prop_accessor(const char *who, Scheme_Object
|
|||
return v;
|
||||
}
|
||||
|
||||
if (!SCHEME_VECTORP(px->redirects)
|
||||
|| (SCHEME_VEC_SIZE(px->redirects) & 1)
|
||||
|| SCHEME_FALSEP(SCHEME_VEC_ELS(px->redirects)[0]))
|
||||
if (!SCHEME_REDIRECTS_STRUCTP(px->redirects)
|
||||
|| SCHEME_FALSEP(SCHEME_VEC_ELS(px->redirects)[0]))
|
||||
arg = px->prev;
|
||||
else {
|
||||
ht = (Scheme_Hash_Tree *)SCHEME_VEC_ELS(px->redirects)[0];
|
||||
|
@ -2253,8 +2252,7 @@ static Scheme_Object *chaperone_struct_ref(const char *who, Scheme_Object *prim,
|
|||
Scheme_Chaperone *px = (Scheme_Chaperone *)o;
|
||||
Scheme_Object *a[2], *red, *orig;
|
||||
|
||||
if (SCHEME_VECTORP(px->redirects)
|
||||
&& !(SCHEME_VEC_SIZE(px->redirects) & 1)
|
||||
if (SCHEME_REDIRECTS_STRUCTP(px->redirects)
|
||||
&& SAME_OBJ(SCHEME_VEC_ELS(px->redirects)[1], scheme_undefined)) {
|
||||
/* chaperone on every field: check that result is not undefined */
|
||||
o = px->prev;
|
||||
|
@ -2269,8 +2267,7 @@ static Scheme_Object *chaperone_struct_ref(const char *who, Scheme_Object *prim,
|
|||
}
|
||||
|
||||
return orig;
|
||||
} else if (!SCHEME_VECTORP(px->redirects)
|
||||
|| (SCHEME_VEC_SIZE(px->redirects) & 1)
|
||||
} else if (!SCHEME_REDIRECTS_STRUCTP(px->redirects)
|
||||
|| SCHEME_FALSEP(SCHEME_VEC_ELS(px->redirects)[PRE_REDIRECTS + i])) {
|
||||
o = px->prev;
|
||||
} else {
|
||||
|
@ -2385,8 +2382,7 @@ static void chaperone_struct_set(const char *who, Scheme_Object *prim,
|
|||
int half;
|
||||
|
||||
o = px->prev;
|
||||
if (SCHEME_VECTORP(px->redirects)
|
||||
&& !(SCHEME_VEC_SIZE(px->redirects) & 1)
|
||||
if (SCHEME_REDIRECTS_STRUCTP(px->redirects)
|
||||
&& !SAME_OBJ(SCHEME_VEC_ELS(px->redirects)[1], scheme_undefined)) {
|
||||
half = (SCHEME_VEC_SIZE(px->redirects) - PRE_REDIRECTS) >> 1;
|
||||
red = SCHEME_VEC_ELS(px->redirects)[PRE_REDIRECTS + half + i];
|
||||
|
@ -2425,8 +2421,7 @@ static void chaperone_struct_set(const char *who, Scheme_Object *prim,
|
|||
return;
|
||||
}
|
||||
}
|
||||
} else if (SCHEME_VECTORP(px->redirects)
|
||||
&& !(SCHEME_VEC_SIZE(px->redirects) & 1)
|
||||
} else if (SCHEME_REDIRECTS_STRUCTP(px->redirects)
|
||||
&& SAME_OBJ(SCHEME_VEC_ELS(px->redirects)[1], scheme_undefined)) {
|
||||
/* chaperone on every field: check that current value is not undefined
|
||||
--- unless check is disabled by a mark (bit it's faster to check
|
||||
|
@ -2996,8 +2991,7 @@ static Scheme_Object *struct_info_chaperone(Scheme_Object *o, Scheme_Object *si,
|
|||
|
||||
while (SCHEME_CHAPERONEP(o)) {
|
||||
px = (Scheme_Chaperone *)o;
|
||||
if (SCHEME_VECTORP(px->redirects)
|
||||
&& !(SCHEME_VEC_SIZE(px->redirects) & 1)) {
|
||||
if (SCHEME_REDIRECTS_STRUCTP(px->redirects)) {
|
||||
proc = SCHEME_VEC_ELS(px->redirects)[1];
|
||||
if (SCHEME_TRUEP(proc) && !SAME_OBJ(proc, scheme_undefined)) {
|
||||
if (SCHEME_CHAPERONE_FLAGS(px) & SCHEME_CHAPERONE_IS_IMPERSONATOR)
|
||||
|
|
|
@ -499,7 +499,7 @@ Scheme_Object *scheme_chaperone_vector_ref2(Scheme_Object *o, int i, Scheme_Obje
|
|||
|
||||
orig = scheme_chaperone_vector_ref2(px->prev, i, outermost);
|
||||
|
||||
if (SCHEME_VECTORP(px->redirects)) {
|
||||
if (SCHEME_REDIRECTS_PROP_ONLY_VECTORP(px->redirects)) {
|
||||
/* chaperone was on property accessors */
|
||||
/* or vector chaperone is property only */
|
||||
return orig;
|
||||
|
@ -580,7 +580,7 @@ void scheme_chaperone_vector_set(Scheme_Object *o, int i, Scheme_Object *v)
|
|||
|
||||
o = px->prev;
|
||||
|
||||
if (!SCHEME_VECTORP(red)) {
|
||||
if (!SCHEME_REDIRECTS_PROP_ONLY_VECTORP(red)) {
|
||||
/* not a property only chaperone */
|
||||
red = SCHEME_CDR(px->redirects);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user