From 1e8125c621275d18c74bc8dae3bfc3c03929fe1e Mon Sep 17 00:00:00 2001 From: Florian Ragwitz Date: Tue, 20 Jul 2010 22:58:24 +0200 Subject: Check API compatibility when loading xs modules This adds PL_apiversion, allowing the API version of a running interpreter to be introspected. It is used in the new XS_APIVERSION_BOOTCHECK macro, which is added to the _boot function of every XS module, to compare it against the API version the module has been compiled against. If the versions do not match, an exception is thrown. This doesn't fully prevent binary incompatible extensions to be loaded. It merely compares PERL_API_* between compile- and runtime, and does not attempt to solve the problem of identifying binary incompatible perls with the same API version (i.e. the same perl version configured with and without DEBUGGING). --- XSUB.h | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'XSUB.h') diff --git a/XSUB.h b/XSUB.h index f3ba8027cd..939a7a64f7 100644 --- a/XSUB.h +++ b/XSUB.h @@ -243,6 +243,10 @@ Macro to verify that a PM module's $VERSION variable matches the XS module's C variable. This is usually handled automatically by C. See L. +=for apidoc Ams||XS_APIVERSION_BOOTCHECK +Macro to verify that the perl api version an XS module has been compiled against +matches the api version of the perl interpreter it's being loaded into. + =head1 Simple Exception Handling Macros =for apidoc Ams||dXCPT @@ -335,6 +339,26 @@ Rethrows a previously caught exception. See L. # define XS_VERSION_BOOTCHECK #endif +#define XS_APIVERSION_BOOTCHECK \ + STMT_START { \ + SV *_xpt = NULL; \ + SV *_compver = Perl_newSVpv(aTHX_ "v" PERL_API_VERSION_STRING, 0); \ + SV *_runver = new_version(PL_apiversion); \ + _compver = upg_version(_compver, 0); \ + if (vcmp(_compver, _runver)) { \ + _xpt = Perl_newSVpvf(aTHX_ "Perl API version %"SVf \ + " of %s does not match %"SVf, \ + SVfARG(Perl_sv_2mortal(aTHX_ vstringify(_compver))), \ + SvPV_nolen_const(ST(0)), \ + SVfARG(Perl_sv_2mortal(aTHX_ vstringify(_runver)))); \ + Perl_sv_2mortal(aTHX_ _xpt); \ + } \ + SvREFCNT_dec(_compver); \ + SvREFCNT_dec(_runver); \ + if (_xpt) \ + Perl_croak_sv(aTHX_ _xpt); \ + } STMT_END + #ifdef NO_XSLOCKS # define dXCPT dJMPENV; int rEtV = 0 # define XCPT_TRY_START JMPENV_PUSH(rEtV); if (rEtV == 0) @@ -343,9 +367,9 @@ Rethrows a previously caught exception. See L. # define XCPT_RETHROW JMPENV_JUMP(rEtV) #endif -/* - The DBM_setFilter & DBM_ckFilter macros are only used by - the *DB*_File modules +/* + The DBM_setFilter & DBM_ckFilter macros are only used by + the *DB*_File modules */ #define DBM_setFilter(db_type,code) \ -- cgit v1.2.1