Michael Matz changed bug 1092877
What Removed Added
Assignee zypp-maintainers@forge.provo.novell.com schwab@suse.com
Summary zypper dup core dumps vasprintf(&dest, "%s", str) doesn't always fill whole destination

Comment # 8 on bug 1092877 from
Thanks for the initial analysis.  I agree that this is a bug in vasprintf(),
and indeed it only seems to happen on some hardware (or needs very specific
environments to occur).  I can reproduce the problem on rancid.arch.suse.de
with this testcase:

------------ snip ------------------
#define _GNU_SOURCE
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#define N 200000
int main()
{
        char *src, *dest;
        //for (int N = 0; N < 300000; N++) {
                src = malloc(N+1);
                memset (src, 'x', N);
                src[N] = 0;
                //dest = form ("%s", src);
                asprintf(&dest, "%s", src);
                if (strlen (dest) != strlen(src))
                        printf("%d: failed\n", N);
                /*else if (!(N & 63))
                        printf("%d: passed\n", N);*/
                free (dest);
                free (src);
        //}
        return 0;
}
---------------- snap ------------------

When the bug occurs (with 200000 chars on that machine always), then
the destination string is only 102300 characters long.  The _allocated_
length of the destination block is 200001, though, as one can see when
tracing the thing in gdb.  It's also the case that the destination buffer
holds more 'x' characters after some intermediate zeros:

(The last malloc done from within IO_str_overflow):
Breakpoint 2, 0x00007ffff7a9da50 in malloc () from /lib64/libc.so.6
(gdb) p $rdi
$19 = 204700

So it's now allocating a buffer of 204700 bytes (before that all mallocs
ultimately were too small to contain the input string).

Then breaking at the final realloc that supposedly sizes the returned buffer
to the exact length necessary, in vasprintf:

Breakpoint 3, 0x00007ffff7a9e1f0 in realloc () from /lib64/libc.so.6
(gdb) p $rdi
$31 = 140737353601040
(gdb) p/x $rdi
$32 = 0x7ffff7f7d010
(gdb) p $rsi
$33 = 200001

So, %rdi is the returned string, it's allocated size will be 200001, now
looking
at content:

(gdb) p ((char*)$rdi)[102300]@100
$44 = "x", '\000' <repeats 83 times>, 'x' <repeats 16 times>

So, [102300] still has an 'x', then follows some zeros (ultimately making
the string length less than the allocated size), then more 'x' (in fact
until the end, though I haven't checked if there are more intermediate blocks
of zeros).

So something is going amiss when copying the string buffers I believe.


You are receiving this mail because: