Heffstar has asked for the wisdom of the Perl Monks concerning the following question:

Good Afternoon Monks,

I'm trying to solve a problem with the error "can't use string ('<insert path here>') as a symbol ref while \"strict refs\" in use at...".

I'm not fantastic with taint checking but I've followed this the best I could and I'm still stumped. Maybe there's some advice out there for this snippet:

my $frompath = "$DATAPATH/documentset/$company/$dept/$doc_id"; my $writetopath = "$EX_DATAPATH/external_gn/$doc_id"; my $u = new MyMod::Untaint; my ($untainted_source_path, undef) = $u->untaintMe($frompath, 'path'); my ($untainted_dest_path, undef) = $u->untaintMe($writetopath, 'path') +; #we have to add this afterward to handle the case of using '*' for ima +ges. '*' makes the string fail normal taint checking. $untainted_source_path .= ".$extension"; $untainted_dest_path .= ".$extension"; if ($untainted_source_path =~ m/^([\/\w\-._*]+)$/ ) { $untainted_source_path="$1"; } else { $g->errorpage($q,"Error adding source file extension. Please contact + the MIS help desk."); } if ($untainted_dest_path =~ m/^([\/\w\-._*]+)$/ ) { $untainted_dest_path="$1"; } else { $g->errorpage($q,"Error adding destination file extension. Please co +ntact the MIS help desk."); } copy($untainted_source_path, $untainted_dest_path); my $upload = &upload_file($g, $q, $untainted_source_path, $untainted_d +est_path);
sub untaintMe()
sub untaintMe { my ($self, $inputArg, $typeArg) = @_; my ($temp, $reason); my @returnArray; if ($typeArg eq 'path') { $inputArg =~ /[\/\w\-._]+/; # includes 'file' chars + "\" $temp = $&; $reason = $` . '...' . $'; # create the reason code } if ($reason eq '...') # no mismatches found if ($temp ne '') { @returnArray = ($temp, ""); } else { @returnArray = ('', "invalid input, not enough characters to ma +tch $typeArg pattern"); } } else { @returnArray = ('', "invalid input, string contains $reason"); } return @returnArray; }
sub upload_file()
sub upload_file() { my ($g, $q, $readpath, $writepath) = @_; my ($bytesread, $buffer); if (!open(WFD,"<$readpath")) { $g->errorpage($q, "Could not copy $readpath: $!\n"); return 0; } $| = 1; # turn off buffering of stdout if (!open(WFD,">$writepath")) { $g->errorpage($q, "Error opening file '$writepath' for writing: $! +\n"); return 0; } #### ## Error points to the following line #### while ($bytesread = read($readpath,$buffer,1024)) { # can't use str +ing "<directory_goes_here>" as a symbol ref while "strict refs" in us +e binmode WFD; print WFD $buffer; } close(WFD); $| = 0; # turn on buffering of stdout chmod 0600, "$writepath"; return 1; }

If someone has some sound advice or can point me in the direction of a solid thread that deals with this error, I'd be pretty darned appreciative! Or hell, even a "why the heck are you doing it that way?!" would be good.

I've never seen the $& used before in untainting, but again, I'm not that fluent in this to begin with...

Thanks in advance... ~Hugh

Replies are listed 'Best First'.
Re: File Upload - Strict Ref Issue
by ikegami (Patriarch) on Oct 28, 2009 at 22:12 UTC
    The error message is poor. It's being triggered by the the first argument of read. It should be a file handle, but isn't. Fix:
    sub upload_file { my ($g, $q, $readpath, $writepath) = @_; my $rfh; if (!open($rfh, "<", $readpath)) { $g->errorpage($q, "Could not open file '$readpath': $!\n"); return 0; } my $wfh; if (!open($wfh, '>', $writepath)) { $g->errorpage($q, "Error creating file '$writepath': $!\n"); return 0; } binmode($rfh); binmode($wfh); while (read($rfh, my $buf, 4*1024)) { print $wfh $buf; } close($wfh); chmod 0600, $writepath; return 1; }

    I got rid of your $| manipulation since you don't even use STDOUT.

    I got rid of the sub's prototype. Not only should prototypes be avoided in general, it was completely wrong forcing you to bypass it elsewhere by wrongly adding "&" to sub calls.

      Holy crap. I was guided into perl and "learned" it from existing, and apparently poorly written, code. Prototyping like this was ALWAYS done, so I just followed suit...

      Should I be closing my read filehandle?

      I'll give this a shot, thanks VERY much for the input ikegami.

        They're lexically scoped, so they'll get closed when the sub exits. I left the close for the writer in case having an open handle prevents chmod from working.

      I tried to implement the open syntax you provided, but my version of perl doesn't support it. We're using 5.00503, which might be the problem.

      I've put it forward that we actually get our software updated for the first time in... who ever knows. We'll see what comes of it.

      Thanks again for your input.

        First time in a decade. 5.6 introduced the 3-arg open in 2000.