![](https://seccdn.libravatar.org/avatar/e2145bc5cf53dda95c308a3c75e8fef3.jpg?s=120&d=mm&r=g)
Hello community, here is the log from the commit of package perl-Module-Runtime for openSUSE:Factory checked in at 2012-02-16 16:22:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/perl-Module-Runtime (Old) and /work/SRC/openSUSE:Factory/.perl-Module-Runtime.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "perl-Module-Runtime", Maintainer is "" Changes: -------- --- /work/SRC/openSUSE:Factory/perl-Module-Runtime/perl-Module-Runtime.changes 2011-11-16 17:21:39.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.perl-Module-Runtime.new/perl-Module-Runtime.changes 2012-02-16 16:22:06.000000000 +0100 @@ -1,0 +2,33 @@ +Mon Feb 13 09:03:02 UTC 2012 - coolo@suse.com + +- updated to 0.012 + * work around Perl core bug [RT#68590] regarding leakage of %^H + into modules being loaded + + * work around Perl core bug that made a failed module loading appear + successful when re-requiring the same module + + * duplicate is_string() from Params::Classify, rather than importing it, + to avoid circular dependency problems (affecting both installation + and runtime) + + * duplicate minimal exporting behaviour from Exporter, and avoid using + the "feature", "warnings", "strict", and "parent" pragmata, to allow + for possible future use of this module by any infrastructure module + + * document core bug workarounds + + * document module name syntax more prominently, and discuss the state + of Unicode handling + + * tweak documentation of use_package_optimistically() + + * test behaviour with tainted module name + + * test lack of unwanted eval frame around require + + * give test modules more meaningful names + + * convert .cvsignore to .gitignore + +------------------------------------------------------------------- Old: ---- Module-Runtime-0.011.tar.gz New: ---- Module-Runtime-0.012.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-Module-Runtime.spec ++++++ --- /var/tmp/diff_new_pack.dPwlrJ/_old 2012-02-16 16:22:07.000000000 +0100 +++ /var/tmp/diff_new_pack.dPwlrJ/_new 2012-02-16 16:22:07.000000000 +0100 @@ -1,7 +1,7 @@ # # spec file for package perl-Module-Runtime # -# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,41 +16,40 @@ # - Name: perl-Module-Runtime -Version: 0.011 -Release: 1 -License: GPL-1.0+ or Artistic-1.0 +Version: 0.012 +Release: 0 %define cpan_name Module-Runtime Summary: runtime module handling -Url: http://search.cpan.org/dist/Module-Runtime/ +License: Artistic-1.0 or GPL-1.0+ Group: Development/Libraries/Perl +Url: http://search.cpan.org/dist/Module-Runtime/ Source: http://www.cpan.org/authors/id/Z/ZE/ZEFRAM/%{cpan_name}-%{version}.tar.gz BuildArch: noarch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: perl BuildRequires: perl-macros -BuildRequires: perl(Exporter) BuildRequires: perl(Module::Build) -BuildRequires: perl(Params::Classify) -BuildRequires: perl(parent) -BuildRequires: perl(strict) -BuildRequires: perl(Test::More) -BuildRequires: perl(warnings) -#BuildRequires: perl(CPAN) -#BuildRequires: perl(Cwd) -#BuildRequires: perl(ExtUtils::MakeMaker) -#BuildRequires: perl(File::Spec) -Requires: perl(Exporter) -Requires: perl(Params::Classify) -Requires: perl(parent) -Requires: perl(strict) -Requires: perl(warnings) +#BuildRequires: perl(Module::Runtime) %{perl_requires} %description The functions exported by this module deal with runtime handling of Perl -modules, which are normally handled at compile time. +modules, which are normally handled at compile time. This module avoids +using any other modules, so that it can be used in low-level +infrastructure. + +The parts of this module that work with module names apply the same syntax +that is used for barewords in Perl source. In principle this syntax can +vary between versions of Perl, and this module applies the syntax of the +Perl on which it is running. In practice the usable syntax hasn't changed +yet, but there's a good chance of it changing in Perl 5.18. + +The functions of this module whose purpose is to load modules include +workarounds for three old Perl core bugs regarding 'require'. These +workarounds are applied on any Perl version where the bugs exist, except +for a case where one of the bugs cannot be adequately worked around in pure +Perl. %prep %setup -q -n %{cpan_name}-%{version} ++++++ Module-Runtime-0.011.tar.gz -> Module-Runtime-0.012.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/.gitignore new/Module-Runtime-0.012/.gitignore --- old/Module-Runtime-0.011/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/Module-Runtime-0.012/.gitignore 2012-02-12 12:54:02.000000000 +0100 @@ -0,0 +1,11 @@ +/Build +/Makefile +/_build +/blib +/META.json +/META.yml +/MYMETA.json +/MYMETA.yml +/Makefile.PL +/SIGNATURE +/Module-Runtime-* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/Build.PL new/Module-Runtime-0.012/Build.PL --- old/Module-Runtime-0.011/Build.PL 2011-10-25 00:15:17.000000000 +0200 +++ new/Module-Runtime-0.012/Build.PL 2012-02-12 12:54:02.000000000 +0100 @@ -21,12 +21,7 @@ "warnings" => 0, }, requires => { - "Exporter" => 0, - "Params::Classify" => 0, - "parent" => 0, "perl" => "5.006", - "strict" => 0, - "warnings" => 0, }, dynamic_config => 0, meta_add => { distribution_type => "module" }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/Changes new/Module-Runtime-0.012/Changes --- old/Module-Runtime-0.011/Changes 2011-10-25 00:15:17.000000000 +0200 +++ new/Module-Runtime-0.012/Changes 2012-02-12 12:54:02.000000000 +0100 @@ -1,3 +1,34 @@ +version 0.012; 2012-02-12 + + * work around Perl core bug [perl #68590] regarding leakage of %^H + into modules being loaded + + * work around Perl core bug that made a failed module loading appear + successful when re-requiring the same module + + * duplicate is_string() from Params::Classify, rather than importing it, + to avoid circular dependency problems (affecting both installation + and runtime) + + * duplicate minimal exporting behaviour from Exporter, and avoid using + the "feature", "warnings", "strict", and "parent" pragmata, to allow + for possible future use of this module by any infrastructure module + + * document core bug workarounds + + * document module name syntax more prominently, and discuss the state + of Unicode handling + + * tweak documentation of use_package_optimistically() + + * test behaviour with tainted module name + + * test lack of unwanted eval frame around require + + * give test modules more meaningful names + + * convert .cvsignore to .gitignore + version 0.011; 2011-10-24 * bugfix: in require_module() and use_module(), work around a Perl diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/MANIFEST new/Module-Runtime-0.012/MANIFEST --- old/Module-Runtime-0.011/MANIFEST 2011-10-25 00:15:17.000000000 +0200 +++ new/Module-Runtime-0.012/MANIFEST 2012-02-12 12:54:02.000000000 +0100 @@ -1,4 +1,4 @@ -.cvsignore +.gitignore Build.PL Changes MANIFEST @@ -7,15 +7,21 @@ Makefile.PL README lib/Module/Runtime.pm -t/Mod0.pm -t/Mod1.pm +t/Break.pm +t/Context.pm +t/Eval.pm +t/Hints.pm +t/Simple.pm t/cmn.t +t/dependency.t +t/import_error.t t/ivmn.t t/ivms.t t/mnf.t t/pod_cvg.t t/pod_syn.t t/rm.t +t/taint.t t/um.t t/upo.t SIGNATURE Added here by Module::Build diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/META.json new/Module-Runtime-0.012/META.json --- old/Module-Runtime-0.011/META.json 2011-10-25 00:15:17.000000000 +0200 +++ new/Module-Runtime-0.012/META.json 2012-02-12 12:54:02.000000000 +0100 @@ -33,19 +33,14 @@ }, "runtime" : { "requires" : { - "Exporter" : 0, - "Params::Classify" : 0, - "parent" : 0, - "perl" : "5.006", - "strict" : 0, - "warnings" : 0 + "perl" : "5.006" } } }, "provides" : { "Module::Runtime" : { "file" : "lib/Module/Runtime.pm", - "version" : "0.011" + "version" : "0.012" } }, "release_status" : "stable", @@ -54,5 +49,5 @@ "http://dev.perl.org/licenses/" ] }, - "version" : "0.011" + "version" : "0.012" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/META.yml new/Module-Runtime-0.012/META.yml --- old/Module-Runtime-0.011/META.yml 2011-10-25 00:15:17.000000000 +0200 +++ new/Module-Runtime-0.012/META.yml 2012-02-12 12:54:02.000000000 +0100 @@ -23,14 +23,9 @@ provides: Module::Runtime: file: lib/Module/Runtime.pm - version: 0.011 + version: 0.012 requires: - Exporter: 0 - Params::Classify: 0 - parent: 0 perl: 5.006 - strict: 0 - warnings: 0 resources: license: http://dev.perl.org/licenses/ -version: 0.011 +version: 0.012 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/README new/Module-Runtime-0.012/README --- old/Module-Runtime-0.011/README 2011-10-25 00:15:17.000000000 +0200 +++ new/Module-Runtime-0.012/README 2012-02-12 12:54:02.000000000 +0100 @@ -4,8 +4,22 @@ DESCRIPTION -The functions exported by this module deal with runtime handling of Perl -modules, which are normally handled at compile time. +The functions exported by this module deal with runtime handling of +Perl modules, which are normally handled at compile time. This module +avoids using any other modules, so that it can be used in low-level +infrastructure. + +The parts of this module that work with module names apply the same +syntax that is used for barewords in Perl source. In principle this +syntax can vary between versions of Perl, and this module applies the +syntax of the Perl on which it is running. In practice the usable syntax +hasn't changed yet, but there's a good chance of it changing in Perl 5.18. + +The functions of this module whose purpose is to load modules include +workarounds for three old Perl core bugs regarding "require". These +workarounds are applied on any Perl version where the bugs exist, except +for a case where one of the bugs cannot be adequately worked around in +pure Perl. INSTALLATION @@ -20,7 +34,7 @@ COPYRIGHT -Copyright (C) 2004, 2006, 2007, 2009, 2010, 2011 +Copyright (C) 2004, 2006, 2007, 2009, 2010, 2011, 2012 Andrew Main (Zefram) <zefram@fysh.org> LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/SIGNATURE new/Module-Runtime-0.012/SIGNATURE --- old/Module-Runtime-0.011/SIGNATURE 2011-10-25 00:15:27.000000000 +0200 +++ new/Module-Runtime-0.012/SIGNATURE 2012-02-12 12:54:07.000000000 +0100 @@ -14,30 +14,36 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 -SHA1 ebdaab906c62ff40b3e35b320d0724e2e38cd959 .cvsignore -SHA1 de6c2fdf1247bfd8b7eecfba4fd403d615fe5102 Build.PL -SHA1 347dc1d11d4ac43933d6fd8d1438aa0b82ae9248 Changes -SHA1 0824ada5d908f7df2d10648c20aa14a454053cd3 MANIFEST -SHA1 0f7940cb32c667fc022a3ed5c89df48592515ae8 META.json -SHA1 cf12caa191857cc293f6e1d095a2f04b41a515d4 META.yml +SHA1 846abd52ddad1c3141b395933fd10f14cb3cd7bc .gitignore +SHA1 dd0ddabd6469a1b8c7f9dd0e7eb63a59d9b763db Build.PL +SHA1 ba7b415c1638b6f8056b0fafec88acab3f9a2a3a Changes +SHA1 7761501f07e9045a073537d0cce2e4214d417abd MANIFEST +SHA1 f483967b1e2121537599d2ca1c9f10083ca6d2b3 META.json +SHA1 bf9146284bf2f6a1dd595bb6b677ff6820a6f444 META.yml SHA1 a4df8e97ccd390a42212af5a9f4d0986c85e7a5f Makefile.PL -SHA1 51e1825521428873eb7ffb3dbba5503fd71fa23d README -SHA1 5cd392a8733b918f3699beec0e89beb753861069 lib/Module/Runtime.pm -SHA1 15f83d769adddc47c9b7f41bfd1c8d109af030f5 t/Mod0.pm -SHA1 e13ce4d6f9946cc4e9f59d4c24dd0dd208992663 t/Mod1.pm +SHA1 5601c747fdb2c85a790ebfe21303f693f9e38574 README +SHA1 0863044a64b2b6f22d548db4a2be56684b7fd1a1 lib/Module/Runtime.pm +SHA1 e80e49f06f99a5b5bb0faf54988df29a7aff89c5 t/Break.pm +SHA1 c3c7b101e683f9f3d7f915763aa6d1850421bcb4 t/Context.pm +SHA1 fbe32c46e3fe2cac40e4ab173764aec7db9b2a00 t/Eval.pm +SHA1 d7f5ca01199b601b1a1a86127270d9ab7d1ca50b t/Hints.pm +SHA1 f8988828e7cab17800a0b5f25547f09431933480 t/Simple.pm SHA1 a0f9c0dfbe6472e81222a196a2f17554697d0d48 t/cmn.t +SHA1 c0cdbe18b2c347ebabda457af0b73a1c14866535 t/dependency.t +SHA1 9331d0076c868209e9d3f0572d80f3e81df456df t/import_error.t SHA1 fa24ea0033e10712a16c71466d488cd3e69e3697 t/ivmn.t SHA1 84e207008efae1ed0ad21601d77205c2a8739fa5 t/ivms.t SHA1 8adfb7863317a2d0962a2538800cb5ad3bda1690 t/mnf.t SHA1 904d9a4f76525e2303e4b0c168c68230f223c8de t/pod_cvg.t SHA1 65c75abdef6f01a5d1588a307f2ddfe2333dc961 t/pod_syn.t -SHA1 e288041e245f8915789efefd2e97d3f14ff394ef t/rm.t -SHA1 7f12b2d9db3fbf8dc444c24a2cf3ee682fd722dd t/um.t -SHA1 33de70ab8e0c415ab87e2120edefddc9516632ad t/upo.t +SHA1 2e9638c32424e2e58100d64cb74ac50a0b964d1b t/rm.t +SHA1 5a0ef5f7a982fbaff5d501165ae2720f465c7560 t/taint.t +SHA1 75d8504e7dc405bc5b7296b509bcfad5230477c0 t/um.t +SHA1 4aed128da5418fa7b5f3ff21d89fc3134bc5a111 t/upo.t -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) -iEYEARECAAYFAk6l43UACgkQOV9mt2VyAVEzYgCeJVbJUMNFU2ekn71CsMRORDam -ctsAnR6Kk9RbpdbJiEywsdwd1Z+VhySd -=zdZP +iEYEARECAAYFAk83qFoACgkQOV9mt2VyAVHCiACggpTkwm7VqCcQHjRXMUIlRrQd +vdgAoJ2f0k6rm+zI63O9RMutiaRB5hBY +=KypS -----END PGP SIGNATURE----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/lib/Module/Runtime.pm new/Module-Runtime-0.012/lib/Module/Runtime.pm --- old/Module-Runtime-0.011/lib/Module/Runtime.pm 2011-10-25 00:15:17.000000000 +0200 +++ new/Module-Runtime-0.012/lib/Module/Runtime.pm 2012-02-12 12:54:02.000000000 +0100 @@ -37,22 +37,92 @@ =head1 DESCRIPTION -The functions exported by this module deal with runtime handling of Perl -modules, which are normally handled at compile time. +The functions exported by this module deal with runtime handling of +Perl modules, which are normally handled at compile time. This module +avoids using any other modules, so that it can be used in low-level +infrastructure. + +The parts of this module that work with module names apply the same +syntax that is used for barewords in Perl source. In principle this +syntax can vary between versions of Perl, and this module applies the +syntax of the Perl on which it is running. In practice the usable syntax +hasn't changed yet, but there's a good chance of it changing in Perl 5.18. + +The functions of this module whose purpose is to load modules include +workarounds for three old Perl core bugs regarding C<require>. These +workarounds are applied on any Perl version where the bugs exist, except +for a case where one of the bugs cannot be adequately worked around in +pure Perl. + +=head2 Module name syntax + +The usable module name syntax has not changed from Perl 5.000 up to +Perl 5.15.7. The syntax is composed entirely of ASCII characters. +From Perl 5.6 onwards there has been some attempt to allow the use of +non-ASCII Unicode characters in Perl source, but it was fundamentally +broken (like the entirety of Perl 5.6's Unicode handling) and remained +pretty much entirely unusable until it got some attention in the Perl +5.15 series. Although Unicode is now consistently accepted by the +parser in some places, it remains broken for module names. Furthermore, +there has not yet been any work on how to map Unicode module names into +filenames, so in that respect also Unicode module names are unusable. +This may finally be addressed in the Perl 5.17 series. + +The module name syntax is, precisely: the string must consist of one or +more segments separated by C<::>; each segment must consist of one or more +identifier characters (ASCII alphanumerics plus "_"); the first character +of the string must not be a digit. Thus "C<IO::File>", "C<warnings>", +and "C<foo::123::x_0>" are all valid module names, whereas "C<IO::>" +and "C<1foo::bar>" are not. C<'> separators are not permitted by this +module, though they remain usable in Perl source, being translated to +C<::> in the parser. + +=head2 Core bugs worked around + +The first bug worked around is core bug [perl #68590], which causes +lexical state in one file to leak into another that is C<require>d/C<use>d +from it. This bug is present from Perl 5.6 up to Perl 5.10, and is +fixed in Perl 5.11.0. From Perl 5.9.4 up to Perl 5.10.0 no satisfactory +workaround is possible in pure Perl. The workaround means that modules +loaded via this module don't suffer this pollution of their lexical +state. Modules loaded in other ways, or via this module on the Perl +versions where the pure Perl workaround is impossible, remain vulnerable. +The module L<Lexical::SealRequireHints> provides a complete workaround +for this bug. + +The second bug worked around causes some kinds of failure in module +loading, principally compilation errors in the loaded module, to be +recorded in C<%INC> as if they were successful, so later attempts to load +the same module immediately indicate success. This bug is present up +to Perl 5.8.9, and is fixed in Perl 5.9.0. The workaround means that a +compilation error in a module loaded via this module won't be cached as +a success. Modules loaded in other ways remain liable to produce bogus +C<%INC> entries, and if a bogus entry exists then it will mislead this +module if it is used to re-attempt loading. + +The third bug worked around causes the wrong context to be seen at +file scope of a loaded module, if C<require> is invoked in a location +that inherits context from a higher scope. This bug is present up to +Perl 5.11.2, and is fixed in Perl 5.11.3. The workaround means that +a module loaded via this module will always see the correct context. +Modules loaded in other ways remain vulnerable. =cut package Module::Runtime; -{ use 5.006; } -use warnings; -use strict; +# Don't "use 5.006" here, because Perl 5.15.6 will load feature.pm if +# the version check is done that way. +BEGIN { require 5.006; } +# Don't "use warnings" here, to avoid dependencies. Do standardise the +# warning status by lexical override; unfortunately the only safe bitset +# to build in is the empty set, equivalent to "no warnings". +BEGIN { ${^WARNING_BITS} = ""; } +# Don't "use strict" here, to avoid dependencies. -use Params::Classify 0.000 qw(is_string); +our $VERSION = "0.012"; -our $VERSION = "0.011"; - -use parent "Exporter"; +# Don't use Exporter here, to avoid dependencies. our @EXPORT_OK = qw( $module_name_rx is_module_name is_valid_module_name check_module_name module_notional_filename require_module @@ -61,6 +131,36 @@ is_module_spec is_valid_module_spec check_module_spec compose_module_name ); +my %export_ok = map { ($_ => undef) } @EXPORT_OK; +sub import { + my $me = shift; + my $callpkg = caller(0); + my $errs = ""; + foreach(@_) { + if(exists $export_ok{$_}) { + # We would need to do "no strict 'refs'" here + # if we had enabled strict at file scope. + if(/\A\$(.*)\z/s) { + *{$callpkg."::".$1} = \$$1; + } else { + *{$callpkg."::".$_} = \&$_; + } + } else { + $errs .= "\"$_\" is not exported by the $me module\n"; + } + } + if($errs ne "") { + die "${errs}Can't continue after import errors ". + "at @{[(caller(0))[1]]} line @{[(caller(0))[2]]}.\n"; + } +} + +# Logic duplicated from Params::Classify. Duplicating it here avoids +# an extensive and potentially circular dependency graph. +sub _is_string($) { + my($arg) = @_; + return defined($arg) && ref(\$arg) eq "SCALAR"; +} =head1 REGULAR EXPRESSIONS @@ -73,15 +173,6 @@ =item $module_name_rx Matches a valid Perl module name in bareword syntax. -The rule for this, precisely, is: the string must -consist of one or more segments separated by C<::>; each segment must -consist of one or more identifier characters (alphanumerics plus "_"); -the first character of the string must not be a digit. Thus "C<IO::File>", -"C<warnings>", and "C<foo::123::x_0>" are all valid module names, whereas -"C<IO::>" and "C<1foo::bar>" are not. -Only ASCII characters are permitted; Perl's handling of non-ASCII -characters in source code is inconsistent. -C<'> separators are not permitted. =cut @@ -128,7 +219,7 @@ =cut -sub is_module_name($) { is_string($_[0]) && $_[0] =~ /\A$module_name_rx\z/o } +sub is_module_name($) { _is_string($_[0]) && $_[0] =~ /\A$module_name_rx\z/o } =item is_valid_module_name(ARG) @@ -148,7 +239,7 @@ sub check_module_name($) { unless(&is_module_name) { - die +(is_string($_[0]) ? "`$_[0]'" : "argument"). + die +(_is_string($_[0]) ? "`$_[0]'" : "argument"). " is not a module name\n"; } } @@ -194,15 +285,37 @@ =cut +# Don't "use constant" here, to avoid dependencies. +BEGIN { + *_WORK_AROUND_HINT_LEAKAGE = + "$]" < 5.011 && !("$]" >= 5.009004 && "$]" < 5.010001) + ? sub(){1} : sub(){0}; + *_WORK_AROUND_BROKEN_MODULE_STATE = "$]" < 5.009 ? sub(){1} : sub(){0}; +} + +BEGIN { if(_WORK_AROUND_BROKEN_MODULE_STATE) { eval q{ + sub Module::Runtime::__GUARD__::DESTROY { + delete $INC{$_[0]->[0]} if @{$_[0]}; + } + 1; +}; die $@ if $@ ne ""; } } + sub require_module($) { - # Explicit scalar() here works around a Perl core bug, present - # in Perl 5.8 and 5.10, which allowed a require() in return - # position to pass a non-scalar context through to file scope - # of the required file. This breaks some modules. require() - # in any other position, where its op flags determine context - # statically, doesn't have this problem, because the op flags - # are forced to scalar. - return scalar(require(&module_notional_filename)); + # Localise %^H to work around [perl #68590], where the bug exists + # and this is a satisfactory workaround. The bug consists of + # %^H state leaking into each required module, polluting the + # module's lexical state. + local %^H if _WORK_AROUND_HINT_LEAKAGE; + if(_WORK_AROUND_BROKEN_MODULE_STATE) { + my $notional_filename = &module_notional_filename; + my $guard = bless([ $notional_filename ], + "Module::Runtime::__GUARD__"); + my $result = require($notional_filename); + pop @$guard; + return $result; + } else { + return scalar(require(&module_notional_filename)); + } } =back @@ -248,8 +361,8 @@ An attempt is made to load the named module (as if by the bareword form of C<require>). If the module cannot be found then it is assumed that -the package was actually already loaded but wasn't detected correctly, -and no error is signalled. That's the optimistic bit. +the package was actually already loaded by other means, and no error +is signalled. That's the optimistic bit. This is mostly the same operation that is performed by the L<base> pragma to ensure that the specified base classes are available. The behaviour @@ -267,11 +380,9 @@ sub use_package_optimistically($;$) { my($name, $version) = @_; check_module_name($name); - eval { local $SIG{__DIE__}; require(module_notional_filename($name)); }; - die $@ if $@ ne "" && $@ !~ /\A - Can't\ locate\ .+\ at - \ \Q@{[__FILE__]}\E\ line\ \Q@{[__LINE__-1]}\E - /xs; + eval { local $SIG{__DIE__}; require_module($name); }; + die $@ if $@ ne "" && + $@ !~ /\ACan't locate .+ at \Q@{[__FILE__]}\E line/s; $name->VERSION($version) if defined $version; return $name; } @@ -294,7 +405,7 @@ sub is_module_spec($$) { my($prefix, $spec) = @_; - return is_string($spec) && + return _is_string($spec) && $spec =~ ($prefix ? qr/\A$sub_module_spec_rx\z/o : qr/\A$top_module_spec_rx\z/o); } @@ -316,7 +427,7 @@ sub check_module_spec($$) { unless(&is_module_spec) { - die +(is_string($_[1]) ? "`$_[1]'" : "argument"). + die +(_is_string($_[1]) ? "`$_[1]'" : "argument"). " is not a module specification\n"; } } @@ -359,6 +470,7 @@ =head1 SEE ALSO +L<Lexical::SealRequireHints>, L<base>, L<perlfunc/require>, L<perlfunc/use> @@ -369,7 +481,7 @@ =head1 COPYRIGHT -Copyright (C) 2004, 2006, 2007, 2009, 2010, 2011 +Copyright (C) 2004, 2006, 2007, 2009, 2010, 2011, 2012 Andrew Main (Zefram) <zefram@fysh.org> =head1 LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/Break.pm new/Module-Runtime-0.012/t/Break.pm --- old/Module-Runtime-0.011/t/Break.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/Module-Runtime-0.012/t/Break.pm 2012-02-12 12:54:02.000000000 +0100 @@ -0,0 +1,7 @@ +package t::Break; + +{ use 5.006; } +use warnings; +use strict; + +die "broken"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/Context.pm new/Module-Runtime-0.012/t/Context.pm --- old/Module-Runtime-0.011/t/Context.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/Module-Runtime-0.012/t/Context.pm 2012-02-12 12:54:02.000000000 +0100 @@ -0,0 +1,12 @@ +package t::Context; + +{ use 5.006; } +use warnings; +use strict; + +our $VERSION = 1; + +die "t::Context sees array context at file scope" if wantarray; +die "t::Context sees void context at file scope" unless defined wantarray; + +"t::Context return"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/Eval.pm new/Module-Runtime-0.012/t/Eval.pm --- old/Module-Runtime-0.011/t/Eval.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/Module-Runtime-0.012/t/Eval.pm 2012-02-12 12:54:02.000000000 +0100 @@ -0,0 +1,41 @@ +package t::Eval; + +use warnings; +use strict; + +use Test::More; + +sub _ok_no_eval() { + my $lastsub = ""; + my $i = 0; + while(1) { + my @c = caller($i); + unless(@c) { + ok 0; + diag "failed to find main program in stack trace"; + return; + } + my $sub = $c[3]; + if($sub eq "main::eval_test") { + ok 1; + return; + } + my $type = $sub ne "(eval)" ? "subroutine" : + $c[7] ? "require" : + defined($c[6]) ? "string eval" : "block eval"; + if($type =~ /eval/ && !($lastsub eq "t::Eval::BEGIN" && + $type eq "block eval")) { + ok 0; + diag "have $type between module and main program"; + return; + } + $lastsub = $sub; + $i++; + } +} + +BEGIN { _ok_no_eval(); } +_ok_no_eval(); +sub import { _ok_no_eval(); } + +1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/Hints.pm new/Module-Runtime-0.012/t/Hints.pm --- old/Module-Runtime-0.011/t/Hints.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/Module-Runtime-0.012/t/Hints.pm 2012-02-12 12:54:02.000000000 +0100 @@ -0,0 +1,17 @@ +package t::Hints; + +use warnings; +use strict; + +use Test::More; + +BEGIN { is $^H{"Module::Runtime/test_a"}, undef; } +main::test_runtime_hint_hash "Module::Runtime/test_a", undef; + +sub import { + is $^H{"Module::Runtime/test_a"}, 1; + $^H |= 0x20000 if "$]" < 5.009004; + $^H{"Module::Runtime/test_b"} = 1; +} + +1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/Mod0.pm new/Module-Runtime-0.012/t/Mod0.pm --- old/Module-Runtime-0.011/t/Mod0.pm 2011-10-25 00:15:17.000000000 +0200 +++ new/Module-Runtime-0.012/t/Mod0.pm 1970-01-01 01:00:00.000000000 +0100 @@ -1,9 +0,0 @@ -package t::Mod0; - -{ use 5.006; } -use warnings; -use strict; - -our $VERSION = 1; - -"t::Mod0 return"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/Mod1.pm new/Module-Runtime-0.012/t/Mod1.pm --- old/Module-Runtime-0.011/t/Mod1.pm 2011-10-25 00:15:17.000000000 +0200 +++ new/Module-Runtime-0.012/t/Mod1.pm 1970-01-01 01:00:00.000000000 +0100 @@ -1,12 +0,0 @@ -package t::Mod1; - -{ use 5.006; } -use warnings; -use strict; - -our $VERSION = 1; - -die "t::Mod1 sees array context at file scope" if wantarray; -die "t::Mod1 sees void context at file scope" unless defined wantarray; - -"t::Mod1 return"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/Simple.pm new/Module-Runtime-0.012/t/Simple.pm --- old/Module-Runtime-0.011/t/Simple.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/Module-Runtime-0.012/t/Simple.pm 2012-02-12 12:54:02.000000000 +0100 @@ -0,0 +1,9 @@ +package t::Simple; + +{ use 5.006; } +use warnings; +use strict; + +our $VERSION = 1; + +"t::Simple return"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/dependency.t new/Module-Runtime-0.012/t/dependency.t --- old/Module-Runtime-0.011/t/dependency.t 1970-01-01 01:00:00.000000000 +0100 +++ new/Module-Runtime-0.012/t/dependency.t 2012-02-12 12:54:02.000000000 +0100 @@ -0,0 +1,8 @@ +# This test checks that M:R doesn't load any other modules. Hence this +# script cannot itself use warnings, Test::More, or any other module. + +BEGIN { print "1..1\n"; } +use Module::Runtime qw(require_module); +print join(" ", sort keys %INC) eq "Module/Runtime.pm" ? "" : "not ", "ok 1\n"; + +1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/import_error.t new/Module-Runtime-0.012/t/import_error.t --- old/Module-Runtime-0.011/t/import_error.t 1970-01-01 01:00:00.000000000 +0100 +++ new/Module-Runtime-0.012/t/import_error.t 2012-02-12 12:54:02.000000000 +0100 @@ -0,0 +1,35 @@ +use warnings; +use strict; + +use Test::More tests => 3; + +eval q{#line 11 "test_eval" + use Module::Runtime qw(foo); +}; +$@ =~ s/\(eval [0-9]+\) line 2/test_eval line 11/ if "$]" < 5.006001; +like $@, qr/\A + \"foo\"\ is\ not\ exported\ by\ the\ Module::Runtime\ module\n + Can't\ continue\ after\ import\ errors\ at\ test_eval\ line\ 11.\n +/x; + +eval q{#line 22 "test_eval" + use Module::Runtime qw(require_module.1); +}; +$@ =~ s/\(eval [0-9]+\) line 2/test_eval line 22/ if "$]" < 5.006001; +like $@, qr/\A + \"require_module.1\"\ is\ not\ exported + \ by\ the\ Module::Runtime\ module\n + Can't\ continue\ after\ import\ errors\ at\ test_eval\ line\ 22.\n +/x; + +eval q{#line 33 "test_eval" + use Module::Runtime qw(foo require_module bar); +}; +$@ =~ s/\(eval [0-9]+\) line 2/test_eval line 33/ if "$]" < 5.006001; +like $@, qr/\A + \"foo\"\ is\ not\ exported\ by\ the\ Module::Runtime\ module\n + \"bar\"\ is\ not\ exported\ by\ the\ Module::Runtime\ module\n + Can't\ continue\ after\ import\ errors\ at\ test_eval\ line\ 33.\n +/x; + +1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/rm.t new/Module-Runtime-0.012/t/rm.t --- old/Module-Runtime-0.011/t/rm.t 2011-10-25 00:15:17.000000000 +0200 +++ new/Module-Runtime-0.012/t/rm.t 2012-02-12 12:54:02.000000000 +0100 @@ -1,7 +1,7 @@ use warnings; use strict; -use Test::More tests => 9; +use Test::More tests => 26; BEGIN { use_ok "Module::Runtime", qw(require_module); } @@ -23,17 +23,64 @@ is($result, 1); # a module that we'll load now -test_require_module("t::Mod0"); +test_require_module("t::Simple"); is($err, ""); -is($result, "t::Mod0 return"); +is($result, "t::Simple return"); # re-requiring the module that we just loaded -test_require_module("t::Mod0"); +test_require_module("t::Simple"); is($err, ""); is($result, 1); # module file scope sees scalar context regardless of calling context -eval { require_module("t::Mod1"); 1 }; +eval { require_module("t::Context"); 1 }; is $@, ""; +# lexical hints don't leak through +my $have_runtime_hint_hash = "$]" >= 5.009004; +sub test_runtime_hint_hash($$) { + SKIP: { + skip "no runtime hint hash", 1 unless $have_runtime_hint_hash; + is +((caller(0))[10] || {})->{$_[0]}, $_[1]; + } +} +SKIP: { + skip "core bug makes this test crash", 13 + if "$]" >= 5.008 && "$]" < 5.008004; + skip "can't work around hint leakage in pure Perl", 13 + if "$]" >= 5.009004 && "$]" < 5.010001; + $^H |= 0x20000 if "$]" < 5.009004; + $^H{"Module::Runtime/test_a"} = 1; + is $^H{"Module::Runtime/test_a"}, 1; + is $^H{"Module::Runtime/test_b"}, undef; + require_module("t::Hints"); + is $^H{"Module::Runtime/test_a"}, 1; + is $^H{"Module::Runtime/test_b"}, undef; + t::Hints->import; + is $^H{"Module::Runtime/test_a"}, 1; + is $^H{"Module::Runtime/test_b"}, 1; + eval q{ + BEGIN { $^H |= 0x20000; $^H{foo} = 1; } + BEGIN { is $^H{foo}, 1; } + main::test_runtime_hint_hash("foo", 1); + BEGIN { require_module("Math::BigInt"); } + BEGIN { is $^H{foo}, 1; } + main::test_runtime_hint_hash("foo", 1); + 1; + }; die $@ unless $@ eq ""; +} + +# broken module is visibly broken when re-required +eval { require_module("t::Break") }; +like $@, qr/\A(?:broken |Attempt to reload )/; +eval { require_module("t::Break") }; +like $@, qr/\A(?:broken |Attempt to reload )/; + +# no extra eval frame +SKIP: { + skip "core bug makes this test crash", 2 if "$]" < 5.006001; + sub eval_test () { require_module("t::Eval") } + eval_test(); +} + 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/taint.t new/Module-Runtime-0.012/t/taint.t --- old/Module-Runtime-0.011/t/taint.t 1970-01-01 01:00:00.000000000 +0100 +++ new/Module-Runtime-0.012/t/taint.t 2012-02-12 12:54:02.000000000 +0100 @@ -0,0 +1,24 @@ +#!perl -T +# above line is required to enable taint mode + +use warnings; +use strict; + +use Test::More tests => 5; + +BEGIN { + use_ok "Module::Runtime", + qw(require_module use_module use_package_optimistically); +} + +my $tainted_modname = substr($ENV{PATH}, 0, 0) . "Module::Runtime"; +eval { require_module($tainted_modname) }; +like $@, qr/\AInsecure dependency /; +eval { use_module($tainted_modname) }; +like $@, qr/\AInsecure dependency /; +eval { use_package_optimistically($tainted_modname) }; +like $@, qr/\AInsecure dependency /; +eval { require_module("Module::Runtime") }; +is $@, ""; + +1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/um.t new/Module-Runtime-0.012/t/um.t --- old/Module-Runtime-0.011/t/um.t 2011-10-25 00:15:17.000000000 +0200 +++ new/Module-Runtime-0.012/t/um.t 2012-02-12 12:54:02.000000000 +0100 @@ -1,7 +1,7 @@ use warnings; use strict; -use Test::More tests => 12; +use Test::More tests => 29; BEGIN { use_ok "Module::Runtime", qw(use_module); } @@ -23,19 +23,66 @@ is($result, "Test::More"); # a module that we'll load now -test_use_module("t::Mod0"); +test_use_module("t::Simple"); is($err, ""); -is($result, "t::Mod0"); +is($result, "t::Simple"); # re-requiring the module that we just loaded -test_use_module("t::Mod0"); +test_use_module("t::Simple"); is($err, ""); -is($result, "t::Mod0"); +is($result, "t::Simple"); # module file scope sees scalar context regardless of calling context -eval { use_module("t::Mod1"); 1 }; +eval { use_module("t::Context"); 1 }; is $@, ""; +# lexical hints don't leak through +my $have_runtime_hint_hash = "$]" >= 5.009004; +sub test_runtime_hint_hash($$) { + SKIP: { + skip "no runtime hint hash", 1 unless $have_runtime_hint_hash; + is +((caller(0))[10] || {})->{$_[0]}, $_[1]; + } +} +SKIP: { + skip "core bug makes this test crash", 13 + if "$]" >= 5.008 && "$]" < 5.008004; + skip "can't work around hint leakage in pure Perl", 13 + if "$]" >= 5.009004 && "$]" < 5.010001; + $^H |= 0x20000 if "$]" < 5.009004; + $^H{"Module::Runtime/test_a"} = 1; + is $^H{"Module::Runtime/test_a"}, 1; + is $^H{"Module::Runtime/test_b"}, undef; + use_module("t::Hints"); + is $^H{"Module::Runtime/test_a"}, 1; + is $^H{"Module::Runtime/test_b"}, undef; + t::Hints->import; + is $^H{"Module::Runtime/test_a"}, 1; + is $^H{"Module::Runtime/test_b"}, 1; + eval q{ + BEGIN { $^H |= 0x20000; $^H{foo} = 1; } + BEGIN { is $^H{foo}, 1; } + main::test_runtime_hint_hash("foo", 1); + BEGIN { use_module("Math::BigInt"); } + BEGIN { is $^H{foo}, 1; } + main::test_runtime_hint_hash("foo", 1); + 1; + }; die $@ unless $@ eq ""; +} + +# broken module is visibly broken when re-required +eval { use_module("t::Break") }; +like $@, qr/\A(?:broken |Attempt to reload )/; +eval { use_module("t::Break") }; +like $@, qr/\A(?:broken |Attempt to reload )/; + +# no extra eval frame +SKIP: { + skip "core bug makes this test crash", 2 if "$]" < 5.006001; + sub eval_test () { use_module("t::Eval") } + eval_test(); +} + # successful version check test_use_module("Module::Runtime", 0.001); is($err, ""); @@ -46,5 +93,3 @@ like($err, qr/^Module::Runtime version /); 1; - -1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Module-Runtime-0.011/t/upo.t new/Module-Runtime-0.012/t/upo.t --- old/Module-Runtime-0.011/t/upo.t 2011-10-25 00:15:17.000000000 +0200 +++ new/Module-Runtime-0.012/t/upo.t 2012-02-12 12:54:02.000000000 +0100 @@ -1,7 +1,7 @@ use warnings; use strict; -use Test::More tests => 15; +use Test::More tests => 30; BEGIN { use_ok "Module::Runtime", qw(use_package_optimistically); } @@ -24,11 +24,51 @@ is $result, "Test::More"; # a module that we'll load now -test_use_package_optimistically("t::Mod0"); +test_use_package_optimistically("t::Simple"); is $err, ""; -is $result, "t::Mod0"; +is $result, "t::Simple"; no strict "refs"; -ok defined(${"t::Mod0::VERSION"}); +ok defined(${"t::Simple::VERSION"}); + +# lexical hints don't leak through +my $have_runtime_hint_hash = "$]" >= 5.009004; +sub test_runtime_hint_hash($$) { + SKIP: { + skip "no runtime hint hash", 1 unless $have_runtime_hint_hash; + is +((caller(0))[10] || {})->{$_[0]}, $_[1]; + } +} +SKIP: { + skip "core bug makes this test crash", 13 + if "$]" >= 5.008 && "$]" < 5.008004; + skip "can't work around hint leakage in pure Perl", 13 + if "$]" >= 5.009004 && "$]" < 5.010001; + $^H |= 0x20000 if "$]" < 5.009004; + $^H{"Module::Runtime/test_a"} = 1; + is $^H{"Module::Runtime/test_a"}, 1; + is $^H{"Module::Runtime/test_b"}, undef; + use_package_optimistically("t::Hints"); + is $^H{"Module::Runtime/test_a"}, 1; + is $^H{"Module::Runtime/test_b"}, undef; + t::Hints->import; + is $^H{"Module::Runtime/test_a"}, 1; + is $^H{"Module::Runtime/test_b"}, 1; + eval q{ + BEGIN { $^H |= 0x20000; $^H{foo} = 1; } + BEGIN { is $^H{foo}, 1; } + main::test_runtime_hint_hash("foo", 1); + BEGIN { use_package_optimistically("Math::BigInt"); } + BEGIN { is $^H{foo}, 1; } + main::test_runtime_hint_hash("foo", 1); + 1; + }; die $@ unless $@ eq ""; +} + +# broken module is visibly broken when re-required +eval { use_package_optimistically("t::Break") }; +like $@, qr/\A(?:broken |Attempt to reload )/; +eval { use_package_optimistically("t::Break") }; +like $@, qr/\A(?:broken |Attempt to reload )/; # successful version check test_use_package_optimistically("Module::Runtime", 0.001); @@ -40,11 +80,11 @@ like $err, qr/^Module::Runtime version /; # even load module if $VERSION already set, unlike older behaviour -$t::Mod1::VERSION = undef; -test_use_package_optimistically("t::Mod1"); +$t::Context::VERSION = undef; +test_use_package_optimistically("t::Context"); is $err, ""; -is $result, "t::Mod1"; -ok defined($t::Mod1::VERSION); -ok $INC{"t/Mod1.pm"}; +is $result, "t::Context"; +ok defined($t::Context::VERSION); +ok $INC{"t/Context.pm"}; 1; -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org