Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is the right time (and the wrong time) to use backticks?

Tags:

perl

Many beginning programmers write code like this:

sub copy_file ($$) {
  my $from = shift;
  my $to = shift;

  `cp $from $to`;
}

Is this bad, and why? Should backticks ever be used? If so, how?

like image 811
raldi Avatar asked Sep 22 '08 16:09

raldi


3 Answers

A few people have already mentioned that you should only use backticks when:

  • You need to capture (or supress) the output.
  • There exists no built-in function or Perl module to do the same task, or you have a good reason not to use the module or built-in.
  • You sanitise your input.
  • You check the return value.

Unfortunately, things like checking the return value properly can be quite challenging. Did it die to a signal? Did it run to completion, but return a funny exit status? The standard ways of trying to interpret $? are just awful.

I'd recommend using the IPC::System::Simple module's capture() and system() functions rather than backticks. The capture() function works just like backticks, except that:

  • It provides detailed diagnostics if the command doesn't start, is killed by a signal, or returns an unexpected exit value.
  • It provides detailed diagnostics if passed tainted data.
  • It provides an easy mechanism for specifying acceptable exit values.
  • It allows you to call backticks without the shell, if you want to.
  • It provides reliable mechanisms for avoiding the shell, even if you use a single argument.

The commands also work consistently across operating systems and Perl versions, unlike Perl's built-in system() which may not check for tainted data when called with multiple arguments on older versions of Perl (eg, 5.6.0 with multiple arguments), or which may call the shell anyway under Windows.

As an example, the following code snippet will save the results of a call to perldoc into a scalar, avoids the shell, and throws an exception if the page cannot be found (since perldoc returns 1).

#!/usr/bin/perl -w
use strict;
use IPC::System::Simple qw(capture);

# Make sure we're called with command-line arguments.
@ARGV or die "Usage: $0 arguments\n";

my $documentation = capture('perldoc', @ARGV);

IPC::System::Simple is pure Perl, works on 5.6.0 and above, and doesn't have any dependencies that wouldn't normally come with your Perl distribution. (On Windows it depends upon a Win32:: module that comes with both ActiveState and Strawberry Perl).

Disclaimer: I'm the author of IPC::System::Simple, so I may show some bias.

like image 56
pjf Avatar answered Oct 30 '22 03:10

pjf


The rule is simple: never use backticks if you can find a built-in to do the same job, or if their is a robust module on the CPAN which will do it for you. Backticks often rely on unportable code and even if you untaint the variables, you can still open yourself up to a lot of security holes.

Never use backticks with user data unless you have very tightly specified what is allowed (not what is disallowed -- you'll miss things)! This is very, very dangerous.

like image 11
Ovid Avatar answered Oct 30 '22 05:10

Ovid


Backticks should be used if and only if you need to capture the output of a command. Otherwise, system() should be used. And, of course, if there's a Perl function or CPAN module that does the job, this should be used instead of either.

In either case, two things are strongly encouraged:

First, sanitize all inputs: Use Taint mode (-T) if the code is exposed to possible untrusted input. Even if it's not, make sure to handle (or prevent) funky characters like space or the three kinds of quote.

Second, check the return code to make sure the command succeeded. Here is an example of how to do so:

my $cmd = "./do_something.sh foo bar";
my $output = `$cmd`;

if ($?) {
   die "Error running [$cmd]";
}
like image 6
raldi Avatar answered Oct 30 '22 05:10

raldi