Make sure the number of symbols reported and the first global fit the data.
Signed-off-by: Mark Wielaard <m...@redhat.com> --- libdwfl/ChangeLog | 5 +++++ libdwfl/dwfl_module_getdwarf.c | 25 +++++++++++++++++++------ src/ChangeLog | 5 +++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 22bc783..460f4e5 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,8 @@ +2014-11-18 Mark Wielaard <m...@redhat.com> + + * dwfl_module_getdwarf.c (find_symtab): Sanity check the data buffer, + number of symbols and first_global before use. + 2014-11-14 Mark Wielaard <m...@redhat.com> * dwfl_module_getdwarf.c (load_symtab): Don't use tables which have diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c index a20875b..c2e9e59 100644 --- a/libdwfl/dwfl_module_getdwarf.c +++ b/libdwfl/dwfl_module_getdwarf.c @@ -1083,7 +1083,7 @@ find_symtab (Dwfl_Module *mod) mod->symstrdata = elf_getdata (elf_getscn (mod->symfile->elf, strshndx), NULL); - if (mod->symstrdata == NULL) + if (mod->symstrdata == NULL || mod->symstrdata->d_buf == NULL) goto elferr; if (xndxscn == NULL) @@ -1091,12 +1091,18 @@ find_symtab (Dwfl_Module *mod) else { mod->symxndxdata = elf_getdata (xndxscn, NULL); - if (mod->symxndxdata == NULL) + if (mod->symxndxdata == NULL || mod->symxndxdata->d_buf == NULL) goto elferr; } mod->symdata = elf_getdata (symscn, NULL); - if (mod->symdata == NULL) + if (mod->symdata == NULL || mod->symdata->d_buf == NULL) + goto elferr; + + // Sanity check number of symbols. + GElf_Shdr shdr_mem, *shdr = gelf_getshdr (symscn, &shdr_mem); + if (mod->syments > mod->symdata->d_size / shdr->sh_entsize + || (size_t) mod->first_global > mod->syments) goto elferr; /* Cache any auxiliary symbol info, when it fails, just ignore aux_sym. */ @@ -1116,7 +1122,7 @@ find_symtab (Dwfl_Module *mod) mod->aux_symstrdata = elf_getdata (elf_getscn (mod->aux_sym.elf, aux_strshndx), NULL); - if (mod->aux_symstrdata == NULL) + if (mod->aux_symstrdata == NULL || mod->aux_symstrdata->d_buf == NULL) goto aux_cleanup; if (aux_xndxscn == NULL) @@ -1124,12 +1130,19 @@ find_symtab (Dwfl_Module *mod) else { mod->aux_symxndxdata = elf_getdata (aux_xndxscn, NULL); - if (mod->aux_symxndxdata == NULL) + if (mod->aux_symxndxdata == NULL + || mod->aux_symxndxdata->d_buf == NULL) goto aux_cleanup; } mod->aux_symdata = elf_getdata (aux_symscn, NULL); - if (mod->aux_symdata == NULL) + if (mod->aux_symdata == NULL || mod->aux_symdata->d_buf == NULL) + goto aux_cleanup; + + // Sanity check number of aux symbols. + shdr = gelf_getshdr (aux_symscn, &shdr_mem); + if (mod->aux_syments > mod->aux_symdata->d_size / shdr->sh_entsize + || (size_t) mod->aux_first_global > mod->aux_syments) goto aux_cleanup; } } diff --git a/src/ChangeLog b/src/ChangeLog index 2ab1594..bab948a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2014-11-18 Mark Wielaard <m...@redhat.com> + + * readelf.c (print_cfa_program): Fix sanity check of DW_FORM_block + length. + 2014-11-17 Mark Wielaard <m...@redhat.com> * readelf.c (handle_verneed): Check vna_next and vn_next exist. -- 1.8.3.1