7

我正在将 Perl 用于与安全相关的任务,并且想知道何时使用以下语句:

$test = "new value"

$test执行时,在 RAM中创建的旧值是否被覆盖?

如果没有,有没有办法强迫这种情况发生?

4

3 回答 3

13

如果标量不是神奇的并且它有一个字符串缓冲区并且字符串适合字符串缓冲区,那么字符串缓冲区的那部分将被覆盖。

注意

$s = "abcdef";
$s =~ s/...//;
$s = "x" x length($s);

在标量的缓冲区中留下“xxx\0ef\0”。您需要缓冲区的长度,而不是缓冲区内字符串的长度。

我的意思是说

$s = undef;
$s = 123;

无论如何都会影响字符串缓冲区。它甚至不会被释放。同样,将字符串分配给标量不会影响标量的其他字段,例如保存数字的字段。


我忘记了如果分配给标量的字符串是 a TEMP,则目标的缓冲区将被替换而不是被覆盖。

>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
于 2011-07-30T18:07:43.563 回答
9

您可以使用Devel::Peek模块来回答此类问题:

use Devel::Peek;

my $test = "value";
Dump($test);
$test = "new value";
Dump($test);

在这种情况下,您会得到:

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

可以很容易地看出,这种情况下的地址保持不变。正如其他人指出的那样,如果您的字符串比 buffers 长LEN,数据将被重新分配:

my $test = "value";
Dump($test);
$test = "new value that is much longer";
Dump($test);

产量(请参阅更改旁边的指针PV):

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
于 2011-07-30T19:22:50.173 回答
3

我认为这取决于以前的值$test是什么。

例如,如果新值更长,perl 将不得不调用 realloc() (或类似的东西),这可以改变字符串的存储位置。

一般来说,perl 字符串操作似乎尽可能使用相同的内存,尽管我不认为这是有保证的。

您可以获得标量的字符串缓冲区的地址unpack('J', pack('P', $s))。如果标量不包含字符串(即使它有字符串缓冲区),这将不起作用。

于 2011-07-30T18:06:31.623 回答