From d2ca869c9b85a7d9a878022eaa2817f06850b07f Mon Sep 17 00:00:00 2001 From: Max Kanat-Alexander Date: Tue, 28 Dec 2010 14:32:50 -0800 Subject: [PATCH 1/4] Use Capture::Tiny instead of a piped open, for Windows compatibility. --- Changes | 3 +++ dist.ini | 3 ++- lib/Crypt/Random/Source/Base/Proc.pm | 21 +++++++++++++++------ t/blocking.t | 7 +++---- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Changes b/Changes index 509dbf0..7a3494d 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,6 @@ +0.07 + - Switch to using Capture::Tiny for Proc.pm, for Windows + support. 0.06 - Use Any::Moose to allow either Moose or Mouse. - Switch to dzil. diff --git a/dist.ini b/dist.ini index cc1702f..2ae96fa 100644 --- a/dist.ini +++ b/dist.ini @@ -1,5 +1,5 @@ name = Crypt-Random-Source -version = 0.06 +version = 0.07 author = Yuval Kogman license = Perl_5 copyright_holder = Yuval Kogman @@ -16,3 +16,4 @@ repository_at = github [Prereqs] Any::Moose = 0.11 namespace::clean = 0.08 +Capture::Tiny = 0.08 diff --git a/lib/Crypt/Random/Source/Base/Proc.pm b/lib/Crypt/Random/Source/Base/Proc.pm index 41f261f..0fc7c94 100644 --- a/lib/Crypt/Random/Source/Base/Proc.pm +++ b/lib/Crypt/Random/Source/Base/Proc.pm @@ -5,7 +5,8 @@ use Any::Moose; extends qw(Crypt::Random::Source::Base::Handle); -use IO::Handle; +use Capture::Tiny qw(capture); +use IO::File; use 5.008; @@ -16,11 +17,19 @@ sub open_handle { my $cmd = $self->command; my @cmd = ref $cmd ? @$cmd : $cmd; - - open my $fh, "-|", @cmd - or die "open(@cmd|): $!"; - - bless $fh, "IO::Handle"; + my $retval; + my ($stdout, $stderr) = capture { $retval = system(@cmd) }; + chomp($stderr); + if ($retval) { + my $err = join(' ', @cmd) . ": $! ($?)"; + if ($stderr) { + $err .= "\n$stderr"; + } + die $err; + } + warn $stderr if $stderr; + + my $fh = IO::File->new(\$stdout, '<'); return $fh; } diff --git a/t/blocking.t b/t/blocking.t index 415c483..4808bbe 100644 --- a/t/blocking.t +++ b/t/blocking.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More 'no_plan'; +use Test::More tests => 3; use 5.008; @@ -12,9 +12,8 @@ use IO::Select; use ok 'Crypt::Random::Source::Base::Handle'; -{ - my ( $reader, $writer ) = map { IO::Handle->new } 1 .. 2; - +SKIP: { + skip "Windows can't open a blocking child pipe", 2 if $^O =~ /Win32/i; defined ( my $child = open my $fh, "-|" ) or die "open: $!"; if ($child) { From 5a093492cc31161128046bf71fca181ae5423656 Mon Sep 17 00:00:00 2001 From: Max Kanat-Alexander Date: Tue, 28 Dec 2010 15:48:59 -0800 Subject: [PATCH 2/4] Handle.pm was throwing an error during global destruction, because the handle was undef already, and has_handle only checks "exists" on the item, not "defined". --- Changes | 1 + lib/Crypt/Random/Source/Base/Handle.pm | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 7a3494d..f7b4564 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,7 @@ 0.07 - Switch to using Capture::Tiny for Proc.pm, for Windows support. + - Prevent a warning from Handle.pm during global destruction. 0.06 - Use Any::Moose to allow either Moose or Mouse. - Switch to dzil. diff --git a/lib/Crypt/Random/Source/Base/Handle.pm b/lib/Crypt/Random/Source/Base/Handle.pm index 5f4d981..f6fd780 100644 --- a/lib/Crypt/Random/Source/Base/Handle.pm +++ b/lib/Crypt/Random/Source/Base/Handle.pm @@ -85,8 +85,10 @@ sub _read_too_short { sub close { my $self = shift; - if ( $self->has_handle ) { - $self->handle->close; # or die "close: $!"; # open "-|" returns exit status on close + # During global destruction, $self->handle can be undef already, + # so we need to also check if it is defined. + if ( $self->has_handle and $self->handle ) { + $self->handle->close or die "close: $!"; $self->clear_handle; } } From 0901524b44dd7a6797733891714462f5c629d479 Mon Sep 17 00:00:00 2001 From: Max Kanat-Alexander Date: Wed, 29 Dec 2010 17:22:10 -0800 Subject: [PATCH 3/4] Make Crypt::Random::Source pass all tests in Taint mode. --- Changes | 2 ++ lib/Crypt/Random/Source/Base/Proc.pm | 16 ++++++++++++++++ lib/Crypt/Random/Source/Factory.pm | 6 +++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index f7b4564..1e2b11c 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ - Switch to using Capture::Tiny for Proc.pm, for Windows support. - Prevent a warning from Handle.pm during global destruction. + - Make Crypt::Random::Source work properly in taint mode. + 0.06 - Use Any::Moose to allow either Moose or Mouse. - Switch to dzil. diff --git a/lib/Crypt/Random/Source/Base/Proc.pm b/lib/Crypt/Random/Source/Base/Proc.pm index 0fc7c94..d5808a8 100644 --- a/lib/Crypt/Random/Source/Base/Proc.pm +++ b/lib/Crypt/Random/Source/Base/Proc.pm @@ -6,11 +6,26 @@ use Any::Moose; extends qw(Crypt::Random::Source::Base::Handle); use Capture::Tiny qw(capture); +use File::Spec; use IO::File; use 5.008; has command => ( is => "rw", required => 1 ); +has search_path => ( is => 'rw', isa => 'Str', lazy_build => 1 ); + +# This is a scalar so that people can customize it (which they would +# particularly need to do on Windows). +our $TAINT_PATH = + '/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin'; + +sub _build_search_path { + # In taint mode it's not safe to use $ENV{PATH}. + if (${^TAINT}) { + return $TAINT_PATH; + } + return $ENV{PATH}; +} sub open_handle { my $self = shift; @@ -18,6 +33,7 @@ sub open_handle { my $cmd = $self->command; my @cmd = ref $cmd ? @$cmd : $cmd; my $retval; + local $ENV{PATH} = $self->search_path; my ($stdout, $stderr) = capture { $retval = system(@cmd) }; chomp($stderr); if ($retval) { diff --git a/lib/Crypt/Random/Source/Factory.pm b/lib/Crypt/Random/Source/Factory.pm index ee3ae0c..e4723bc 100644 --- a/lib/Crypt/Random/Source/Factory.pm +++ b/lib/Crypt/Random/Source/Factory.pm @@ -146,7 +146,11 @@ sub first_available { sub locate_sources { my ( $self, $category ) = @_; - [ findsubmod "Crypt::Random::Source::$category" ]; + my @sources = findsubmod "Crypt::Random::Source::$category"; + # Untaint class names (which are tainted in taint mode because + # they came from the disk). + ($_) = $_ =~ /^(.*)$/ foreach @sources; + return \@sources; } 1; From d8d20f1f81539fb3c35cd77f8c06013748538687 Mon Sep 17 00:00:00 2001 From: Max Kanat-Alexander Date: Sun, 17 Apr 2011 13:39:03 -0700 Subject: [PATCH 4/4] Proc.pm was using IO::File to open a handle to a scalar, which doesn't work on Perl 5.8 (use open() instead). --- Changes | 2 ++ dist.ini | 2 +- lib/Crypt/Random/Source/Base/Proc.pm | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 1e2b11c..41dd7a1 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,5 @@ +0.08 + - Fix Proc handles on Perl 5.8. 0.07 - Switch to using Capture::Tiny for Proc.pm, for Windows support. diff --git a/dist.ini b/dist.ini index 2ae96fa..bd68487 100644 --- a/dist.ini +++ b/dist.ini @@ -1,5 +1,5 @@ name = Crypt-Random-Source -version = 0.07 +version = 0.08 author = Yuval Kogman license = Perl_5 copyright_holder = Yuval Kogman diff --git a/lib/Crypt/Random/Source/Base/Proc.pm b/lib/Crypt/Random/Source/Base/Proc.pm index d5808a8..2041e50 100644 --- a/lib/Crypt/Random/Source/Base/Proc.pm +++ b/lib/Crypt/Random/Source/Base/Proc.pm @@ -45,7 +45,7 @@ sub open_handle { } warn $stderr if $stderr; - my $fh = IO::File->new(\$stdout, '<'); + open(my $fh, '<', \$stdout) || die $!; return $fh; }