2015-11-15 8 views
12

ho visto questa riga di codice in alcune fontiUntainting un membro di hash benedetto con o senza l'eliminazione

($self->{arg}) = ((delete $self->{arg}) =~ /(.*)/s) if ${^TAINT}; 

Capisco l'untainting. Ho anche conosciuto delete

La mia domanda è, in quali circostanze è necessario o preferito usare il delete, e non è sufficiente per utilizzare la più semplice

($self->{arg}) = (($self->{arg}) =~ /(.*)/s) if ${^TAINT}; 

Per esempio

#!/usr/bin/env perl -T 

use 5.014; 
use warnings; 

package Some { 
    use Moose; 
    has 'arg' => (is => 'rw', isa => 'Str'); 
    sub doit { 
     my $self = shift; 
     #($self->{arg}) = ((delete $self->{arg}) =~ /(.*)/s) if ${^TAINT}; 
     ($self->{arg}) = (($self->{arg}) =~ /(.*)/s) if ${^TAINT}; 
    } 
}; 

my $some = Some->new(arg => 'some text'); 
$some->doit(); 
say $some->arg; 
+1

Sono d'accordo con te. Modificare il valore di hash in posto (o, in questo caso, lasciarlo invariato) sembra essere equivalente all'eliminazione e al reinserimento. Puoi dire dove hai visto questa pratica? – Borodin

+0

@Borodin l'ho visto https://metacpan.org/source/JSWARTZ/Mason-2.24/lib/Mason/Compilation.pm#L105 – Nemo

+1

Può fare la differenza in caso di tie() s, ma non ne vedo nessuno qui . Boh. Non penserei mai di farlo. –

risposta

3

Con un cancelletto normale che cancella il valore e il reinserimento darà lo stesso risultato della modifica in atto.

Il commit non fornisce alcuna informazione sul perché elimina solo che copia la funzionalità da Mason 1. Ma se si guarda alla fonte di HTML::Mason::Lexer, troverete questo commento:

Abbiamo bisogno per stappare il componente, altrimenti le regex falliranno in un bug Perl. L'eliminazione è importante perché abbiamo bisogno di creare uno scalare completamente nuovo, non solo modificare quello esistente.

($current->{comp_source}) = (delete $current->{comp_source}) =~ /(.*)/s if taint_is_on; 

Quindi la ragione di farlo in questo modo è quello di avere un nuovo scalare, anche se lui non lo fa per l'altro posto dove si trova untainting: Mason::Interp, quindi la mia ipotesi è un Perl bug in precedenza, quando non dipingi.

Quindi la differenza è che con delete si otterrà un nuovo scalare, anche se raramente avrà un'applicazione pratica. (Delete e l'inserto è anche un'operazione più lenta, naturalmente.)

use strict; 
my $hash->{test} = 'test'; 
print \($hash->{test}),"\n"; 
($hash->{test}) = (($hash->{test}) =~ /(.*)/s); 
print \($hash->{test}),"\n"; 
($hash->{test}) = ((delete $hash->{test}) =~ /(.*)/s); 
print \($hash->{test}),"\n"; 

SCALAR(0x7f84d10047e8) 
SCALAR(0x7f84d10047e8) 
SCALAR(0x7f84d1029230) 
Problemi correlati