Skip to content

Commit a886a77

Browse files
committed
Properly handle non-Sixmodel objects in dyncall ops.
Two issues: - decontainerize in nqp_dyncall.ops was out of sync with decontainerize in sixmodelobject.c (didn't consider possibility of non-SMO arguments) - unmarshalling code (to int/float types) need to dispatch to VTABLE_get_* in case of non-SMO arguments. FROGGS++ for uncovering the problem.
1 parent c223607 commit a886a77

File tree

1 file changed

+57
-18
lines changed

1 file changed

+57
-18
lines changed

src/ops/nqp_dyncall.ops

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ static INTVAL cs_repr_id = 0;
9090
static INTVAL cp_repr_id = 0;
9191
static INTVAL ca_repr_id = 0;
9292
static INTVAL cstr_repr_id = 0;
93+
static INTVAL smo_id = 0;
9394

9495
PMC *callback_cache = NULL;
9596

@@ -331,41 +332,58 @@ make_carray_result(PARROT_INTERP, PMC *type, void *carray) {
331332

332333
static DCchar
333334
unmarshal_char(PARROT_INTERP, PMC *value) {
335+
if (value->vtable->base_type != smo_id)
336+
return (DCchar) VTABLE_get_integer(interp, value);
334337
return (DCchar)REPR(value)->box_funcs->get_int(interp, STABLE(value), OBJECT_BODY(value));
335338
}
336339

337340
static DCshort
338341
unmarshal_short(PARROT_INTERP, PMC *value) {
342+
if (value->vtable->base_type != smo_id)
343+
return (DCshort) VTABLE_get_integer(interp, value);
339344
return (DCshort)REPR(value)->box_funcs->get_int(interp, STABLE(value), OBJECT_BODY(value));
340345
}
341346

342347
static DCint
343348
unmarshal_int(PARROT_INTERP, PMC *value) {
349+
if (value->vtable->base_type != smo_id)
350+
return (DCint) VTABLE_get_integer(interp, value);
344351
return (DCint)REPR(value)->box_funcs->get_int(interp, STABLE(value), OBJECT_BODY(value));
345352
}
346353

347354
static DClong
348355
unmarshal_long(PARROT_INTERP, PMC *value) {
356+
if (value->vtable->base_type != smo_id)
357+
return (DClong) VTABLE_get_integer(interp, value);
349358
return (DClong)REPR(value)->box_funcs->get_int(interp, STABLE(value), OBJECT_BODY(value));
350359
}
351360

352361
static DClonglong
353362
unmarshal_longlong(PARROT_INTERP, PMC *value) {
363+
if (value->vtable->base_type != smo_id)
364+
return (DClonglong) VTABLE_get_integer(interp, value);
354365
return (DClonglong)REPR(value)->box_funcs->get_int(interp, STABLE(value), OBJECT_BODY(value));
355366
}
356367

357368
static DCfloat
358369
unmarshal_float(PARROT_INTERP, PMC *value) {
370+
if (value->vtable->base_type != smo_id)
371+
return (DCfloat) VTABLE_get_number(interp, value);
359372
return (DCfloat)REPR(value)->box_funcs->get_num(interp, STABLE(value), OBJECT_BODY(value));
360373
}
361374

362375
static DCdouble
363376
unmarshal_double(PARROT_INTERP, PMC *value) {
377+
if (value->vtable->base_type != smo_id)
378+
return (DCdouble) VTABLE_get_number(interp, value);
364379
return (DCdouble)REPR(value)->box_funcs->get_num(interp, STABLE(value), OBJECT_BODY(value));
365380
}
366381

367382
static char *
368383
unmarshal_string(PARROT_INTERP, PMC *value, INTVAL type, INTVAL *free) {
384+
if (value->vtable->base_type != smo_id)
385+
return Parrot_str_to_encoded_cstring(interp, VTABLE_get_string(interp, value), Parrot_utf8_encoding_ptr);
386+
369387
if (IS_CONCRETE(value)) {
370388
char *str;
371389
PMC *meth = VTABLE_find_method(interp, STABLE(value)->WHAT,
@@ -404,11 +422,15 @@ unmarshal_string(PARROT_INTERP, PMC *value, INTVAL type, INTVAL *free) {
404422
else {
405423
return NULL;
406424
}
407-
return NULL;
425+
return NULL;
408426
}
409427

410428
static void *
411429
unmarshal_cstruct(PARROT_INTERP, PMC *value) {
430+
if (value->vtable->base_type != smo_id)
431+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
432+
"Can't unmarshal non-sixmodel PMC to struct");
433+
412434
if (!IS_CONCRETE(value))
413435
return NULL;
414436
else if (REPR(value)->ID == cs_repr_id)
@@ -420,6 +442,10 @@ unmarshal_cstruct(PARROT_INTERP, PMC *value) {
420442

421443
static void *
422444
unmarshal_carray(PARROT_INTERP, PMC *value) {
445+
if (value->vtable->base_type != smo_id)
446+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
447+
"Can't unmarshal non-sixmodel PMC to array");
448+
423449
if (!IS_CONCRETE(value))
424450
return NULL;
425451
else if (REPR(value)->ID == ca_repr_id)
@@ -431,6 +457,10 @@ unmarshal_carray(PARROT_INTERP, PMC *value) {
431457

432458
static void *
433459
unmarshal_cpointer(PARROT_INTERP, PMC *value) {
460+
if (value->vtable->base_type != smo_id)
461+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
462+
"Can't unmarshal non-sixmodel PMC to opaque pointer");
463+
434464
if (!IS_CONCRETE(value))
435465
return NULL;
436466
else if (REPR(value)->ID == cp_repr_id)
@@ -444,6 +474,11 @@ static void *
444474
unmarshal_callback(PARROT_INTERP, PMC *value, PMC *info) {
445475
PMC *callback_data;
446476

477+
if (value->vtable->base_type != smo_id)
478+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
479+
"Can't unmarshal non-sixmodel PMC to callback");
480+
481+
447482
if (!IS_CONCRETE(value)) {
448483
return NULL;
449484
}
@@ -510,23 +545,25 @@ unmarshal_callback(PARROT_INTERP, PMC *value, PMC *info) {
510545
}
511546

512547
PMC * decontainerize(PARROT_INTERP, PMC *var) {
513-
ContainerSpec *spec = STABLE(var)->container_spec;
514-
if (spec && IS_CONCRETE(var)) {
515-
if (!PMC_IS_NULL(spec->value_slot.class_handle)) {
516-
/* Just get slot. */
517-
return VTABLE_get_attr_keyed(interp, var, spec->value_slot.class_handle,
518-
spec->value_slot.attr_name);
519-
}
520-
else {
521-
/* Invoke FETCH method. */
522-
PMC *old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
523-
PMC *meth = spec->fetch_method;
524-
PMC *cappy = Parrot_pmc_new(interp, enum_class_CallContext);
525-
VTABLE_push_pmc(interp, cappy, var);
526-
Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
527-
cappy = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
528-
Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
529-
return VTABLE_get_pmc_keyed_int(interp, cappy, 0);
548+
if (var->vtable->base_type == smo_id) {
549+
ContainerSpec *spec = STABLE(var)->container_spec;
550+
if (spec && IS_CONCRETE(var)) {
551+
if (!PMC_IS_NULL(spec->value_slot.class_handle)) {
552+
/* Just get slot. */
553+
return VTABLE_get_attr_keyed(interp, var, spec->value_slot.class_handle,
554+
spec->value_slot.attr_name);
555+
}
556+
else {
557+
/* Invoke FETCH method. */
558+
PMC *old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
559+
PMC *meth = spec->fetch_method;
560+
PMC *cappy = Parrot_pmc_new(interp, enum_class_CallContext);
561+
VTABLE_push_pmc(interp, cappy, var);
562+
Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
563+
cappy = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
564+
Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
565+
return VTABLE_get_pmc_keyed_int(interp, cappy, 0);
566+
}
530567
}
531568
}
532569
return var;
@@ -782,6 +819,8 @@ inline op nqp_native_call_setup() :base_core {
782819
cstr_repr_id = REGISTER_DYNAMIC_REPR(interp,
783820
Parrot_str_new_constant(interp, "CStr"),
784821
CStr_initialize);
822+
if (!smo_id)
823+
smo_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "SixModelObject", 0));
785824
}
786825

787826

0 commit comments

Comments
 (0)