Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.85k stars 524 forks source link

Hash keys forget taintedness #22137

Open leonerd opened 2 weeks ago

leonerd commented 2 weeks ago

The documentation on taint mode says that the only way to remove taint from a value is to perform a regexp capture on it, and look at the capture buffers. Not so - it turns out that the keys of hashes forget their taintedness too.

#!perl -T
use v5.36;
use Taint::Util;
my $val = "value";
say "1: ", tainted($val)?"TAINT":"not taint";
taint $val;
say "2: ", tainted($val)?"TAINT":"not taint";
my %h = ( $val => 123 );  
my ( $k ) = keys %h;
say "3: ", tainted($k)?"TAINT":"not taint";
1: not taint
2: TAINT
3: not taint

If hash keys remembered taintedness I would have expected the last line to read

3: TAINT
leonerd commented 2 weeks ago

The documentation on taint mode says that the only way to remove taint from a value is to perform a regexp capture on it, and look at the capture buffers

Actually, now I mention that, perlsec does talk about this.

Still, as a quirk, I wonder whether it could be fixed. Either the HEK structure or the HE structure could store an additional bit to say if the key data should be considered tainted.

demerphq commented 2 weeks ago

On Thu, 11 Apr 2024 at 16:55, Paul Evans @.***> wrote:

The documentation on taint mode says that the only way to remove taint from a value is to perform a regexp capture on it, and look at the capture buffers

Actually, now I mention that, perlsec does talk about this.

Still, as a quirk, I wonder whether it could be fixed. Either the HEK structure or the HE structure could store an additional bit to say if the key data should be considered tainted.

I suspect that would break a lot of existing code. Personally I view taint as a failed experiment in software design, I dont think its worth trying to improve it.

Also it raises weird questions, what should happen if I store a tainted key in a hash, and then later store the same key, but untainted.

cheers, Yves -- perl -Mre=debug -e "/just|another|perl|hacker/"

mauke commented 2 weeks ago

Still, as a quirk, I wonder whether it could be fixed. Either the HEK structure or the HE structure could store an additional bit to say if the key data should be considered tainted.

That would change behavior that's been in perl since 5.0 (I think) and documented (in perlsec) since 2003 (commit 595bde10f833e). I bet there is code out there that depends on this. You can't even reasonably change it locally (behind use v5.42 or something): What if new-semantics code adds a tainted key to a hash and then passes the hash to old-semantics code that expects keys to never be tainted?

Anyway, what is the documentation that says the only way to remove taint from a value is to perform a regexp capture on it? I thought the only page that talks about taint mode in detail was perlsec, which does mention the hash keys thing (three times).

Jake-perl commented 2 weeks ago

This behavior is documented and consistent with Perl's taint mode design.

This should work;

use v5.36; use Taint::Util;

my $val = "value"; say "1: ", tainted($val) ? "TAINT" : "not taint";
taint $val; say "2: ", tainted($val) ? "TAINT" : "not taint";

my %h; my $tainted_key = taint_keys($val); $h{$tainted_key} = 123; my ($k) = keys %h; say "3: ", tainted($k) ? "TAINT" : "not taint";

sub taintkeys { my ($value) = @; my $tainted_key = "$value"; taint $tainted_key; return $tainted_key; }