John E. Malmberg wrote:

The patch that I submitted is needed to eliminate a data corruption issue that should be affecting more than just VMS.

If I have diagnosed this wrong, please let me know.

just a wild conjecture from the peanut gallery.
There are some pretty subtle tricks played in the memory allocation areas,
which might explain why nobodys responding; most dont understand it all deeply, and given that tests pass so successfully, its hard to imagine an error of the size
you suggest could be universally present.
(or it could be august vacations, or firefighting at day jobs)



In VMS this data corruption is only visible in one apparent test script where it causes Perl to exit with an access violation after a pointer gets stepped on. So it is easy to see how it might get missed.

What I have found after Nicholas Clark pointed me in the right direction, 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 bytes, 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.

This starts to hint at the complexities im refering to:
http://gisle.aas.no/perl/illguts/

As a special case we also have /SvIV/ and /SvNV/ types that only have room for a single integer or a single double value. These are special in that the PVX/CUR/LEN fields are not present even if the ANY pointer actually points to the ghostual incarnation of them. This arrangement makes it possible for code to always access the IVX/NVX fields at a fixed offset from where the SV field ANY points.



this same trick is also used and described in sv.c

1157 #define new_body_type(TYPE,lctype) \ 1158 S_new_body(aTHX_ (void**)&PL_ ## lctype ## _arenaroot, \ 1159 (void**)&PL_ ## lctype ## _root, \
  1160                  sizeof(TYPE))
  1161
  1162 #define del_body_type(p,TYPE,lctype)                    \
  1163     del_body((void*)p, (void**)&PL_ ## lctype ## _root)
  1164
1165 /* But for some types, we cheat. The type starts with some members that are 1166 never accessed. So we allocate the substructure, starting at the first used 1167 member, then adjust the pointer back in memory by the size of the bit not
  1168    allocated, so it's as if we allocated the full structure.
1169 (But things will all go boom if you write to the part that is "not there", 1170 because you'll be overwriting the last members of the preceding structure
  1171    in memory.)
  1172
1173 We calculate the correction using the STRUCT_OFFSET macro. For example, if 1174 xpv_allocated is the same structure as XPV then the two OFFSETs sum to zero, 1175 and the pointer is unchanged. If the allocated structure is smaller (no 1176 initial NV actually allocated) then the net effect is to subtract the size 1177 of the NV from the pointer, to return a new pointer as if an initial NV were
  1178    actually allocated.
  1179
1180 This is the same trick as was used for NV and IV bodies. Ironically it 1181 doesn't need to be used for NV bodies any more, because NV is now at the 1182 start of the structure. IV bodies don't need it either, because they are
  1183    no longer allocated.  */
  1184
1185 #define new_body_allocated(TYPE,lctype,member) \ 1186 (void*)((char*)S_new_body(aTHX_ (void**)&PL_ ## lctype ## _arenaroot, \ 1187 (void**)&PL_ ## lctype ## _root, \ 1188 sizeof(lctype ## _allocated)) - \ 1189 STRUCT_OFFSET(TYPE, member) \
  1190             + STRUCT_OFFSET(lctype ## _allocated, member))
  1191

sv.h also has some clues

   286 #if 0
   287 typedef struct xpv xpv_allocated;
   288 #else
   289 typedef struct {
   290     STRLEN      xpv_cur;        /* length of svu_pv as a C string */
   291     STRLEN      xpv_len;        /* allocated size */
   292 } xpv_allocated;
   293 #endif
   294


Im not saying the explanation is here, but certainly some clues
and deeper understanding are.

-John
[EMAIL PROTECTED]
Personal Opinion Only

hth,
Jim Cromie

Reply via email to