I was playing around a bit with the set_keyed and get_keyed ops and found
that this:
new P0, PerlArray
set I0, 0
LOOP: set_keyed P0, I0, I0
inc I0
lt I0, 10000, LOOP
end
causes Parrot to segfault.
The culprit appears to be this bit of code in trace_active_PMCs in
resources.c:
----
else {
/* The only thing left is "buffer of PMCs" */
Buffer *trace_buf = current->data;
PMC **cur_pmc = trace_buf->bufstart;
/* Mark the damn buffer as used! */
trace_buf->flags |= BUFFER_live_FLAG;
for (i = 0; i < trace_buf->buflen; i++) {
if (cur_pmc[i]) {
last = mark_used(cur_pmc[i], last);
}
}
}
----
The problem is that trace_buf->buflen is the size of the buffer, and
not the number of PMCs contained in it, so the loop reads out of the
end of cur_pmc and into garbage data. The patch below fixes this, and
also adds a test-case to perlarray.t to stop it from coming back.
Simon
--- resources.c.old Sat Apr 20 17:55:28 2002
+++ resources.c Sat Apr 20 17:58:45 2002
@@ -462,9 +462,10 @@
/* The only thing left is "buffer of PMCs" */
Buffer *trace_buf = current->data;
PMC **cur_pmc = trace_buf->bufstart;
+ UINTVAL no_of_pmcs = trace_buf->buflen / sizeof(PMC*);
/* Mark the damn buffer as used! */
trace_buf->flags |= BUFFER_live_FLAG;
- for (i = 0; i < trace_buf->buflen; i++) {
+ for (i = 0; i < no_of_pmcs; i++) {
if (cur_pmc[i]) {
last = mark_used(cur_pmc[i], last);
}
--- t/pmc/perlarray.t.old Sat Apr 20 18:09:16 2002
+++ t/pmc/perlarray.t Sat Apr 20 18:13:48 2002
@@ -1,6 +1,6 @@
#! perl -w
-use Parrot::Test tests => 6;
+use Parrot::Test tests => 7;
use Test::More;
output_is(<<'CODE', <<'OUTPUT', "size of the array");
@@ -275,4 +275,18 @@
ok 19
OUTPUT
+output_is(<<'CODE', <<'OUTPUT', "Array resizing stress-test");
+ new P0, PerlArray
+ set I0, 0
+LOOP: set_keyed P0, I0, I0 # set P0[I0], I0
+ inc I0
+ lt I0, 10000, LOOP
+ get_keyed I1, P0, 9999 # set I1, P0[9999]
+ print I1
+ print "\n"
+ end
+CODE
+9999
+OUTPUT
+
1;