diff options
author | Alex Bennée <alex.bennee@linaro.org> | 2020-04-03 20:11:39 +0100 |
---|---|---|
committer | Alex Bennée <alex.bennee@linaro.org> | 2020-04-07 16:19:49 +0100 |
commit | 040425f849b959ed903610cc028e0996d921f9ca (patch) | |
tree | abcb701fda090377cdbec99860ff077e81e0596e /include | |
parent | 20a4f14f6e6f543100bfdd93705cbdebb549d250 (diff) |
elf-ops: bail out if we have no function symbols
It's perfectly possible to have no function symbols in your elf file
and if we do the undefined behaviour sanitizer rightly complains about
us passing NULL to qsort. Check nsyms before we go ahead.
While we are at it lets drop the unchecked return value and cleanup
the fail leg by use of g_autoptr.
Another fix was proposed 101 weeks ago in:
Message-Id: 20180421232120.22208-1-f4bug@amsat.org
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20200403191150.863-2-alex.bennee@linaro.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/hw/elf_ops.h | 48 |
1 files changed, 25 insertions, 23 deletions
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h index a1411bfcab..e0bb47bb67 100644 --- a/include/hw/elf_ops.h +++ b/include/hw/elf_ops.h @@ -104,19 +104,21 @@ static int glue(symcmp, SZ)(const void *s0, const void *s1) : ((sym0->st_value > sym1->st_value) ? 1 : 0); } -static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, - int clear_lsb, symbol_fn_t sym_cb) +static void glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, + int clear_lsb, symbol_fn_t sym_cb) { - struct elf_shdr *symtab, *strtab, *shdr_table = NULL; - struct elf_sym *syms = NULL; + struct elf_shdr *symtab, *strtab; + g_autofree struct elf_shdr *shdr_table = NULL; + g_autofree struct elf_sym *syms = NULL; + g_autofree char *str = NULL; struct syminfo *s; int nsyms, i; - char *str = NULL; shdr_table = load_at(fd, ehdr->e_shoff, sizeof(struct elf_shdr) * ehdr->e_shnum); - if (!shdr_table) - return -1; + if (!shdr_table) { + return ; + } if (must_swab) { for (i = 0; i < ehdr->e_shnum; i++) { @@ -125,23 +127,25 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, } symtab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_SYMTAB); - if (!symtab) - goto fail; + if (!symtab) { + return; + } syms = load_at(fd, symtab->sh_offset, symtab->sh_size); - if (!syms) - goto fail; + if (!syms) { + return; + } nsyms = symtab->sh_size / sizeof(struct elf_sym); /* String table */ if (symtab->sh_link >= ehdr->e_shnum) { - goto fail; + return; } strtab = &shdr_table[symtab->sh_link]; str = load_at(fd, strtab->sh_offset, strtab->sh_size); if (!str) { - goto fail; + return; } i = 0; @@ -170,8 +174,13 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, } i++; } - syms = g_realloc(syms, nsyms * sizeof(*syms)); + /* check we have symbols left */ + if (nsyms == 0) { + return; + } + + syms = g_realloc(syms, nsyms * sizeof(*syms)); qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ)); for (i = 0; i < nsyms - 1; i++) { if (syms[i].st_size == 0) { @@ -182,18 +191,11 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, /* Commit */ s = g_malloc0(sizeof(*s)); s->lookup_symbol = glue(lookup_symbol, SZ); - glue(s->disas_symtab.elf, SZ) = syms; + glue(s->disas_symtab.elf, SZ) = g_steal_pointer(&syms); s->disas_num_syms = nsyms; - s->disas_strtab = str; + s->disas_strtab = g_steal_pointer(&str); s->next = syminfos; syminfos = s; - g_free(shdr_table); - return 0; - fail: - g_free(syms); - g_free(str); - g_free(shdr_table); - return -1; } static int glue(elf_reloc, SZ)(struct elfhdr *ehdr, int fd, int must_swab, |