Skip to content

Commit

Permalink
grep: avoid shell code evaluation (#749)
Browse files Browse the repository at this point in the history
* grep: avoid shell code evaluation

* When running grep -g or -u, the default code uses Term::Cap but this fails over to executing external tput command
* tput would be available on Linux/BSD but is not a consideration for Windows
* Feed the TERM environment variable to tput command in single quotes to prevent shell commands from being initiated though TERM
* To verify this I had to temporarily bypass the Term::Cap code on my Linux system
* No other instances of backticks, system() or exec() calls within grep

%TERM='linux;halt -p;' perl  grep -g include a.c   # with patch applied tput fails but system doesn't halt
tput: unknown terminal "linux;halt -p;"
tput: unknown terminal "linux;halt -p;"
#include <stdio.h>
#include <stdlib.h>

* execute tput without subshell

* Previous commit was half baked because invalid user input could still creep into shell
* Switch backticks over to system LIST, which does not execute tput via a shell
* Code for redirecting and restoring STDOUT was lifted out of bin/awk
  • Loading branch information
mknos authored Oct 5, 2024
1 parent 4469a0e commit 0f7ff6d
Showing 1 changed file with 23 additions and 4 deletions.
27 changes: 23 additions & 4 deletions bin/grep
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ use strict;

use File::Basename qw(basename);
use File::Spec;
use File::Temp qw();
use Getopt::Std;

our $VERSION = '1.006';
Expand Down Expand Up @@ -121,6 +122,20 @@ EOF
}

###################################
sub run_tput {
my $arg = shift;
my $term = $ENV{'TERM'} || 'vt100';

open my $oldout, '>&', STDOUT or die "$Me: can't save stdout: $!\n";
my $tmp = File::Temp->new;
open STDOUT, '>&', $tmp or die "$Me: can't redirect stdout: $!\n";
system 'tput', '-T', $term, $arg;
seek $tmp, 0, 0 or die "$Me: can't rewind temporary file: $!\n";
my $bin = <$tmp>;
close $tmp or die "$Me: can't close temporary file: $!\n";
open STDOUT, '>&', $oldout or die "$Me: can't restore stdout: $!\n";
return $bin;
}

sub parse_args {
my (%opt, $pattern, @patterns, $match_code, $SO, $SE);
Expand Down Expand Up @@ -197,12 +212,16 @@ sub parse_args {
: ( $terminal->Tputs('us'), $terminal->Tputs('ue') );
}
else { # if use of Term::Cap fails,
my $term = $ENV{'TERM'} || 'vt100';
( $SO, $SE ) = $opt{'g'} # use tput command to get escapes
? ( `tput -T $term smso`, `tput -T $term rmso` )
: ( `tput -T $term smul`, `tput -T $term rmul` );
if ($opt{'g'}) {
$SO = run_tput('smso');
$SE = run_tput('rmso');
}
else {
$SO = run_tput('smul');
$SE = run_tput('rmul');
}
}
}

if ($no_re) {
if ($opt{'g'} || $opt{'u'} || $opt{'w'}) {
Expand Down

0 comments on commit 0f7ff6d

Please sign in to comment.