t/op/calling_61.pir crashes because Parrot's trying to treat the number -1 as 
a PMC.  Why?

Parrot_convert_arg (interp=0x804f040, st=0xbf8b70c0) at src/inter_call.c:905
905         if (key->vtable->base_type != enum_class_Key)
(gdb) bt
#0  Parrot_convert_arg (interp=0x804f040, st=0xbf8b70c0)
    at src/inter_call.c:905
#1  0xb7d39d51 in set_nci_P (interp=0x804f040, st=0xbf8b70c0, val=0xffffffff)
    at src/nci.c:150
#2  0xb7d3ce40 in pcf_P_JPP (interp=0x804f040, self=0x80da230)
    at src/nci.c:1771
#3  0xb7e3532e in Parrot_NCI_invoke (interp=0x804f040, pmc=0x80da230, 
next=0x0)
    at ./src/pmc/nci.pmc:309
#4  0xb7d1c534 in Parrot_pcc_invoke_sub_from_sig_object (interp=0x804f040, 
    sub_obj=0x80da230, sig_obj=0x80f38f8) at src/inter_call.c:2471
#5  0xb7d27b80 in Parrot_mmd_multi_dispatch_from_c_args (interp=0x804f040, 
    name=0xb7f2bc3e "cmp", sig=0xb7f03acf "PP->I") at src/multidispatch.c:629
#6  0xb7e00166 in Parrot_default_cmp (interp=0x804f040, pmc=0x80f3930, 
    value=0x80f3914) at ./src/pmc/default.pmc:2447
#7  0xb7ccacfa in Parrot_lt_p_i_ic (cur_opcode=0x8127c88, interp=0x804f040)
    at src/ops/cmp.ops:315

The desired MMD sub should take two PMCs and returns an INTVAL (frame #5, 
signature "PP->I"), but the invoked MMD sub takes two PMCs and returns a PMC.  
The crash comes in convert_arg, where the C function has returned INTVAL -1, 
but the argument passing code expects that it has returned and Integer PMC.  
Because 0xffffffff isn't a valid PMC pointer, there's a crash.

If you look at src/pmc/integer.pmc, the cmp MULTIs there return INTVALs 
(signature IJPP), but the MULTI registration code declares them as signature 
PJPP.  I modified Parrot::Pmc2c::MULTI to improve the return-value-of-cmp 
regexp and the test passes.

-- c
Index: lib/Parrot/Pmc2c/MULTI.pm
===================================================================
--- lib/Parrot/Pmc2c/MULTI.pm	(revision 30934)
+++ lib/Parrot/Pmc2c/MULTI.pm	(working copy)
@@ -93,7 +93,7 @@
     # prepend the short signature return type
     if ($self->name =~ /^i_/) {
         $short_sig = "v" . $short_sig;
-    } elsif ($self->name =~ /^is_/ or $self->name =~ /^cmp_/) {
+    } elsif ($self->name =~ /^is_/ or $self->name =~ /\bcmp\b/) {
         $short_sig = "I" . $short_sig;
     } else {
         $short_sig = "P" . $short_sig;

Reply via email to