Re: [perl #31493] Overlapping memory corruption

2004-09-10 Thread Leopold Toetsch
Steve Fink wrote:
Hey, your reason is much better than my reason. Still, why do the
_noinit stuff and duplicate the creation code? Why not just call pmc_new
as in my replacement code?
Cpmc_new would create a Hash already. But the clone has to create one 
of the source type, which might not be quite the same.

leo


[perl #31493] Overlapping memory corruption

2004-09-09 Thread via RT
# New Ticket Created by  Steve Fink 
# Please include the string:  [perl #31493]
# in the subject line of all future correspondence about this issue. 
# URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=31493 


---
osname= linux
osvers= 2.4.21-1.1931.2.382.entsmp
arch=   i386-linux-thread-multi
cc= gcc 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
---
Flags:
category=core
severity=high
ack=no
---
I have a dynamic PMC named 'Match' that extends the PerlHash PMC. I
have occasionally been seeing destroy() not implemented in class
'Match' on program shutdown. Match does not define destroy(), nor
does it set the active destroy flag. Looking deeper, I find that it's
trying to dispose of a PMC with its -obj.flags member completely
trashed, and in particular it has an erroneous bit set for the active
destroy flag.

I won't go through all the details of what I looked at (though I'll
post them in my blog eventually), but what's happening is that this
line (from perlhash.pmc's clone() implementation) is corrupting the
flags field:

((Hash*)PMC_struct_val(dest))-container = dest;

The problem is that the dest PMC contains a Hash structure in its
struct_val field, but the address of the Hash is only 0x18 bytes
before the address of the PMC itself, and Hashes are 0x40 bytes
each. The offset of the container field within a Hash is 0x20, and the
offset of the flags field within a PMC is 0x04. So assigning to that
container field overwrites the flags field, since 0x18 + 0x04 == 0x20.

It seems like an initialization ordering problem, especially since I
can make the problem go away by changing the clone() method from

PMC* clone () {
PMC* dest = pmc_new_noinit(INTERP, SELF-vtable-base_type);
PObj_custom_mark_SET(dest);
((Hash*)PMC_struct_val(dest))-container = dest;
hash_clone(INTERP, (Hash *)PMC_struct_val(SELF),
   (Hash**)PMC_struct_val(dest));
return dest;
}

to

PMC* clone () {
PMC* dest = pmc_new(INTERP, SELF-vtable-base_type);
hash_clone(INTERP, (Hash *)PMC_struct_val(SELF),
   (Hash**)PMC_struct_val(dest));
return dest;
}

But I'm not sure why, and I'm not sure if this is a bug in perlhash's
clone(), or some weird side effect of using dynamic PMCs. (For now,
I'm just reimplementing clone() in my subclass.)

---
Summary of my parrot 0.1.0 configuration:
  configdate='Wed Sep  8 23:20:30 2004'
  Platform:
osname=linux, archname=i386-linux-thread-multi
jitcapable=1, jitarchname=i386-linux,
jitosname=LINUX, jitcpuarch=i386
execcapable=1
perl=/usr/bin/perl
  Compiler:
cc='ccache gcc', ccflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS 
-DDEBUGGING  -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 
-I/usr/include/gdbm -O1',
  Linker and Libraries:
ld='gcc', ldflags=' -L/usr/local/lib',
cc_ldflags='',
libs='-lnsl -ldl -lm -lpthread -lcrypt -lutil -lrt -lgmp'
  Dynamic Linking:
so='.so', ld_shared='-shared -L/usr/local/lib -fPIC',
ld_shared_flags=''
  Types:
iv=long, intvalsize=4, intsize=4, opcode_t=long, opcode_t_size=4,
ptrsize=4, ptr_alignment=1 byteorder=1234, 
nv=double, numvalsize=8, doublesize=8

---
Environment:
HOMELANGLANGUAGELC_ALLLD_LIBRARY_PATHLOGDIRPATHSHELL


Re: [perl #31493] Overlapping memory corruption

2004-09-09 Thread Leopold Toetsch
Steve Fink (via RT) wrote:
I won't go through all the details of what I looked at (though I'll
post them in my blog eventually), but what's happening is that this
line (from perlhash.pmc's clone() implementation) is corrupting the
flags field:
((Hash*)PMC_struct_val(dest))-container = dest;
Ah, yep. PMC_struct_val(dest) doesn't hold the hash yet, it is created 
in hash_clone() only after this line.

The problem is that the dest PMC contains a Hash structure in its
struct_val field
No. That's the pointer of the free_list, pointing to the previous PMC in 
that size class.
Putting above line after the hash_clone() fixes that bug.

Thanks for reporting,
leo


Re: [perl #31493] Overlapping memory corruption

2004-09-09 Thread Steve Fink
On Sep-09, Leopold Toetsch wrote:
 Steve Fink (via RT) wrote:
 
 I won't go through all the details of what I looked at (though I'll
 post them in my blog eventually), but what's happening is that this
 line (from perlhash.pmc's clone() implementation) is corrupting the
 flags field:
 
 ((Hash*)PMC_struct_val(dest))-container = dest;
 
 Ah, yep. PMC_struct_val(dest) doesn't hold the hash yet, it is created 
 in hash_clone() only after this line.
 
 The problem is that the dest PMC contains a Hash structure in its
 struct_val field
 
 No. That's the pointer of the free_list, pointing to the previous PMC in 
 that size class.
 Putting above line after the hash_clone() fixes that bug.

Hey, your reason is much better than my reason. Still, why do the
_noinit stuff and duplicate the creation code? Why not just call pmc_new
as in my replacement code?