Finding the source of a perl taint mode error - perl

When running a perl CGI script in taint mode, I get an error of the form...
Insecure dependency in some_function while running with -T switch at (eval some_line) line some_other_line.
Compilation failed in require at my-script.cgi line 39.
BEGIN failed--compilation aborted at my-script.cgi line 39.
my-script.cgi line 39 is a use statement for a perl module which does not itself use eval or some_function, but presumably uses another library which does. The some_line and some_other_line line numbers don't seem to make sense in either my-script.cgi or the library which is 'use'd on line 39 of my-script.cgi.
Given this error, how can I track down where the taint error is occurring?
I've tried setting a new die signal handler which should print a stack trace, i.e.
$SIG{ __DIE__ } = sub { require Carp; Carp::confess(#_); };
but this seems to have no effect on the error. Perhaps this is the wrong signal to be trapping, not happening early enough, or something more complex is required.

Carp::Always works fine with exceptions raised by taint checks. Example output:
$ perl -MCarp::Always -T blah.pl
Insecure dependency in sprintf while running with -T switch at blah.pl line 6
main::foo() called at blah.pl line 8
main::bar() called at blah.pl line 10

I use Devel::SimpleTrace a lot these days for debugging and it recently helped me find a taint bug when using Archive::Zip.
However, I don't know if it would have worked in your case since it is essentially setting the same sig handler that you used.

Related

CPAN module installation failure

I'm trying to install POE::Component:IRC::State but keep returning this error. I've tried googling but no solutions. Anyone know how to handle this?
install POE::Component:IRC::State
Going to read '/home/user/.cpan/Metadata'
Database was generated on Tue, 22 Jul 2014 11:41:02 GMT
Running install for module 'POE::Component::IRC::State'
Running make for B/BI/BINGOS/POE-Component-IRC-6.88.tar.gz
Checksum for /home/user/.cpan/sources/authors/id/B/BI/BINGOS/POE-Component-IRC-6.88.tar.gz ok
Scanning cache /home/user/.cpan/build for sizes
Use of uninitialized value $newdir in substitution (s///) at /opt/OMNIperl/lib/5.14/i86pc-solaris-thread-multi-64/Cwd.pm line 502.
Use of uninitialized value $newdir in chdir at /opt/OMNIperl/lib/5.14/i86pc-solaris-thread-multi-64/Cwd.pm line 510.
Use of chdir('') or chdir(undef) as chdir() is deprecated at /opt/OMNIperl/lib/5.14/i86pc-solaris-thread-multi-64/Cwd.pm line 510.
Use of uninitialized value $newdir in pattern match (m//) at /opt/OMNIperl/lib/5.14/i86pc-solaris-thread-multi-64/Cwd.pm line 525.
Use of uninitialized value $newdir in split at /opt/OMNIperl/lib/5.14/i86pc-solaris-thread-multi-64/Cwd.pm line 531.
............................................................................DONE
Use of uninitialized value $_[0] in join or string at /opt/OMNIperl/lib/5.14/i86pc-solaris-thread-multi-64/File/Spec/Unix.pm line 86.
Use of uninitialized value $path in pattern match (m//) at /opt/OMNIperl/lib/5.14/i86pc-solaris-thread-multi-64/File/Spec/Unix.pm line 267.
CPAN.pm: Going to build B/BI/BINGOS/POE-Component-IRC-6.88.tar.gz
Warning: No success on command[/opt/OMNIperl/bin/amd64/perl Makefile.PL]
BINGOS/POE-Component-IRC-6.88.tar.gz
/opt/OMNIperl/bin/amd64/perl Makefile.PL -- NOT OK
Running make test
Make had some problems, won't test
Running make install
Make had some problems, won't install
Failed during this command:
BINGOS/POE-Component-IRC-6.88.tar.gz : writemakefile NO '/opt/OMNIperl/bin/amd64/perl Makefile.PL' returned status -1
I came across something similar to this before and I believe the reason for your error, assuming you are receiving this error for other modules installations as well*, is that you need to update your current version of Perl.
From your error report it seems that you are running 5.14 but you should be running 5.20 instead. If this is a remote/personal set up, you can try upgrading your version of Perl but definitely back up everything.
If this is part of a larger system, I would highly advise contacting your system administrator and asking them to look into the problem and have them upgrade it. It is a very sensitive action and upgrading can affect a bunch of other programs you have on your servers.

perl script throws compilation error ONLY when running with -d switch

I have a perl script, that runs fine EXCEPT when I try to run it in the debug mode with the -d switch.
When I use the -d switch, I get a compilation error like:
Loading DB routines from perl5db.pl version 1.33
Editor support available.
Enter h or `h h' for help, or `perldoc perldebug' for more help.
main::(..\..\bin\testnbestrover1.pl:23):
23: binmode STDOUT, ":utf8";
Access is denied.
Unknown error
Compilation failed in require at //fbl/NAS/PUB/RapTools/Perl64/lib/Term/ReadLine
/Perl.pm line 65.
at //fbl/NAS/PUB/RapTools/Perl64/lib/Term/ReadLine/Perl.pm line 65
Term::ReadLine::Perl::new('Term::ReadLine', 'perldb', 'GLOB(0x382418)',
'GLOB(0x322c30)') called at //fbl/NAS/PUB/RapTools/Perl64/lib/perl5db.pl line 60
68
DB::setterm called at //fbl/NAS/PUB/RapTools/Perl64/lib/perl5db.pl line
2241
DB::DB called at ..\..\bin\testnbestrover1.pl line 23
Attempt to reload Term/ReadLine/readline.pm aborted.
Compilation failed in require at //fbl/NAS/PUB/RapTools/Perl64/lib/Term/ReadLine
/Perl.pm line 65.
END failed--call queue aborted at ..\..\bin\testnbestrover1.pl line 65.
at ..\..\bin\testnbestrover1.pl line 65
This does not happen when I run the script without the -d switch. Any ideas about what may be going wrong here?
Thanks!
EDIT:
The same error in Term/ReadLine/Perl.pm line 65 occurs if I comment out the binmode STDOUT, ":utf8"; statement.
Upon searching for this specific error on the web, I found someone else had faced the same error when they were redirecting their STDOUT to a file using the ">" operator. Turns out, my perl command was doing the same thing, and when I removed it, the debugger works fine.
Seems to be a problem with the specific perl debugger (i.e., per5db.pl version 1.33)?
The stacktrace indicates that the problem comes from Term::ReadLine::Perl which is loaded from the debugger. So no debugging -> no loading of debugger -> no loading of Term::ReadLine::Perl -> no error.
From looking at Term::ReadLine::Perl I guess that the problem is in the line where it tries to load Term::ReadLine::readline which tries to do some stuff with STDIN, STDOUT etc to use it as a terminal. Because this effectively means, that some byte sequences have a special meaning (escape and control codes, like to reset terminal, switch line mode, echo etc) this might infere with your binmode STDOUT settings.

Syntax error reading and reversing STDIN

I'm just starting to learn Perl today by going through Modern Perl, but one of the examples is tripping me up. The book has this code:
while (<>)
{
chomp;
say scalar reverse;
}
Running this code with the command perl stdin.pm hi.txt or cat hi.txt | perl stdin.pm gives me this error:
syntax error at stdin.pm line 4, near "say scalar"
Execution of stdin.pm aborted due to compilation errors.
The contents of hi.txt are:
hi
how
are
you
What am I doing wrong?
You can enable say feature
use feature `say`;
or use what author of the book suggest,
use Modern::Perl;

What is the significance of -T or -w in #!/usr/bin/perl?

I googled about #!/usr/bin/perl, but I could not find any satisfactory answer. I know it’s a pretty basic thing, but still, could explain me what is the significance of #!/usr/bin/perl in Perl? Moreover, what does -w or -T signify in #!/usr/bin/perl? I am a newbie to Perl, so please be patient.
The #! is commonly called a "shebang" and it tells the computer how to run a script. You'll also see lots of shell-scripts with #!/bin/sh or #!/bin/bash.
So, /usr/bin/perl is your Perl interpreter and it is run and given the file to execute.
The rest of the line are options for Perl. The "-T" is tainting (it means input is marked as "not trusted" until you check it's format). The "-w" turns warnings on.
You can find out more by running perldoc perlrun (perldoc is Perl's documentation reader, might be installed, might be in its own package).
For scripts you write I would recommend starting them with:
#!/usr/bin/perl
use warnings;
use strict;
This turns on lots of warnings and extra checks - especially useful while you are learning (I'm still learning and I've been using Perl for more than 10 years now).
Both -w and -T are sort of "foolproof" flags.
-w is the same as use warning statement in your code, and it's an equivalent of warning option in many compilers. A simplest example would be a warning about using uninitialized variable:
#!/usr/bin/perl -w
print "$A\n";
print "Hello, world!\n";
Will print:
Name "main::A" used only once: possible typo at ./perl-warnings line 3.
Use of uninitialized value $A in concatenation (.) or string at
./perl-warnings line 3.
Hello, world!
The -T flag means that any value that came from the outside world (as opposite to being calculated inside the program) is considered potential threat, and disallows usage of such values in system-related operations, like writing files, executing system command, etc. (That's why Perl would activate the "taint" mode when the script is running under setuid/setgid.)
The "tainted" mode is "enforcing" you to double-check the value inside the script.
E.g., the code:
#!/usr/bin/perl -T
$A = shift;
open FILE, ">$A";
print "$A\n";
close FILE;
Will produce a fatal error (terminating the program):
$ ./perl-tainted jkjk
Insecure dependency in open while running with -T switch at
./perl-tainted line 3.
And that's only because the argument value came from "outside" and was not "double-checked". The "taint" mode is drawing your attention to that fact. Of course, it's easy to fool it, e.g.:
#!/usr/bin/perl -T
$A = shift;
$A = $1 if $A =~ /(^.*$)/;
open FILE, ">$A";
print "$A\n";
close FILE;
In this case everything worked fine. You "fooled" the "taint mode". Well, the assumption is that programer's intentions are to make the program safer, so the programmer wouldn't just work around the error, but would rather take some security measures. One of Perl's nicknames is "the glue and the duct tape of system administrators". It's not unlikely that system administrator would create Perl script for his own needs and would run it with root permissions. Think of this script doing something normal users are not allowed to do... you probably want to double-check things which are not part of the program itself, and you want Perl to remind you about them.
Hope it helps.
about Taint Mode(-T):
require and use statements change when taint mode is turned on.
The path to load libraries/modules no longer contains . (the current directory) from its path.
So if you load any libraries or modules relative to the current working directory without explicitly specifying the path, your script will break under taint mode.
For ex: Consider perl_taint_ex.pl
#!/usr/bin/perl -T
require "abc.pl";
print "Done";
would fail like this
D:\perlex>perl perl_taint_ex.pl
"-T" is on the #! line, it must also be used on the command line
at perl_taint_ex.pl line 1.
D:\perlex>perl -T perl_taint_ex.pl
Can't locate abc.pl in #INC (#INC contains: C:/Perl/site/lib C:/Perl/lib)
at perl_taint_ex.pl line 3.
So when taint mode is on, you must tell the require statement explicitly where to load the library since . is removed during taint mode from the #INC array.
#INC contains a list of valid paths to read library files and modules from.
If taint mode is on, you would simply do the following:
D:\perlex>perl -ID:\perlex -T perl_taint_ex.pl
Done
-ID:\perlex will include directory D:\perlex in #INC.
You can try other ways for adding path to #INC,this is just one example.
It's called a shebang. On Unix based systems (OSX, Linux, etc...) that line indicates the path to the language interpreter when the script is run from the command line. In the case of perl /usr/bin/perl is the path to the perl interpreter. If the hashbang is left out the *nix systems won't know how to parse the script when invoked as an executable. It will instead try to interpret the script in whatever shell the user happens to be running (probably bash) and break the script.
http://en.wikipedia.org/wiki/Hashbang
The -W and -T are arguments that controll the way the perl interpreter operates. They are the same arguments that you could invoke when calling perl interpreter directly from the command line.
-W shows warnings (aka debuging information).
-T turns on taint / security checking.

Why does TextMate always complain 'Can't find string terminator '"'' when it runs a Perl script?

I have a long-ish Perl script that runs just fine, but always gives this warning:
Can't find string terminator '"' anywhere before EOF at -e line 1
I've read elsewhere online that this is because of a misuse of single or double quotes and the error generally stops the script from running, but mine works. I'm pretty sure I've used my quotes correctly.
Is there anything else that could cause this warning?
EDIT:
I'm running the script via TextMate, which may be spawning a new Perl process to run my script.
I actually get the error when I run simple scripts as well, like this one:
#!/usr/bin/perl -w
use strict;
use warnings;
print "Hello world.";
Yes, you are right, your script does that in TextMate when I try it too.
Simple solution: don't run it using TextMate; just use the command line:
cd Projectdirectory
chmod +x myscript.pl
./myscript.pl
Hello world
More complex solution: tell TextMate that their application is broken and wait for them to fix it. The error is coming from some other Perl script that TextMate is invoking. Even a completely blank file run as Perl in TextMate fails with this error.
-Alex
The "at -e line 1" bit means it's coming from a one-liner. I suspect your long script is somewhere starting a separate perl process (possibly indirectly), and that perl is what is giving the error (and not doing whatever it is supposed to do.)
Start the debugger by doing
perl -d ./youscript.pl
Then keep pressing n[ENTER] (or just ENTER after you press n once) until you see the warning - the line that was just executed is your culprit. n stands for the next debugger directive btw.