Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: does reassigning a new value to a scalar overwrite its current contents in RAM?

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?

like image 341
LawrenceC Avatar asked Jul 30 '11 17:07

LawrenceC


2 Answers

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
like image 197
ikegami Avatar answered Sep 21 '22 14:09

ikegami


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
like image 22
bvr Avatar answered Sep 22 '22 14:09

bvr