diff options
| author | Mark Wielaard <[email protected]> | 2014-12-19 00:06:26 +0100 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2014-12-19 00:06:26 +0100 |
| commit | bd0434b61e0317718eb159fe7b5dc9ea870a0b79 (patch) | |
| tree | 825a373c2233a59b5156b219013e32f8f241aacc /libelf/elf_getphdrnum.c | |
| parent | e18bf66ce8070f96195880e83a50c9d98006b832 (diff) | |
| parent | 898ed261444cdd817c2d9b3656209a291eb5e807 (diff) | |
Merge branch 'master' into portable
Diffstat (limited to 'libelf/elf_getphdrnum.c')
| -rw-r--r-- | libelf/elf_getphdrnum.c | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/libelf/elf_getphdrnum.c b/libelf/elf_getphdrnum.c index 99649bee..63c27fb1 100644 --- a/libelf/elf_getphdrnum.c +++ b/libelf/elf_getphdrnum.c @@ -1,5 +1,5 @@ /* Return number of program headers in the ELF file. - Copyright (C) 2010 Red Hat, Inc. + Copyright (C) 2010, 2014 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -62,10 +62,18 @@ __elf_getphdrnum_rdlock (elf, dst) /* If there are no section headers, perhaps this is really just 65536 written without PN_XNUM support. Either that or it's bad data. */ - if (likely (scns->cnt > 0)) - *dst = (elf->class == ELFCLASS32 - ? scns->data[0].shdr.e32->sh_info - : scns->data[0].shdr.e64->sh_info); + if (elf->class == ELFCLASS32) + { + if (likely (scns->cnt > 0 + && elf->state.elf32.scns.data[0].shdr.e32 != NULL)) + *dst = scns->data[0].shdr.e32->sh_info; + } + else + { + if (likely (scns->cnt > 0 + && elf->state.elf64.scns.data[0].shdr.e64 != NULL)) + *dst = scns->data[0].shdr.e64->sh_info; + } } return 0; @@ -89,6 +97,39 @@ elf_getphdrnum (elf, dst) rwlock_rdlock (elf->lock); result = __elf_getphdrnum_rdlock (elf, dst); + + /* Do some sanity checking to make sure phnum and phoff are consistent. */ + Elf64_Off off = (elf->class == ELFCLASS32 + ? elf->state.elf32.ehdr->e_phoff + : elf->state.elf64.ehdr->e_phoff); + if (unlikely (off == 0)) + { + *dst = 0; + goto out; + } + + if (unlikely (off >= elf->maximum_size)) + { + __libelf_seterrno (ELF_E_INVALID_DATA); + result = -1; + goto out; + } + + /* Check for too many sections. */ + size_t phdr_size = (elf->class == ELFCLASS32 + ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr)); + if (unlikely (*dst > SIZE_MAX / phdr_size)) + { + __libelf_seterrno (ELF_E_INVALID_DATA); + result = -1; + goto out; + } + + /* Truncated file? Don't return more than can be indexed. */ + if (unlikely (elf->maximum_size - off < *dst * phdr_size)) + *dst = (elf->maximum_size - off) / phdr_size; + +out: rwlock_unlock (elf->lock); return result; |
