in reply to backticks execution "inside" variable (string)

eval'ing user-supplied string (the filename) within perl is not only dangerous as others said but it is a practice frowned upon and you will be told off (even if it is innocent) if this is at work.

I would use a function to parse the user-input/filename and recognise a *few* things that may be useful in a log filename. For example date:

#!/usr/bin/perl use strict; use warnings; use Time::Piece; my $newfilename = userinput2filename($ARGV[0]); print "got this: $newfilename\n"; sub userinput2filename { my $inp = $_[0]; my $out = $inp; while( $out =~ s/`(.+?)`/_userinput2filename($1)/eg ){} return $out } sub _userinput2filename { my $inp = $_[0]; # date +FORMAT where FORMAT must be understood by POSIX's strftime if( $inp =~ /^date\s+\+(.+?)$/ ){ return Time::Piece->new()->strftim +e($1) } # insert other cases you want to substitute # eventually there is something in backticks that is not in our list die "do not understand '$inp'" }

Replies are listed 'Best First'.
Re^2: backticks execution "inside" variable (string)
by richard.sharpe (Sexton) on Dec 20, 2019 at 14:34 UTC

    Thank you, Bliako, for inspirative command-safeness checking example!

    Although I am afraind, it won't be useful in my case, because in general, there could be anything between backticks, and nevertheless, there is some human-checking in our use case.

    Therefore I am curious, if exists something like this (or I would need to implement it into my codebase myself):

    my $backticketed_string = 'static text `execute this` static text `exe +cute this` ... `execute this` static text'; my $interpolated_string = interpolate_all_backtick_pairs($backticketed +_string);

    It is possible, that there is no such thing in Perl modules or built-ins, and this is not meant to abuse you guys, to do this work instead of me, as said also here.

    Greetings to Island of Saints!

      then try this (with all the bells and whistles for shelling out user input):

      use IPC::Cmd; sub _userinput2filename { my $cmd = $_[0]; print "executing >>unchecked<< user-input : '$cmd'\n"; # see https://perldoc.perl.org/IPC/Cmd.html for more details: my( $success, $error_message, $full_buf, $stdout_buf, $stderr_buf ) += IPC::Cmd::run( command => $cmd, verbose => 1, ); die "failed : $error_message (@$stderr_buf)" unless $success; # this is the stdout of the command return $stdout_buf }

      userinput2filename($string) will run each `command` block in $string and substitute it with the result of command's execution (stdout with all newlines in there) unless there is a failure whereas it dies. Regards to over the hills and far away...

      Edit: it needs the sub (userinput2filename) and main from my previous post.