# 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);