[LLVMbugs] [Bug 21573] New: libxcb-1.11 miscompiles with Clang -O2 on x86_32/linux

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Fri Nov 14 07:47:18 PST 2014


http://llvm.org/bugs/show_bug.cgi?id=21573

            Bug ID: 21573
           Summary: libxcb-1.11 miscompiles with Clang -O2 on x86_32/linux
           Product: new-bugs
           Version: unspecified
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: joakim.gebart at eistec.se
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified

The function get_peer_sock_name in src/xcb_auth.c of libxcb-1.11 generates
broken assembly code on x86_32 when compiled with Clang/LLVM-3.5.0 using -O2
optimization level, this does not happen on -O1 or lower level, it also seems
to work correctly on x86_64 even with -O2.

The C code first calls malloc(), then checks the returned pointer for NULL,
finally calls the function getpeername() or getsockname() via a function
pointer, using the malloc'ed pointer as second argument.

When compiled with -O2 the assembly code generated will (incorrectly)
dereference the pointer returned by malloc() and pass the value pointed at as
second argument to the getpeername() function call.

By coincidence, the uninitialized malloced area may contain a valid pointer
which results in a corrupt heap since the getpeername function will write its
result to an incorrect address.

C-code snippet below:

/* Return a dynamically allocated socket address structure according
   to the value returned by either getpeername() or getsockname()
   (according to POSIX, applications should not assume a particular
   length for `sockaddr_un.sun_path') */
static struct sockaddr *get_peer_sock_name(int (*socket_func)(int,
                                                              struct sockaddr
*,
                                                              socklen_t *),
                                           int fd)
{
    socklen_t socknamelen = sizeof(struct sockaddr) + INITIAL_SOCKNAME_SLACK;
    socklen_t actual_socknamelen = socknamelen;
    struct sockaddr *sockname = malloc(socknamelen);

    if (sockname == NULL)
        return NULL;

    /* Both getpeername() and getsockname() truncates sockname if
       there is not enough space and set the required length in
       actual_socknamelen */
    if (socket_func(fd, sockname, &actual_socknamelen) == -1) // <======= This
is where the incorrect dereference happens. /////////////
        goto sock_or_realloc_error;

    if (actual_socknamelen > socknamelen)
    {
        struct sockaddr *new_sockname = NULL;
        socknamelen = actual_socknamelen;

        if ((new_sockname = realloc(sockname, actual_socknamelen)) == NULL)
            goto sock_or_realloc_error;

        sockname = new_sockname;

        if (socket_func(fd, sockname, &actual_socknamelen) == -1 ||
            actual_socknamelen > socknamelen)
            goto sock_or_realloc_error;
    }

    return sockname;

 sock_or_realloc_error:
    free(sockname);
    return NULL;
}

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20141114/e2439fab/attachment.html>


More information about the llvm-bugs mailing list