diff options
author | njn <njn@a5019735-40e9-0310-863c-91ae7b9d1cf9> | 2009-06-30 06:06:14 +0000 |
---|---|---|
committer | njn <njn@a5019735-40e9-0310-863c-91ae7b9d1cf9> | 2009-06-30 06:06:14 +0000 |
commit | 58899e8e2af51859289d0badea881b7b72c3fb13 (patch) | |
tree | 006dade0827b7a07b4e10f70bf99b5e7423909e9 /coregrind | |
parent | 018916e835a3f21a278a16ac012b021778d1b070 (diff) | |
download | valgrind-58899e8e2af51859289d0badea881b7b72c3fb13.tar.gz |
Fix a problem with r10384: it was failing to read the ELF header if the
executable was less than 4096 bytes.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10387 a5019735-40e9-0310-863c-91ae7b9d1cf9
Diffstat (limited to 'coregrind')
-rw-r--r-- | coregrind/launcher-linux.c | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/coregrind/launcher-linux.c b/coregrind/launcher-linux.c index 34754d02a..7b89969ae 100644 --- a/coregrind/launcher-linux.c +++ b/coregrind/launcher-linux.c @@ -113,9 +113,8 @@ static const char *select_platform(const char *clientname) { int fd; uint8_t header[4096]; - ssize_t bytes; + ssize_t n_bytes; const char *platform = NULL; - long pagesize = sysconf(_SC_PAGESIZE); if (strchr(clientname, '/') == NULL) clientname = find_client(clientname); @@ -124,28 +123,38 @@ static const char *select_platform(const char *clientname) return NULL; // barf("open(%s): %s", clientname, strerror(errno)); - bytes = read(fd, header, sizeof(header)); + n_bytes = read(fd, header, sizeof(header)); close(fd); - if (bytes != sizeof(header)) { + if (n_bytes < 2) { return NULL; } if (header[0] == '#' && header[1] == '!') { + int i = 2; char *interp = (char *)header + 2; - char *interpend; - while (*interp == ' ' || *interp == '\t') - interp++; - - for (interpend = interp; !isspace(*interpend); interpend++) - ; + // Skip whitespace. + while (1) { + if (i == n_bytes) return NULL; + if (' ' != header[i] && '\t' == header[i]) break; + i++; + } - *interpend = '\0'; + // Get the interpreter name. + interp = &header[i]; + while (1) { + if (i == n_bytes) break; + if (isspace(header[i])) break; + i++; + } + if (i == n_bytes) return NULL; + header[i] = '\0'; platform = select_platform(interp); - } else if (memcmp(header, ELFMAG, SELFMAG) == 0) { - if (header[EI_CLASS] == ELFCLASS32) { + } else if (n_bytes >= SELFMAG && memcmp(header, ELFMAG, SELFMAG) == 0) { + + if (n_bytes >= sizeof(Elf32_Ehdr) && header[EI_CLASS] == ELFCLASS32) { const Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header; if (header[EI_DATA] == ELFDATA2LSB) { @@ -160,7 +169,7 @@ static const char *select_platform(const char *clientname) platform = "ppc32-linux"; } } - } else if (header[EI_CLASS] == ELFCLASS64) { + } else if (n_bytes >= sizeof(Elf64_Ehdr) && header[EI_CLASS] == ELFCLASS64) { const Elf64_Ehdr *ehdr = (Elf64_Ehdr *)header; if (header[EI_DATA] == ELFDATA2LSB) { @@ -177,8 +186,6 @@ static const char *select_platform(const char *clientname) } } - munmap(header, pagesize); - return platform; } @@ -266,7 +273,7 @@ int main(int argc, char** argv, char** envp) /* Figure out the name of this executable (viz, the launcher), so we can tell stage2. stage2 will use the name for recursive - invokations of valgrind on child processes. */ + invocations of valgrind on child processes. */ memset(launcher_name, 0, PATH_MAX+1); r = readlink("/proc/self/exe", launcher_name, PATH_MAX); if (r == -1) { @@ -306,7 +313,7 @@ int main(int argc, char** argv, char** envp) if (cp != NULL) valgrind_lib = cp; - /* Build the stage2 invokation, and execve it. Bye! */ + /* Build the stage2 invocation, and execve it. Bye! */ toolfile = malloc(strlen(valgrind_lib) + strlen(toolname) + strlen(platform) + 3); if (toolfile == NULL) barf("malloc of toolfile failed."); |