I'm using Perl for a security-related task and am wondering when a statement such as:
$test = "new value"
is executed, is the old value that $test created overwritten in RAM?
If not, is there a way to force that to happen?
I'm using Perl for a security-related task and am wondering when a statement such as:
$test = "new value"
is executed, is the old value that $test created overwritten in RAM?
If not, is there a way to force that to happen?
If the scalar isn't magical and it has a string buffer and the string fits in the string buffer, then that portion of the string buffer will be overwritten.
Note that
$s = "abcdef";
$s =~ s/...//;
$s = "x" x length($s);
leaves "xxx\0ef\0" in the scalar's buffer. You want the buffer's length, and not the length of the string inside the buffer.
I meant to say that neither of
$s = undef;
$s = 123;
will affect the string buffer whatsoever. It won't even be deallocated. Similarly, assigning a string to a scalar will not affect the other fields of the scalar, such as fields to hold numbers.
I forgot that if string being assigned to the scalar is a TEMP, the buffer of the target is replaced instead of being overwritten.
>perl -MDevel::Peek -e"my $s = 'abc'; Dump($s); $s = 'X' x length($s); Dump($s);"
SV = PV(0x348d54) at 0x1d3927c
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x349fac "abc"\0
CUR = 3
LEN = 12
SV = PV(0x348d54) at 0x1d3927c
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x349fac "XXX"\0 <-- same address
CUR = 3
LEN = 12
>perl -MDevel::Peek -e"my $s = 'abc'; Dump($s); $s = sub { 'X' x length($s); }->(); Dump($s);"
SV = PV(0x38d54) at 0x1c3930c
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x39fac "abc"\0
CUR = 3
LEN = 12
SV = PV(0x38d54) at 0x1c3930c
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x1c603fc "XXX"\0 <-- different address
CUR = 3 No overwriting.
LEN = 12
You can use Devel::Peek module to answer this kind of questions:
use Devel::Peek;
my $test = "value";
Dump($test);
$test = "new value";
Dump($test);
In this case you get:
SV = PV(0x297c04) at 0x187b9ac
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x18751cc "value"\0
CUR = 5
LEN = 12
SV = PV(0x297c04) at 0x187b9ac
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x18751cc "new value"\0
CUR = 9
LEN = 12
It can be easily seen that address in this case remained the same. As others noted, if your string is longer than buffers LEN, the data will be reallocated:
my $test = "value";
Dump($test);
$test = "new value that is much longer";
Dump($test);
yields (see that pointer next to PV changed):
SV = PV(0x297c04) at 0x187b9ac
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x18751cc "value"\0
CUR = 5
LEN = 12
SV = PV(0x297c04) at 0x187b9ac
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x187cf74 "new value that is much longer"\0
CUR = 29
LEN = 32
I think it depends on what the previous value of $test was.
If, for instance, the new value is longer, perl will have to call realloc() (or something similar) which can change where the string is stored.
In general, the perl string operations seem to use the same memory when possible, although I don't think this is guaranteed.
You can get the address of the string buffer of a scalar unpack('J', pack('P', $s)). This doesn't work if the scalar doesn't contain a string (even if it has a string buffer).