John E. Malmberg wrote:
Nicholas Clark wrote:
On Sat, Jul 30, 2005 at 12:27:43AM -0400, John E. Malmberg wrote:
The address 10439704 was already a part of the structure that
Perl_hv_iternext_flags() had pointed a variable named iter at.
DBG> exam *iter
*HV\Perl_hv_iternext_flags\iter
xhv_name: 1162633044
xhv_eiter: 4998486
xhv_riter: -256
DBG> eval/addr iter->xhv_riter
10439704
It appears to me that one of these structures was not allocated large
enough for the data that is being put in it. As the xpvhv_aux
structure is a fixed size structure, my suspicion is that the problem
is the above code somewhere since this is where the HEK struct is
allocated just before *iter got corrupted.
However the xpvhv_aux structure is allocated by extending the HV's array
of linked list heads, and using space after it. So there is the
possibility
that there is a code path where the extending realloc() didn't take
place,
and the memory is being used out-of-bounds.
What is the value of sv_flags in the hash?
(struct hv, defined in sv.h, typdef'd to HV)
DBG> exam/hex *hv
*HV\Perl_hv_iternext_flags\hv
sv_any: 0097721C
sv_refcnt: 00000001
sv_flags: 2020C00C
sv_u
[Displaying union member number 1]
svu_iv: 009D33D8
DBG>
Specifically is bit 0x00200000 set? It should be, where xpvhv_aux is
in use
(See the comment near SVf_OOK in sv.h)
The bit is set. Of course I am looking after a state where I know that
data corruption has taken place, so I will need start over and look again.
I'm about to set off to the US for OSCON, so I'm unlikely to be in a
position
to read mail, let alone respond to it, for over 24 hours. (travel +
sleep)
Ok,
So what I need to look at in the mean time is how and where the
xpvhv_aux structure gets allocated. Looking for that bit being set is
probably my best clue.
From what I can see, if the name for the environment variable being
stored in the hash had been 1 byte less in length, this data corruption
may be invisible.
Right now my reproducer is test 16 of script t/run/switches.t which
spawns the VMS command:
$ MCR EAGLE$DQA0:[PROJECT_ROOT.perl-blead.][000000]DBGPERL.EXE;1 -
"-I../lib" "-V"
Other spawned Perl commands succeed, so I do not know what is different
here.
What I have found is that in this case is that the allocation size for
the sv_u.svu_array member appears to be too small.
The size of the allocated or reallocated array is controlled by the
xhv_max member.
DBG> exam hv->sv_any->xhv_max
HV\Perl_hv_iternext_flags\hv->sv_any->xhv_max: 7
The actual calculation is for the array size =
PERL_HV_ARRAY_ALLOC_BYTES(HvMAX(hv) + 1) + sizeof(struct xpvfhv_aux)
HvMAX(hv) = 7 from above.
So PERL_HV_ARRAY_ALLOC_BYTES results in:
(8 * sizeof(HE*) + sizeof(struct xpvfhv_aux)
The size of a Pointer type on VMS is 4 bytes. And the size of the
struct xpvfhv is 12 bytes. This results in (8 * 4) + 12 or 48 bytes.
A pointer to the xpvfhv is then stored in hv->sv_u.svu_array[8].
The size of the svu_array type is 12, so the offset is 12 * (8-1) is 84
which is a bit beyond the 48 bytes that was allocated.
It appears to me that macro PERL_HV_ARRAY_ALLOC_BYTES should be using
the size of the HE structure instead of the size of a pointer to that
structure.
If that were the calculation, than 108 bytes would have been allocated
or reallocated for the array member, which looks like the correct size.
-John
[EMAIL PROTECTED]
Personal Opinion Only