Subject: | tough to trap errors in taint mode |
Using IPC::Open3::Simple produces duplicate output if running in taint
mode and an insecure dependency is encountered while running the script.
I've written this script that does `ls $ARGV[0]` to demonstrate.
In the context I discovered the bug, I am using Template Toolkit in eval
{ } to process into a scalar var which is then printed, so that thrown
exceptions can be trapped and then the page started over with the error
page. In a similar way to the test script here, my CGI app prints the
$ipc_error string to the debug log and then tries to throw an
Exception::Class object with that string as the message. When it prints
to the debug log, that string contains the entire HTML of the template
page with the error text inside as if it were trapped and formatted as
an error page. I think that is happening inside the fork, which
executes the full path of the CGI again and traps the error there.
Because the parent never sees the exception thrown, and the browser
displays a normal page, acting like the IPC was simply not run.
Subject: | ipc-open3-simple-bugtest.pl |
#!/usr/bin/perl -T
use strict;
use warnings FATAL => 'all';
use English '-no_match_vars';
die "usage: $PROGRAM_NAME /some/directory/path\n" if !$ARGV[0];
my $output = '';
eval {
$output .= "hooblie dooblie\n";
use IPC::Open3::Simple;
my $ipc_output = '';
my $ipc_error = '';
my $script = "ls $ARGV[0]";
$ENV{PATH} = '';
my $ipc = IPC::Open3::Simple->new(
in => sub {
my ($fh) = @_;
close $fh;
},
out => sub {
$ipc_output .= $_ for grep defined, @_;
},
'err' => sub {
$ipc_error .= $_ for grep defined, @_;
},
);
$ipc->run($script);
$output .= "hrmm.\n";
$output .= "ipc_output:\n$ipc_output\n---\n";
$output .= "ipc_error:\n$ipc_error\n---\n";
};
if ($EVAL_ERROR) {
$output .= "Why does this get into the ipc_output print statment?\n";
$output .= "Why no newlines?\n";
$output .= "EVAL_ERROR WAS: '$EVAL_ERROR'\n";
}
else {
$output .= "OK.\n";
}
print $output;