Skip to content

Instantly share code, notes, and snippets.

@niner
Created September 27, 2014 08:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niner/493268db5ba449caef49 to your computer and use it in GitHub Desktop.
Save niner/493268db5ba449caef49 to your computer and use it in GitHub Desktop.
SEGFAULTs in S_mg_findext_flags because obj_deref in line 110 is a broken SV.
#include <EXTERN.h>
#include <XSUB.h>
#include <perl.h>
static void xs_init (pTHX);
EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
EXTERN_C void boot_Socket (pTHX_ CV* cv);
XS(p5_call_p6_method);
EXTERN_C void xs_init(pTHX) {
char *file = __FILE__;
newXS("Perl6::Object::call_method", p5_call_p6_method, file);
}
PerlInterpreter *my_perl;
PerlInterpreter *p5_init_perl() {
char *embedding[] = { "", "-e", "0" };
PERL_SYS_INIT3(0, NULL, NULL);
my_perl = perl_alloc();
PERL_SET_CONTEXT(my_perl);
PL_perl_destruct_level = 1;
perl_construct( my_perl );
perl_parse(my_perl, xs_init, 3, embedding, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
return my_perl;
}
AV *p5_call_function(PerlInterpreter *my_perl, char *name, int len, SV *args[]) {
dSP;
int i;
int count;
AV * const retval = newAV();
int flags = G_ARRAY | G_EVAL;
PERL_SET_CONTEXT(my_perl);
ENTER;
SAVETMPS;
PUSHMARK(SP);
for (i = 0; i < len; i++) {
XPUSHs(sv_2mortal(args[i]));
}
PUTBACK;
count = call_pv(name, flags);
return retval;
}
typedef struct {
I32 key; /* to make sure it came from Inline */
IV index;
SV *(*call_p6_method)(int, char *, SV *, SV **);
} _perl6_magic;
#define PERL6_MAGIC_KEY 0x0DD515FE
SV *p5_wrap_p6_object(PerlInterpreter *my_perl, IV i, SV *p5obj, SV *(*call_p6_method)(int, char * , SV *, SV **)) {
SV * inst;
SV * inst_ptr;
if (p5obj == NULL) {
inst_ptr = newSViv(0);
inst = newSVrv(inst_ptr, "Perl6::Object");
}
else {
inst_ptr = p5obj;
inst = SvRV(inst_ptr);
SvREFCNT_inc(inst_ptr);
}
_perl6_magic priv;
/* set up magic */
priv.key = PERL6_MAGIC_KEY;
priv.index = i;
priv.call_p6_method = call_p6_method;
sv_magic(inst, inst, PERL_MAGIC_ext, (char *) &priv, sizeof(priv));
MAGIC * const mg = mg_find(inst, PERL_MAGIC_ext);
return inst_ptr;
}
SV *call_p6_method(int obj, char *name, SV *i, SV **args) {
}
XS(p5_call_p6_method) {
dXSARGS;
SV * name = ST(0);
SV * obj = ST(1);
AV * args = newAV();
av_extend(args, items - 2);
int i;
for (i = 0; i < items - 2; i++) {
SV * const next = SvREFCNT_inc(ST(i + 2));
if (av_store(args, i, next) == NULL)
SvREFCNT_dec(next); /* see perlguts Working with AVs */
}
STRLEN len;
char * const name_pv = SvPV(name, len);
char * const name_str = savepvn(name_pv, len);
SV * const obj_deref = SvRV(obj);
MAGIC * const mg = mg_find(obj_deref, '~');
_perl6_magic* const p6mg = (_perl6_magic*)(mg->mg_ptr);
SV *err = NULL;
return newRV_inc((SV*)p5_call_function(my_perl, "zero", 0, NULL));
}
int main(int argc, char **argv) {
PerlInterpreter *my_perl = p5_init_perl();
eval_pv("\
package Perl6::Object;\
\
our $AUTOLOAD;\
sub AUTOLOAD {\
my ($self) = @_;\
warn qq{AUTOLOAD $AUTOLOAD};\
my $name = $AUTOLOAD =~ s/.*:://r;\
Perl6::Object::call_method($name, @_);\
}\
\
", 1);
eval_pv("\
sub zero {\
warn 'zero';\
return 1;\
}\
sub one {\
my ($obj) = @_;\
warn 'callback one';\
return $obj->foo;\
}\
", 1);
SV *callme = p5_wrap_p6_object(my_perl, 0, NULL, &call_p6_method);
p5_call_function(my_perl, "one", 1, &callme);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment