# New Ticket Created by  Mark Glines 
# Please include the string:  [perl #52462]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=52462 >


When doing a test for --gc=libc, I noticed test 10 of t/op/calling.t
was hanging.  The test creates a FixedIntegerArray from the string "0,
0x20, 0x20, 0".  The new_from_string() constructor relies on STRING*
buffers containing a trailing NULL (which isn't counted in the
"strlen" tally).  The existence of that NULL is not a valid assumption
in the gc=libc case.  Everything goes ok until the following code:

125     start = p;
126     elem  = strtoul(p, &p, base);
127     --p;
128     i -= (p - start);
129     SELF.set_integer_keyed_int(n, elem);
130     break;

The string is 16 bytes long.  On gc=<default>, the cstring buffer is
NULL terminated, and everything works fine.  But the planets have
aligned toward my laptop, or whatever.  So on gc=libc, the cstring
buffer happens to have a "1" directly afterwards in memory.  So the
buffer actually looks like "0, 0x20, 0x20, 01", where the "1" is at
buffer[16].  In other words, directly after the valid area of the
buffer.  But strtoul() doesn't know any better, so it sets &p to
&buffer[17], and the enclosing for() loop spins forever.

I've attached a fix.  It isn't very pretty, and it probably really hurts
performance.  But it fixes the hang, and allows the test script to
complete successfully.  I am submitting it to RT in the hopes that
someone with better knowledge of parrot internals can come up with a
Better Way (tm).

Mark
Index: src/pmc/fixedintegerarray.pmc
===================================================================
--- src/pmc/fixedintegerarray.pmc       (revision 26715)
+++ src/pmc/fixedintegerarray.pmc       (working copy)
@@ -56,11 +56,15 @@
 =cut
 
 */
-    VTABLE PMC *new_from_string(STRING *rep, INTVAL flags) {
+    VTABLE PMC *new_from_string(STRING *rep_orig, INTVAL flags) {
         const INTVAL type = SELF->vtable->base_type;
         INTVAL  n, elem, i, l;
         char   *p, *start;
         int     base;
+        /* the use of strtoul(), below, requires NULL termination. */
+        STRING *null = string_from_cstring(interp, "\0", 1);
+        STRING *rep = string_concat(interp, rep_orig, null, 0);
+        rep->strlen--;
 
         if (flags & PObj_constant_FLAG)
             SELF = constant_pmc_new(INTERP, type);

Reply via email to