readelf.c display_lto_symtab offset outside bounds of constant string

Using gcc-10 or current mainline gcc, binutils configured with
--disable-nls results in:

readelf.c: In function 'display_lto_symtab':
readelf.c:12283:26: error: offset '17' outside bounds of constant string [-Werror=array-bounds]
12283 |   SECTION_NAME (section) + strlen (".gnu.lto_.symtab.")) > 0
      |                          ^

Which is actually a bogus warning in this case because we've already
checked the name string for validity, so SECTION_NAME won't ever be
"<none>", "<no-strings>" or "<corrupt>".  This patch fixes the problem
by making SECTION_NAME simply return the string from the string table.
Other places also shouldn't be trying to match any of the error
strings against a section name, so fix them too.

	* readelf.c: Delete whitespace at end of line throughout.
	(SECTION_NAME, SECTION_NAME_VALID): New.
	(SECTION_NAME_PRINT): Rename from SECTION_NAME.  Formatting.
	(printable_section_name, dump_relocations): Use SECTION_NAME_PRINT.
	(process_section_headers, process_section_groups): Likewise.
	(shdr_to_ctf_sect): Likewise.
	(find_section, find_section_in_set): Use SECTION_NAME_VALID.
	(ia64_process_unwind, hppa_process_unwind): Likewise.
	(display_debug_section, initialise_dumps_byname): Likewise.
	(process_lto_symbol_tables): Likewise.  Check trailing period of
	lto symbol table names.
	(display_lto_symtab): Use sizeof instead of strlen.
This commit is contained in:
Alan Modra
2020-10-20 14:59:40 +10:30
parent ce786647f0
commit b9e920ecd6
2 changed files with 77 additions and 37 deletions

View File

@ -1,3 +1,18 @@
2020-10-20 Alan Modra <amodra@gmail.com>
* readelf.c: Delete whitespace at end of line throughout.
(SECTION_NAME, SECTION_NAME_VALID): New.
(SECTION_NAME_PRINT): Rename from SECTION_NAME. Formatting.
(printable_section_name, dump_relocations): Use SECTION_NAME_PRINT.
(process_section_headers, process_section_groups): Likewise.
(shdr_to_ctf_sect): Likewise.
(find_section, find_section_in_set): Use SECTION_NAME_VALID.
(ia64_process_unwind, hppa_process_unwind): Likewise.
(display_debug_section, initialise_dumps_byname): Likewise.
(process_lto_symbol_tables): Likewise. Check trailing period of
lto symbol table names.
(display_lto_symtab): Use sizeof instead of strlen.
2020-10-20 Nelson Chu <nelson.chu@sifive.com> 2020-10-20 Nelson Chu <nelson.chu@sifive.com>
* MAINTAINERS (RISC-V): Add myself as RISC-V co-maintainer. * MAINTAINERS (RISC-V): Add myself as RISC-V co-maintainer.

View File

@ -336,10 +336,18 @@ static const char * get_symbol_version_string
#define UNKNOWN -1 #define UNKNOWN -1
#define SECTION_NAME(X) \ #define SECTION_NAME(X) \
(filedata->string_table + (X)->sh_name)
#define SECTION_NAME_VALID(X) \
((X) != NULL \
&& filedata->string_table != NULL \
&& (X)->sh_name < filedata->string_table_length)
#define SECTION_NAME_PRINT(X) \
((X) == NULL ? _("<none>") \ ((X) == NULL ? _("<none>") \
: filedata->string_table == NULL ? _("<no-strings>") \ : filedata->string_table == NULL ? _("<no-strings>") \
: ((X)->sh_name >= filedata->string_table_length ? _("<corrupt>") \ : (X)->sh_name >= filedata->string_table_length ? _("<corrupt>") \
: filedata->string_table + (X)->sh_name)) : filedata->string_table + (X)->sh_name)
#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
@ -669,7 +677,7 @@ printable_section_name (Filedata * filedata, const Elf_Internal_Shdr * sec)
{ {
#define MAX_PRINT_SEC_NAME_LEN 128 #define MAX_PRINT_SEC_NAME_LEN 128
static char sec_name_buf [MAX_PRINT_SEC_NAME_LEN + 1]; static char sec_name_buf [MAX_PRINT_SEC_NAME_LEN + 1];
const char * name = SECTION_NAME (sec); const char * name = SECTION_NAME_PRINT (sec);
char * buf = sec_name_buf; char * buf = sec_name_buf;
char c; char c;
unsigned int remaining = MAX_PRINT_SEC_NAME_LEN; unsigned int remaining = MAX_PRINT_SEC_NAME_LEN;
@ -731,7 +739,8 @@ find_section (Filedata * filedata, const char * name)
return NULL; return NULL;
for (i = 0; i < filedata->file_header.e_shnum; i++) for (i = 0; i < filedata->file_header.e_shnum; i++)
if (streq (SECTION_NAME (filedata->section_headers + i), name)) if (SECTION_NAME_VALID (filedata->section_headers + i)
&& streq (SECTION_NAME (filedata->section_headers + i), name))
return filedata->section_headers + i; return filedata->section_headers + i;
return NULL; return NULL;
@ -797,7 +806,8 @@ find_section_in_set (Filedata * filedata, const char * name, unsigned int * set)
if (i >= filedata->file_header.e_shnum) if (i >= filedata->file_header.e_shnum)
continue; /* FIXME: Should we issue an error message ? */ continue; /* FIXME: Should we issue an error message ? */
if (streq (SECTION_NAME (filedata->section_headers + i), name)) if (SECTION_NAME_VALID (filedata->section_headers + i)
&& streq (SECTION_NAME (filedata->section_headers + i), name))
return filedata->section_headers + i; return filedata->section_headers + i;
} }
} }
@ -1729,7 +1739,8 @@ dump_relocations (Filedata * filedata,
if (ELF_ST_TYPE (psym->st_info) == STT_SECTION) if (ELF_ST_TYPE (psym->st_info) == STT_SECTION)
{ {
if (psym->st_shndx < filedata->file_header.e_shnum) if (psym->st_shndx < filedata->file_header.e_shnum)
sec_name = SECTION_NAME (filedata->section_headers + psym->st_shndx); sec_name = SECTION_NAME_PRINT (filedata->section_headers
+ psym->st_shndx);
else if (psym->st_shndx == SHN_ABS) else if (psym->st_shndx == SHN_ABS)
sec_name = "ABS"; sec_name = "ABS";
else if (psym->st_shndx == SHN_COMMON) else if (psym->st_shndx == SHN_COMMON)
@ -6394,7 +6405,7 @@ process_section_headers (Filedata * filedata)
i < filedata->file_header.e_shnum; i < filedata->file_header.e_shnum;
i++, section++) i++, section++)
{ {
char * name = SECTION_NAME (section); char * name = SECTION_NAME_PRINT (section);
/* Run some sanity checks on the headers and /* Run some sanity checks on the headers and
possibly fill in some file data as well. */ possibly fill in some file data as well. */
@ -6730,7 +6741,7 @@ process_section_headers (Filedata * filedata)
if (do_section_details) if (do_section_details)
printf ("%s\n ", printable_section_name (filedata, section)); printf ("%s\n ", printable_section_name (filedata, section));
else else
print_symbol (-17, SECTION_NAME (section)); print_symbol (-17, SECTION_NAME_PRINT (section));
printf (do_wide ? " %-15s " : " %-15.15s ", printf (do_wide ? " %-15s " : " %-15.15s ",
get_section_type_name (filedata, section->sh_type)); get_section_type_name (filedata, section->sh_type));
@ -7127,7 +7138,8 @@ process_section_groups (Filedata * filedata)
continue; continue;
} }
group_name = SECTION_NAME (filedata->section_headers + sym->st_shndx); group_name = SECTION_NAME_PRINT (filedata->section_headers
+ sym->st_shndx);
strtab_sec = NULL; strtab_sec = NULL;
free (strtab); free (strtab);
strtab = NULL; strtab = NULL;
@ -8055,7 +8067,8 @@ ia64_process_unwind (Filedata * filedata)
{ {
sec = filedata->section_headers + g->section_index; sec = filedata->section_headers + g->section_index;
if (streq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info)) if (SECTION_NAME_VALID (sec)
&& streq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info))
break; break;
} }
@ -8063,14 +8076,19 @@ ia64_process_unwind (Filedata * filedata)
i = filedata->file_header.e_shnum; i = filedata->file_header.e_shnum;
} }
} }
else if (strneq (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind_once, len)) else if (SECTION_NAME_VALID (unwsec)
&& strneq (SECTION_NAME (unwsec),
ELF_STRING_ia64_unwind_once, len))
{ {
/* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.ia64unwi.FOO. */ /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.ia64unwi.FOO. */
len2 = sizeof (ELF_STRING_ia64_unwind_info_once) - 1; len2 = sizeof (ELF_STRING_ia64_unwind_info_once) - 1;
suffix = SECTION_NAME (unwsec) + len; suffix = SECTION_NAME (unwsec) + len;
for (i = 0, sec = filedata->section_headers; i < filedata->file_header.e_shnum; for (i = 0, sec = filedata->section_headers;
i < filedata->file_header.e_shnum;
++i, ++sec) ++i, ++sec)
if (strneq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info_once, len2) if (SECTION_NAME_VALID (sec)
&& strneq (SECTION_NAME (sec),
ELF_STRING_ia64_unwind_info_once, len2)
&& streq (SECTION_NAME (sec) + len2, suffix)) && streq (SECTION_NAME (sec) + len2, suffix))
break; break;
} }
@ -8081,11 +8099,14 @@ ia64_process_unwind (Filedata * filedata)
len = sizeof (ELF_STRING_ia64_unwind) - 1; len = sizeof (ELF_STRING_ia64_unwind) - 1;
len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1; len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
suffix = ""; suffix = "";
if (strneq (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind, len)) if (SECTION_NAME_VALID (unwsec)
&& strneq (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind, len))
suffix = SECTION_NAME (unwsec) + len; suffix = SECTION_NAME (unwsec) + len;
for (i = 0, sec = filedata->section_headers; i < filedata->file_header.e_shnum; for (i = 0, sec = filedata->section_headers;
i < filedata->file_header.e_shnum;
++i, ++sec) ++i, ++sec)
if (strneq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info, len2) if (SECTION_NAME_VALID (sec)
&& strneq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info, len2)
&& streq (SECTION_NAME (sec) + len2, suffix)) && streq (SECTION_NAME (sec) + len2, suffix))
break; break;
} }
@ -8468,7 +8489,8 @@ hppa_process_unwind (Filedata * filedata)
&aux.strtab, &aux.strtab_size)) &aux.strtab, &aux.strtab_size))
return FALSE; return FALSE;
} }
else if (streq (SECTION_NAME (sec), ".PARISC.unwind")) else if (SECTION_NAME_VALID (sec)
&& streq (SECTION_NAME (sec), ".PARISC.unwind"))
unwsec = sec; unwsec = sec;
} }
@ -8477,7 +8499,8 @@ hppa_process_unwind (Filedata * filedata)
for (i = 0, sec = filedata->section_headers; i < filedata->file_header.e_shnum; ++i, ++sec) for (i = 0, sec = filedata->section_headers; i < filedata->file_header.e_shnum; ++i, ++sec)
{ {
if (streq (SECTION_NAME (sec), ".PARISC.unwind")) if (SECTION_NAME_VALID (sec)
&& streq (SECTION_NAME (sec), ".PARISC.unwind"))
{ {
unsigned long num_unwind = sec->sh_size / 16; unsigned long num_unwind = sec->sh_size / 16;
@ -12280,7 +12303,7 @@ display_lto_symtab (Filedata * filedata,
char * ext_name = NULL; char * ext_name = NULL;
if (asprintf (& ext_name, ".gnu.lto_.ext_symtab.%s", if (asprintf (& ext_name, ".gnu.lto_.ext_symtab.%s",
SECTION_NAME (section) + strlen (".gnu.lto_.symtab.")) > 0 SECTION_NAME (section) + sizeof (".gnu.lto_.symtab.") - 1) > 0
&& ext_name != NULL /* Paranoia. */ && ext_name != NULL /* Paranoia. */
&& (ext = find_section (filedata, ext_name)) != NULL) && (ext = find_section (filedata, ext_name)) != NULL)
{ {
@ -12429,7 +12452,8 @@ process_lto_symbol_tables (Filedata * filedata)
for (i = 0, section = filedata->section_headers; for (i = 0, section = filedata->section_headers;
i < filedata->file_header.e_shnum; i < filedata->file_header.e_shnum;
i++, section++) i++, section++)
if (CONST_STRNEQ (SECTION_NAME (section), ".gnu.lto_.symtab")) if (SECTION_NAME_VALID (section)
&& CONST_STRNEQ (SECTION_NAME (section), ".gnu.lto_.symtab."))
res &= display_lto_symtab (filedata, section); res &= display_lto_symtab (filedata, section);
return res; return res;
@ -14508,7 +14532,7 @@ dump_section_as_bytes (Elf_Internal_Shdr * section,
static ctf_sect_t * static ctf_sect_t *
shdr_to_ctf_sect (ctf_sect_t *buf, Elf_Internal_Shdr *shdr, Filedata *filedata) shdr_to_ctf_sect (ctf_sect_t *buf, Elf_Internal_Shdr *shdr, Filedata *filedata)
{ {
buf->cts_name = SECTION_NAME (shdr); buf->cts_name = SECTION_NAME_PRINT (shdr);
buf->cts_size = shdr->sh_size; buf->cts_size = shdr->sh_size;
buf->cts_entsize = shdr->sh_entsize; buf->cts_entsize = shdr->sh_entsize;
@ -15071,7 +15095,7 @@ free_debug_section (enum dwarf_section_display_enum debug)
static bfd_boolean static bfd_boolean
display_debug_section (int shndx, Elf_Internal_Shdr * section, Filedata * filedata) display_debug_section (int shndx, Elf_Internal_Shdr * section, Filedata * filedata)
{ {
char * name = SECTION_NAME (section); char * name = SECTION_NAME_VALID (section) ? SECTION_NAME (section) : "";
const char * print_name = printable_section_name (filedata, section); const char * print_name = printable_section_name (filedata, section);
bfd_size_type length; bfd_size_type length;
bfd_boolean result = TRUE; bfd_boolean result = TRUE;
@ -15160,7 +15184,8 @@ initialise_dumps_byname (Filedata * filedata)
bfd_boolean any = FALSE; bfd_boolean any = FALSE;
for (i = 0; i < filedata->file_header.e_shnum; i++) for (i = 0; i < filedata->file_header.e_shnum; i++)
if (streq (SECTION_NAME (filedata->section_headers + i), cur->name)) if (SECTION_NAME_VALID (filedata->section_headers + i)
&& streq (SECTION_NAME (filedata->section_headers + i), cur->name))
{ {
request_dump_bynumber (&filedata->dump, i, cur->type); request_dump_bynumber (&filedata->dump, i, cur->type);
any = TRUE; any = TRUE;