Commit 6f231de3 authored by Florian Schlichting's avatar Florian Schlichting

Import original source of Lexical-SealRequireHints 0.007

parents
/Build
/Makefile
/_build
/blib
/META.json
/META.yml
/MYMETA.json
/MYMETA.yml
/Makefile.PL
/SIGNATURE
/Lexical-SealRequireHints-*
/lib/Lexical/SealRequireHints.c
/lib/Lexical/SealRequireHints.o
{ use 5.006; }
use warnings;
use strict;
use Module::Build;
my $require_xs = "$]" < 5.007002 || ("$]" >= 5.009004 && "$]" < 5.010001);
Module::Build->subclass(code => q{
unless(__PACKAGE__->can("cbuilder")) {
*cbuilder = sub { $_[0]->_cbuilder or die "no C support" };
}
unless(__PACKAGE__->can("have_c_compiler")) {
*have_c_compiler = sub {
my $cb = eval { $_[0]->cbuilder };
return $cb && $cb->have_compiler;
};
}
if($Module::Build::VERSION < 0.33) {
# Older versions of Module::Build have a bug where if the
# cbuilder object is used at Build.PL time (which it will
# be for this distribution due to the logic in
# ->find_xs_files) then that object can be dumped to the
# build_params file, and then at Build time it will
# attempt to use the dumped blessed object without loading
# the ExtUtils::CBuilder class that is needed to make it
# work.
*write_config = sub {
delete $_[0]->{properties}->{_cbuilder};
return $_[0]->SUPER::write_config;
};
}
sub find_xs_files {
my($self) = @_;
return {} unless $self->have_c_compiler;
# On MSWin32, the XS version of the workaround can't work
# properly, because it doesn't have access to the core
# symbols to let SAVEHINTS() work.
return {} if "$]" < 5.012 && $^O eq "MSWin32";
return $self->SUPER::find_xs_files;
}
sub compile_c {
my($self, $file, %args) = @_;
if("$]" < 5.012) {
# need PERL_CORE for working SAVEHINTS()
$args{defines} = { %{$args{defines} || {}},
PERL_CORE => 1,
};
}
return $self->SUPER::compile_c($file, %args);
}
})->new(
module_name => "Lexical::SealRequireHints",
license => "perl",
configure_requires => {
"Module::Build" => 0,
"perl" => "5.006",
"strict" => 0,
"warnings" => 0,
($require_xs ? (
"ExtUtils::CBuilder" => "0.15",
) : ()),
},
configure_recommends => {
($require_xs ? () : (
"ExtUtils::CBuilder" => "0.15",
)),
},
build_requires => {
"Module::Build" => 0,
"Test::More" => 0,
"perl" => "5.006",
"strict" => 0,
"warnings" => 0,
($require_xs ? (
"ExtUtils::CBuilder" => "0.15",
) : ()),
},
build_recommends => {
($require_xs ? () : (
"ExtUtils::CBuilder" => "0.15",
)),
},
requires => {
"perl" => "5.006",
($require_xs ? (
"XSLoader" => 0,
) : ()),
},
recommends => {
($require_xs ? () : (
"XSLoader" => 0,
)),
},
conflicts => {
"B::Hooks::OP::Check" => "< 0.19",
},
needs_compiler => 0,
dynamic_config => 1,
meta_add => { distribution_type => "module" },
create_makefile_pl => "passthrough",
sign => 1,
)->create_build_script;
1;
version 0.007; 2012-02-11
* be thread-safe, by mutex control on op check hooking
* in pure Perl implementation, avoid putting extra eval stack frames
around the require, to avoid unnecessary complication of exception
handling; this can't be done on Perls 5.9.4 to 5.10.0, so don't
allow use of the pure Perl implementation on those Perls
* revise documentation to suggest loading this module earlier
* document the relevant changes to the Perl core in more detail
* on Perl versions where the pure Perl implementation can't work,
dynamically declare requirement for XS infrastructure in Build.PL
* refine threshold for ability to correctly override require from
5.8.0 to 5.7.2
* revise minimum required Perl version down from 5.6.1 to 5.6.0
* test that modules see the correct context at file scope
* test that module return values are handled correctly
* test that the module doesn't generate warnings
* in pure Perl implementation, fix handling of the variable that
previously needed to be "our"
* rearrange and better comment the treatment of lexical warnings in
the Perl code
version 0.006; 2011-11-20
* bugfix: avoid loading warnings.pm and leaving its delayed requires
of Carp.pm susceptible to hint leakage, which was causing trouble
on some Perls
* skip swash test on Perl 5.6, where swash loading appears to be broken
by loading Test::More or anything else useful
* remove bogus tests that cause false failures on Perl 5.15.5
* in Build.PL, declare incompatibility with pre-0.19
B::Hooks::OP::Check, which doesn't play nicely around op check hooking
* comment why a variable surprisingly needs to be "our"
* convert .cvsignore to .gitignore
version 0.005; 2011-07-25
* bugfix: work around core bug [perl #73174] affecting Unicode swash
loading, and apply entire workaround arrangement to 5.11.{0..5}
where [perl #73174] exists but [perl #68590] does not
* correct dynamic_config setting to 0
* include META.json in distribution
* add MYMETA.json to .cvsignore
version 0.004; 2010-11-21
* bugfix: don't attempt to use XS version of the workaround on Win32,
where it can't work properly due to linker restriction on access to
core symbols
* only define PERL_CORE for compilation on Perl versions where the
bug workaround (and thus interference with core-private stuff)
is actually necessary
* in XS, use PERL_NO_GET_CONTEXT for efficiency
* in XS, declare "PROTOTYPES: DISABLE" to prevent automatic generation
of unintended prototypes
* in XS, provide a reserve definition of croak, so that the Perl_croak
circumlocution is avoided even with PERL_CORE defined
* in XS, give symbolic names to the Perl version thresholds
* jump through hoops to avoid compiler warnings
* use full stricture in test suite
* also test POD coverage of pure Perl implementation
* in t/setup_pp.pl, avoid a warning that occurs if XSLoader::load()
is given no arguments, which is now a valid usage
* in Build.PL, explicitly set needs_compiler to avoid bogus
auto-dependency on ExtUtils::CBuilder
* in Build.PL, complete declaration of configure-time requirements
version 0.003; 2010-04-10
* bugfix: in pure-Perl implementation, make sure ambient package (from
which require is invoked) is passed on correctly to the code in the
required file, on those Perls where it is so inherited
* in XS, use macros to avoid explicit passing of aTHX, in the manner
of the core
* in XS, avoid using "class" as a variable name, for compatibility
with C++ compilers
* make all numeric comparisons against $] stringify it first, to avoid
architecture-dependent problems with floating point rounding giving
it an unexpected numeric value
* in Build.PL, explicitly declare configure-time requirements
* add MYMETA.yml to .cvsignore
version 0.002; 2009-10-21
* generate a more normal-looking op tree, that doesn't crash B::Deparse
* don't apply the workaround on Perl 5.11.0 or later, where the bug
has been fixed
* in t/seal.t, test that cop_hints_hash is properly handled
* check for required Perl version at runtime
version 0.001; 2009-09-26
* bugfix: die cleanly if the pure-Perl implementation is needed but
won't work (which occurs on pre-5.8 perls)
* bugfix: avoid undesired warning from pure-Perl implementation if
require has already been overridden via CORE::GLOBAL::require
* in tests, set HINT_LOCALIZE_HH where appropriate, to avoid false
test failures on pre-5.10 perls
* test that the module plays nicely with code that overrides require
via CORE::GLOBAL::require
version 0.000; 2009-09-22
* initial released version
.gitignore
Build.PL
Changes
MANIFEST
META.json
META.yml
Makefile.PL
README
lib/Lexical/SealRequireHints.pm
lib/Lexical/SealRequireHints.xs
t/before_warnings.t
t/before_warnings_pp.t
t/context.t
t/context_0.pm
t/context_1.pm
t/context_2.pm
t/context_pp.t
t/eval.t
t/eval_0.pm
t/eval_pp.t
t/override.t
t/override_pp.t
t/package.t
t/package_0.pm
t/package_pp.t
t/pod_cvg.t
t/pod_cvg_pp.t
t/pod_syn.t
t/seal.t
t/seal_0.pm
t/seal_1.pm
t/seal_2.pm
t/seal_3.pm
t/seal_4.pm
t/seal_pp.t
t/setup_pp.pl
t/swash.t
t/swash_pp.t
t/threads.t
t/threads_pp.t
SIGNATURE Added here by Module::Build
NAME
Lexical::SealRequireHints - prevent leakage of lexical hints
DESCRIPTION
This module works around two historical bugs in Perl's handling of the
"%^H" (lexical hints) variable. One bug causes lexical state in one file
to leak into another that is "require"d/"use"d from it. This bug, [perl
#68590], was present from Perl 5.6 up to Perl 5.10, fixed in Perl 5.11.0.
The second bug causes lexical state (normally a blank "%^H" once the first
bug is fixed) to leak outwards from "utf8.pm", if it is automatically
loaded during Unicode regular expression matching, into whatever source
is compiling at the time of the regexp match. This bug, [perl #73174],
was present from Perl 5.8.7 up to Perl 5.11.5, fixed in Perl 5.12.0.
Both of these bugs seriously damage the usability of any module relying
on "%^H" for lexical scoping, on the affected Perl versions. It is in
practice essential to work around these bugs when using such modules.
On versions of Perl that require such a workaround, this module globally
changes the behaviour of "require", including "use" and the implicit
"require" performed in Unicode regular expression matching, so that it
no longer exhibits these bugs.
The workaround supplied by this module takes effect the first time its
"import" method is called. Typically this will be done by means of a
"use" statement. This should be done as early as possible, because
it only affects "require"/"use" statements that are compiled after
the workaround goes into effect. For "use" statements, and "require"
statements that are executed immediately and only once, it suffices to
invoke the workaround when loading the first module that will set up
vulnerable lexical state. Delayed-action "require" statements, however,
are more troublesome, and can require the workaround to be loaded
much earlier. Ultimately, an affected Perl program may need to load
the workaround as very nearly its first action. Invoking this module
multiple times, from multiple modules, is not a problem: the workaround
is only applied once, and applies to everything subsequently compiled.
This module is implemented in XS, with a pure Perl backup version for
systems that can't handle XS modules. The XS version has a better chance
of playing nicely with other modules that modify "require" handling.
The pure Perl version can't work at all on some Perl versions; users of
those versions must use the XS.
INSTALLATION
perl Build.PL
./Build
./Build test
./Build install
AUTHOR
Andrew Main (Zefram) <zefram@fysh.org>
COPYRIGHT
Copyright (C) 2009, 2010, 2011, 2012
Andrew Main (Zefram) <zefram@fysh.org>
LICENSE
This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
=head1 NAME
Lexical::SealRequireHints - prevent leakage of lexical hints
=head1 SYNOPSIS
use Lexical::SealRequireHints;
=head1 DESCRIPTION
This module works around two historical bugs in Perl's handling of the
C<%^H> (lexical hints) variable. One bug causes lexical state in one
file to leak into another that is C<require>d/C<use>d from it. This bug,
[perl #68590], was present from Perl 5.6 up to Perl 5.10, fixed in Perl
5.11.0. The second bug causes lexical state (normally a blank C<%^H>
once the first bug is fixed) to leak outwards from C<utf8.pm>, if it is
automatically loaded during Unicode regular expression matching, into
whatever source is compiling at the time of the regexp match. This bug,
[perl #73174], was present from Perl 5.8.7 up to Perl 5.11.5, fixed in
Perl 5.12.0.
Both of these bugs seriously damage the usability of any module relying
on C<%^H> for lexical scoping, on the affected Perl versions. It is in
practice essential to work around these bugs when using such modules.
On versions of Perl that require such a workaround, this module globally
changes the behaviour of C<require>, including C<use> and the implicit
C<require> performed in Unicode regular expression matching, so that it
no longer exhibits these bugs.
The workaround supplied by this module takes effect the first time its
C<import> method is called. Typically this will be done by means of a
C<use> statement. This should be done as early as possible, because it
only affects C<require>/C<use> statements that are compiled after the
workaround goes into effect. For C<use> statements, and C<require>
statements that are executed immediately and only once, it suffices
to invoke the workaround when loading the first module that will set
up vulnerable lexical state. Delayed-action C<require> statements,
however, are more troublesome, and can require the workaround to be loaded
much earlier. Ultimately, an affected Perl program may need to load
the workaround as very nearly its first action. Invoking this module
multiple times, from multiple modules, is not a problem: the workaround
is only applied once, and applies to everything subsequently compiled.
This module is implemented in XS, with a pure Perl backup version for
systems that can't handle XS modules. The XS version has a better chance
of playing nicely with other modules that modify C<require> handling.
The pure Perl version can't work at all on some Perl versions; users of
those versions must use the XS.
=head1 PERL VERION DIFFERENCES
The history of the C<%^H> bugs is complex. Here is a chronological
statement of the relevant changes.
=over
=item Perl 5.6.0
C<%^H> introduced. It exists only as a hash at compile time. It is not
localised by C<require>, so lexical hints leak into every module loaded,
which is bug [perl #68590].
The C<CORE::GLOBAL> mechanism doesn't work cleanly for C<require>, because
overriding C<require> loses the necessary special parsing of bareword
arguments to it. As a result, pure Perl code can't properly globally
affect the behaviour of C<require>. Pure Perl code can localise C<%^H>
itself for any particular C<require> invocation, but a global fix is
only possible through XS.
=item Perl 5.7.2
The C<CORE::GLOBAL> mechanism now works cleanly for C<require>, so pure
Perl code can globally affect the behaviour of C<require> to achieve a
global fix for the bug.
=item Perl 5.8.7
When C<utf8.pm> is automatically loaded during Unicode regular expression
matching, C<%^H> now leaks outward from it into whatever source is
compiling at the time of the regexp match, which is bug [perl #73174].
It often goes unnoticed, because [perl #68590] makes C<%^H> leak into
C<utf8.pm> which then doesn't modify it, so what leaks out tends to
be identical to what leaked in. If [perl #68590] is worked around,
however, C<%^H> tends to be (correctly) blank inside C<utf8.pm>, and
this bug therefore blanks it for the outer module.
=item Perl 5.9.4
C<%^H> now exists in two forms. In addition to the relatively ordinary
hash that is modified during compilation, the value that it had at
each point in compilation is recorded in the compiled op tree, for later
examination at runtime. It is in a special representation-sharing format,
and writes to C<%^H> are meant to be performed on both forms. C<require>
does not localise the runtime form of C<%^H> (and still doesn't localise
the compile-time form).
A couple of special C<%^H> entries are erroneously written only to the
runtime form.
Pure Perl code, although it can localise the compile-time C<%^H> by
normal means, can't adequately localise the runtime C<%^H>, except by
using a string eval stack frame. This makes a satisfactory global fix
for the leakage bug impossible in pure Perl.
=item Perl 5.10.1
C<require> now properly localises the runtime form of C<%^H>, but still
not the compile-time form.
A global fix is once again possible in pure Perl, because the fix only
needs to localise the compile-time form.
=item Perl 5.11.0
C<require> now properly localises both forms of C<%^H>, fixing [perl
#68590]. This makes [perl #73174] apparent without any workaround for
[perl #68590].
The special C<%^H> entries are now correctly written to both forms of
the hash.
=item Perl 5.12.0
The automatic loading of C<utf8.pm> during Unicode regular expression
matching now properly restores C<%^H>, fixing [perl #73174].
=back
=cut
package Lexical::SealRequireHints;
{ use 5.006; }
# Don't "use warnings" here because warnings.pm can include require
# statements that execute at runtime, and if they're compiled before
# this module takes effect then they won't get the magic needed to avoid
# leaking hints generated later. We do need to set warning bits here,
# because it is necessary to turn *off* redefinition warnings for the
# pure Perl implementation (which can redefine CORE::GLOBAL::require).
# Not wanting to encode knowledge of specific warning bits, the only
# safe thing to do is to turn them all off.
BEGIN { ${^WARNING_BITS} = ""; }
# Also don't "use strict", because of consequences of compiling
# strict.pm's code.
our $VERSION = "0.007";
if("$]" >= 5.012) {
# bug not present
*import = sub {
die "$_[0] does not take any importation arguments\n"
unless @_ == 1;
};
*unimport = sub { die "$_[0] does not support unimportation\n" };
} elsif(eval { local $SIG{__DIE__};
require XSLoader;
XSLoader::load(__PACKAGE__, $VERSION);
1;
}) {
# Successfully loaded XS. Now preemptively load modules that
# may be subject to delayed require statements in XSLoader or
# things that it loaded.
foreach(qw(Carp.pm Carp/Heavy.pm)) {
eval { local $SIG{__DIE__}; require($_); };
}
} elsif("$]" >= 5.007002 && !("$]" >= 5.009004 && "$]" < 5.010001)) {
my $done;
*import = sub {
die "$_[0] does not take any importation arguments\n"
unless @_ == 1;
return if $done;
$done = 1;
my $next_require = defined(&CORE::GLOBAL::require) ?
\&CORE::GLOBAL::require : sub {
my($arg) = @_;
# The shenanigans with $CORE::GLOBAL::{require}
# are required because if there's a
# &CORE::GLOBAL::require when the eval is
# executed (compiling the CORE::require it
# contains) then the CORE::require in there is
# interpreted as plain require on some Perl
# versions, leading to recursion.
my $grequire = $CORE::GLOBAL::{require};
delete $CORE::GLOBAL::{require};
my $requirer = eval qq{
package @{[scalar(caller(0))]};
sub { scalar(CORE::require(\$_[0])) };
};
$CORE::GLOBAL::{require} = $grequire;
return scalar($requirer->($arg));
};
*CORE::GLOBAL::require = sub {
die "wrong number of arguments to require\n"
unless @_ == 1;
my($arg) = @_;
# Some reference to $next_require is required
# at this level of subroutine so that it will
# be closed over and hence made available to
# the string eval below.
my $nr = $next_require;
# Compile-time %^H gets localised by the
# "local %^H". Runtime %^H doesn't exist prior
# to Perl 5.9.4, and on Perl 5.10.1 and above is
# correctly localised by require. Between those
# two regimes there's an area where we can't
# correctly localise runtime %^H in pure Perl,
# short of putting an eval frame around the
# require, so we don't use this implementation in
# that region. On Perl 5.11 we need to set the
# HINT_LOCALIZE_HH bit to get proper restoration
# of %^H by the swash loading code.
my $requirer = eval qq{
package @{[scalar(caller(0))]};
sub { scalar(\$next_require->(\$_[0])) };
};
$^H |= 0x20000 if "$]" >= 5.011;
local %^H;
return scalar($requirer->($arg));
};
};
*unimport = sub { die "$_[0] does not support unimportation\n" };
} else {
die "pure Perl version of @{[__PACKAGE__]} can't work on pre-5.8 perl";
}
=head1 BUGS
The operation of this module depends on influencing the compilation of
C<require>. As a result, it cannot prevent lexical state leakage through
a C<require> statement that was compiled before this module was invoked.
Where problems occur, this module must be invoked earlier.
=head1 SEE ALSO
L<perlpragma>
=head1 AUTHOR
Andrew Main (Zefram) <zefram@fysh.org>
=head1 COPYRIGHT
Copyright (C) 2009, 2010, 2011, 2012
Andrew Main (Zefram) <zefram@fysh.org>
=head1 LICENSE
This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
=cut
1;
#define PERL_NO_GET_CONTEXT 1
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s)
#define PERL_DECIMAL_VERSION \
PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
#define PERL_VERSION_GE(r,v,s) \
(PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s))
#ifndef croak
# define croak Perl_croak_nocontext
#endif /* !croak */
#define Q_MUST_WORKAROUND (!PERL_VERSION_GE(5,12,0))
#define Q_HAVE_COP_HINTS_HASH PERL_VERSION_GE(5,9,4)
#if Q_MUST_WORKAROUND
# if !PERL_VERSION_GE(5,9,3)
typedef OP *(*Perl_check_t)(pTHX_ OP *);
# endif /* <5.9.3 */
# if !PERL_VERSION_GE(5,10,1)
typedef unsigned Optype;
# endif /* <5.10.1 */
# ifndef wrap_op_checker
# define wrap_op_checker(c,n,o) THX_wrap_op_checker(aTHX_ c,n,o)
static void THX_wrap_op_checker(pTHX_ Optype opcode,
Perl_check_t new_checker, Perl_check_t *old_checker_p)
{
if(*old_checker_p) return;
OP_REFCNT_LOCK;
if(!*old_checker_p) {
*old_checker_p = PL_check[opcode];
PL_check[opcode] = new_checker;
}
OP_REFCNT_UNLOCK;
}
# endif /* !wrap_op_checker */
# define refcounted_he_free(he) Perl_refcounted_he_free(aTHX_ he)
static OP *pp_squashhints(pTHX)
{
/*
* SAVEHINTS() won't actually localise %^H unless the
* HINT_LOCALIZE_HH bit is set. Normally that bit would be set if
* there were anything in %^H, but when affected by [perl #73174]
* the core's swash-loading code clears $^H without # changing
* %^H, so we set the bit here. We localise $^H while doing this,
* in order to not clobber $^H across a normal require where the
* bit is legitimately clear, except on Perl 5.11, where the bit
* needs to stay set in order to get proper restoration of %^H.
*/
# if !PERL_VERSION_GE(5,11,0)
SAVEI32(PL_hints);
# endif /* <5.11.0 */
PL_hints |= HINT_LOCALIZE_HH;
SAVEHINTS();
hv_clear(GvHV(PL_hintgv));
# if Q_HAVE_COP_HINTS_HASH
if(PL_compiling.cop_hints_hash) {
refcounted_he_free(PL_compiling.cop_hints_hash);
PL_compiling.cop_hints_hash = NULL;
}
# endif /* Q_HAVE_COP_HINTS_HASH */
return PL_op->op_next;
}
#define gen_squashhints_op() THX_gen_squashhints_op(aTHX)
static OP *THX_gen_squashhints_op(pTHX)
{
OP *squashhints_op = newOP(OP_PUSHMARK, 0);
squashhints_op->op_type = OP_RAND;
squashhints_op->op_ppaddr = pp_squashhints;
return squashhints_op;
}
static OP *(*nxck_require)(pTHX_ OP *op);
static OP *myck_require(pTHX_ OP *op)
{
op = nxck_require(aTHX_ op);
op = append_list(OP_LINESEQ, (LISTOP*)gen_squashhints_op(),
(LISTOP*)op);
op = prepend_elem(OP_LINESEQ, newOP(OP_ENTER, 0), op);
op->op_type = OP_LEAVE;
op->op_ppaddr = PL_ppaddr[OP_LEAVE];
op->op_flags |= OPf_PARENS;
return op;
}
#endif /* Q_MUST_WORKAROUND */
MODULE = Lexical::SealRequireHints PACKAGE = Lexical::SealRequireHints
PROTOTYPES: DISABLE
void
import(SV *classname)
CODE:
PERL_UNUSED_VAR(classname);
#if Q_MUST_WORKAROUND
wrap_op_checker(OP_REQUIRE, myck_require, &nxck_require);
#endif /* Q_MUST_WORKAROUND */
void
unimport(SV *classname, ...)
CODE:
PERL_UNUSED_VAR(classname);
croak("Lexical::SealRequireHints does not support unimportation");
# This script checks whether L:SRH takes effect sufficiently early. It is
# specifically concerned with the "require Carp" or "require Carp::Heavy"
# that warnings.pm may execute in a delayed manner. Either it must
# be possible to delay loading warnings.pm until after L:SRH has taken
# effect, so that its require statements will be appropriately altered
# to avoid hint leakage, or L:SRH must cause Carp to load, so that it's
# loaded without problematic hints in existence. We test this by loading
# L:SRH first thing, and checking what's been loaded. This script,
# as a result, can't use warnings.pm or anything that might load it.
# The test is only applied on Perls where L:SRH makes a difference,
# so that infrastructure modules can start using warnings in the future.
BEGIN {
if("$]" >= 5.012) {
print "1..0 # SKIP no problem on this Perl\n";
exit 0;
}
}
BEGIN { print "1..1\n"; }