1

Running Valgrind on my program generates an invalid read of size 4 error. I'm trying to locate it, but can't seem to find it.

#define _GNU_SOURCE
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/socket.h>

void download_file (void){
    int ret;
    char *service = "http";
    char *site = "www.sony.com";
    char *page = "/";
    char *msg;
    struct addrinfo *res;
    struct addrinfo hints;
    const char * format = "GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0\r\n\r\n";
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    asprintf(&msg, format, page, site);

    if((ret = getaddrinfo(site, service, &hints, &res)) != 0){
        fprintf(stderr, "download_file: getaddrinfo error: %s\n", gai_strerror(ret));
        freeaddrinfo(res);
        free(msg);
        return;
    }
    freeaddrinfo(res);
    free(msg);
    return;
}
int main (void){
    download_file();
    exit(0);
}

Here is the output from Valgrind:

==3215== Memcheck, a memory error detector
==3215== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==3215== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==3215== Command: ./a.out
==3215== 
==3215== Invalid read of size 4
==3215==    at 0x401718C: strlen (strlen.S:53)
==3215==    by 0x4012F1F: _dl_open (dl-open.c:672)
==3215==    by 0x495982F: do_dlopen (dl-libc.c:86)
==3215==    by 0x400F0BF: _dl_catch_error (dl-error.c:178)
==3215==    by 0x4959917: dlerror_run (dl-libc.c:47)
==3215==    by 0x495997F: __libc_dlopen_mode (dl-libc.c:160)
==3215==    by 0x4935447: __nss_lookup_function (nsswitch.c:434)
==3215==    by 0x493569B: __nss_lookup (nsswitch.c:229)
==3215==    by 0x493DB93: getservbyname_r@@GLIBC_2.4 (getXXbyYY_r.c:203)
==3215==    by 0x48FDBA3: gaih_inet_serv (getaddrinfo.c:164)
==3215==    by 0x48FE917: gaih_inet (getaddrinfo.c:332)
==3215==    by 0x490145F: getaddrinfo (getaddrinfo.c:2438)
==3215==  Address 0x4988e64 is 44 bytes inside a block of size 46 alloc'd
==3215==    at 0x4835978: malloc (vg_replace_malloc.c:263)
==3215==    by 0x400EE03: _dl_signal_error (dl-error.c:90)
==3215==    by 0x400903F: _dl_map_object (dl-load.c:2556)
==3215==    by 0x4013157: dl_open_worker (dl-open.c:226)
==3215==    by 0x400F0BF: _dl_catch_error (dl-error.c:178)
==3215==    by 0x4012C9B: _dl_open (dl-open.c:633)
==3215==    by 0x495982F: do_dlopen (dl-libc.c:86)
==3215==    by 0x400F0BF: _dl_catch_error (dl-error.c:178)
==3215==    by 0x4959917: dlerror_run (dl-libc.c:47)
==3215==    by 0x495997F: __libc_dlopen_mode (dl-libc.c:160)
==3215==    by 0x4935447: __nss_lookup_function (nsswitch.c:434)
==3215==    by 0x493569B: __nss_lookup (nsswitch.c:229)
==3215== 
==3215== 
==3215== HEAP SUMMARY:
==3215==     in use at exit: 0 bytes in 0 blocks
==3215==   total heap usage: 67 allocs, 67 frees, 6,461 bytes allocated
==3215== 
==3215== All heap blocks were freed -- no leaks are possible
==3215== 
==3215== For counts of detected and suppressed errors, rerun with: -v
==3215== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 25 from 11)

Can someone please help me understand why this error occurs? Or how to correct it? In my searches I am only finding errors related to the gethostbyaddr().

It looks like the invalid read error is coming from getaddrinfo(), but I'm unable to locate the file getaddrinfo.c on my system to try and correct it.

Deanie
  • 2,316
  • 2
  • 19
  • 35

2 Answers2

1

This looks like a problem similar to one discussed here: http://git.661346.n2.nabble.com/PATCH-valgrind-ignore-SSE-based-strlen-invalid-reads-td6175816.html

An optimized strlen() often reads full words when searching for the null terminator char. This can be done by an implementation in a safe way, even if it technically violates an allocation boundary.

It might be that you need a newer version of valgrind (3.9.0 is current) or valgrind needs to be configured or patched for the runtime you're using. You might want to configure a suppression for this: http://valgrind.org/docs/manual/manual-core.html#manual-core.suppress

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • Can I assume that this is a problem that will never affect my programs? I mean if I configure a suppression for this? – Deanie Aug 11 '14 at 02:05
  • You might see a similar error that is actually your error if you pass a string that hasn't been properly null-terminated to `strlen()`. So I think configuring a suppression is something that might need to be done carefully - I didn't really think it all the way through when I made the suggestion so casually. I'm not knowledgeable enough with valgrind to be able to say how to do it properly (or even if it's possible). – Michael Burr Aug 11 '14 at 05:24
  • Creating the suppression rules for valgrind is pretty simple, just include the option '--gen-suppressions=all' which will automatically generate suppression rules for all errors found. – Deanie Aug 11 '14 at 14:39
  • @Deanie: I think what might be tricky is making sure that a suppression for this doesn't prevent valgrind detecting a situation where an actual non-terminated string is passed to `strlen()`. If it can't be handled by suppression configuration, then at least the possibility of this situation should be understood when enabling the suppression. – Michael Burr Aug 11 '14 at 16:07
  • I see what your concern is. But from the documentation, it looks like the suppressions offered from valgrind with the option '--gen-suppressions=all' only suppresses if all the conditions are met (when 'strlen' is called by '_dl_open' which is called by ... which is first called by 'getaddrinfo'. So I should be safe regarding other calls to 'strlen'. – Deanie Aug 11 '14 at 16:35
0

Looks like an issue with GNU libc. Looking at the valgrind output, I guess you're using a rather old version of GNU libc?

The filenames and line numbers shown in the Valgrind output do not (always) correspond to real files on the filesystem. Valgrind takes the filenames and line numbers from the debug information sections put into the executable binaries by the compiler.

jotik
  • 17,044
  • 13
  • 58
  • 123
  • 'ldd (Debian EGLIBC 2.13-38+rpi2+deb7u3) 2.13' - Would the fact that I'm using EGLIBC instead of GLIBC be the issue? – Deanie Aug 09 '14 at 20:02
  • Hmm... That's not that old. I now realize that I made the mistake of thinking your GLIBC is version 2.4 because of the `@@GLIBC_2.4` in the symbol name. – jotik Aug 10 '14 at 20:14