perl5 icon indicating copy to clipboard operation
perl5 copied to clipboard

Hash keys forget taintedness

Open leonerd opened this issue 10 months ago • 4 comments

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 avatar Apr 11 '24 14:04 leonerd

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.

leonerd avatar Apr 11 '24 14:04 leonerd

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/"

demerphq avatar Apr 11 '24 16:04 demerphq

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).

mauke avatar Apr 11 '24 17:04 mauke

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 taint_keys { my ($value) = @_; my $tainted_key = "$value"; taint $tainted_key; return $tainted_key; }

Jake-perl avatar Apr 16 '24 16:04 Jake-perl