Avoid ubsan bug complaining about &p->field

I reckon it's quite OK to write &p->field in C when p might be NULL,
and lots of old C programmers probably agree with me.  However, ubsan
disagrees and so do some people I respect.  I suspect C++ influence is
to blame for the ubsan behaviour.  See
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92634.  So far no one has
educated me as to why I'm wrong to claim that there isn't anything in
the C standard to say that p->field is always (*p).field.  Note 79
doesn't quite do that because it doesn't cover null pointers.  If
there was such an equivalence then you could claim &p->field has a
null pointer reference when p is NULL, even though no C compiler would
ever dereference p.

Anyway, to silence ubsan I'm going to apply the following though I
prefer to avoid casts when possible.  And I'm using (void *)
deliberately because this is C, not C++!

	* ldlang.c (lang_output_section_find_by_flags): Don't use &p->field
	when p might be NULL.
	* ldelf.c (output_rel_find, ldelf_place_orphan): Likewise.
	(insert_os_after, lang_insert_orphan, lookup_name): Likewise.
	(strip_excluded_output_sections, lang_clear_os_map): Likewise.
	(lang_check, lang_for_each_input_file): Likewise.
	(lang_reset_memory_regions, find_replacements_insert_point): Likewise.
	(find_rescan_insertion, lang_propagate_lma_regions): Likewise.
	(lang_record_phdrs): Likewise.
	* emultempl/alphaelf.em (alpha_after_open): Likewise.
	* emultempl/mmo.em (mmo_place_orphan): Likewise.
	* emultempl/pe.em (gld_${EMULATION_NAME}_place_orphan): Likewise.
	* emultempl/pep.em (gld_${EMULATION_NAME}_place_orphan): Likewise.
	* emultempl/ppc32elf.em (ppc_after_check_relocs): Likewise.
	* emultempl/spuelf.em (spu_before_allocation): Likewise.
	(embedded_spu_file): Likewise.
This commit is contained in:
Alan Modra 2019-11-26 16:49:44 +10:30
parent 100b122fc1
commit 8ce18f9cdf
9 changed files with 44 additions and 25 deletions

View File

@ -1,3 +1,22 @@
2019-12-26 Alan Modra <amodra@gmail.com>
* ldlang.c (lang_output_section_find_by_flags): Don't use &p->field
when p might be NULL.
* ldelf.c (output_rel_find, ldelf_place_orphan): Likewise.
(insert_os_after, lang_insert_orphan, lookup_name): Likewise.
(strip_excluded_output_sections, lang_clear_os_map): Likewise.
(lang_check, lang_for_each_input_file): Likewise.
(lang_reset_memory_regions, find_replacements_insert_point): Likewise.
(find_rescan_insertion, lang_propagate_lma_regions): Likewise.
(lang_record_phdrs): Likewise.
* emultempl/alphaelf.em (alpha_after_open): Likewise.
* emultempl/mmo.em (mmo_place_orphan): Likewise.
* emultempl/pe.em (gld_${EMULATION_NAME}_place_orphan): Likewise.
* emultempl/pep.em (gld_${EMULATION_NAME}_place_orphan): Likewise.
* emultempl/ppc32elf.em (ppc_after_check_relocs): Likewise.
* emultempl/spuelf.em (spu_before_allocation): Likewise.
(embedded_spu_file): Likewise.
2019-12-19 Alan Modra <amodra@gmail.com> 2019-12-19 Alan Modra <amodra@gmail.com>
* testsuite/lib/ld-lib.exp (uses_genelf): Remove moxie. * testsuite/lib/ld-lib.exp (uses_genelf): Remove moxie.

View File

@ -47,7 +47,7 @@ alpha_after_open (void)
lang_output_section_statement_type *plt_os[2]; lang_output_section_statement_type *plt_os[2];
num_plt = 0; num_plt = 0;
for (os = &lang_os_list.head->output_section_statement; for (os = (void *) lang_os_list.head;
os != NULL; os != NULL;
os = os->next) os = os->next)
{ {

View File

@ -163,7 +163,7 @@ mmo_place_orphan (asection *s,
/* We have to find the oss before this one, so we can use that as /* We have to find the oss before this one, so we can use that as
"after". */ "after". */
for (lookup = &lang_os_list.head->output_section_statement; for (lookup = (void *) lang_os_list.head;
lookup != NULL && lookup->next != before; lookup != NULL && lookup->next != before;
lookup = lookup->next) lookup = lookup->next)
; ;

View File

@ -2151,7 +2151,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
NULL); NULL);
if (after == NULL) if (after == NULL)
/* *ABS* is always the first output section statement. */ /* *ABS* is always the first output section statement. */
after = &lang_os_list.head->output_section_statement; after = (void *) lang_os_list.head;
} }
/* All sections in an executable must be aligned to a page boundary. /* All sections in an executable must be aligned to a page boundary.

View File

@ -1950,7 +1950,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
NULL); NULL);
if (after == NULL) if (after == NULL)
/* *ABS* is always the first output section statement. */ /* *ABS* is always the first output section statement. */
after = &lang_os_list.head->output_section_statement; after = (void *) lang_os_list.head;
} }
/* All sections in an executable must be aligned to a page boundary. /* All sections in an executable must be aligned to a page boundary.

View File

@ -79,7 +79,7 @@ ppc_after_check_relocs (void)
num_got = 0; num_got = 0;
num_plt = 0; num_plt = 0;
for (os = &lang_os_list.head->output_section_statement; for (os = (void *) lang_os_list.head;
os != NULL; os != NULL;
os = os->next) os = os->next)
{ {

View File

@ -290,7 +290,7 @@ spu_before_allocation (void)
} }
/* Ensure alignment of overlay sections is sufficient. */ /* Ensure alignment of overlay sections is sufficient. */
for (os = &lang_os_list.head->output_section_statement; for (os = (void *) lang_os_list.head;
os != NULL; os != NULL;
os = os->next) os = os->next)
if (os->bfd_section != NULL if (os->bfd_section != NULL
@ -512,7 +512,7 @@ embedded_spu_file (lang_input_statement_type *entry, const char *flags)
return FALSE; return FALSE;
close (fd); close (fd);
for (search = &input_file_chain.head->input_statement; for (search = (void *) input_file_chain.head;
search != NULL; search != NULL;
search = search->next_real_file) search = search->next_real_file)
if (search->filename != NULL) if (search->filename != NULL)

View File

@ -1780,7 +1780,7 @@ output_rel_find (int isdyn, int rela)
lang_output_section_statement_type *last_rel = NULL; lang_output_section_statement_type *last_rel = NULL;
lang_output_section_statement_type *last_rel_alloc = NULL; lang_output_section_statement_type *last_rel_alloc = NULL;
for (lookup = &lang_os_list.head->output_section_statement; for (lookup = (void *) lang_os_list.head;
lookup != NULL; lookup != NULL;
lookup = lookup->next) lookup = lookup->next)
{ {
@ -1952,7 +1952,7 @@ ldelf_place_orphan (asection *s, const char *secname, int constraint)
{ {
/* Find the output mbind section with the same type, attributes /* Find the output mbind section with the same type, attributes
and sh_info field. */ and sh_info field. */
for (os = &lang_os_list.head->output_section_statement; for (os = (void *) lang_os_list.head;
os != NULL; os != NULL;
os = os->next) os = os->next)
if (os->bfd_section != NULL if (os->bfd_section != NULL
@ -2129,7 +2129,7 @@ ldelf_place_orphan (asection *s, const char *secname, int constraint)
_bfd_elf_match_sections_by_type); _bfd_elf_match_sections_by_type);
if (after == NULL) if (after == NULL)
/* *ABS* is always the first output section statement. */ /* *ABS* is always the first output section statement. */
after = &lang_os_list.head->output_section_statement; after = (void *) lang_os_list.head;
} }
return lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL); return lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL);

View File

@ -1552,7 +1552,7 @@ lang_output_section_find_by_flags (const asection *sec,
/* We know the first statement on this list is *ABS*. May as well /* We know the first statement on this list is *ABS*. May as well
skip it. */ skip it. */
first = &lang_os_list.head->output_section_statement; first = (void *) lang_os_list.head;
first = first->next; first = first->next;
/* First try for an exact match. */ /* First try for an exact match. */
@ -1780,7 +1780,7 @@ insert_os_after (lang_output_section_statement_type *after)
lang_statement_union_type **assign = NULL; lang_statement_union_type **assign = NULL;
bfd_boolean ignore_first; bfd_boolean ignore_first;
ignore_first = after == &lang_os_list.head->output_section_statement; ignore_first = after == (void *) lang_os_list.head;
for (where = &after->header.next; for (where = &after->header.next;
*where != NULL; *where != NULL;
@ -1904,7 +1904,7 @@ lang_insert_orphan (asection *s,
/* Shuffle the bfd section list to make the output file look /* Shuffle the bfd section list to make the output file look
neater. This is really only cosmetic. */ neater. This is really only cosmetic. */
if (place->section == NULL if (place->section == NULL
&& after != &lang_os_list.head->output_section_statement) && after != (void *) lang_os_list.head)
{ {
asection *bfd_section = after->bfd_section; asection *bfd_section = after->bfd_section;
@ -2846,7 +2846,7 @@ lookup_name (const char *name)
{ {
lang_input_statement_type *search; lang_input_statement_type *search;
for (search = &input_file_chain.head->input_statement; for (search = (void *) input_file_chain.head;
search != NULL; search != NULL;
search = search->next_real_file) search = search->next_real_file)
{ {
@ -4329,7 +4329,7 @@ strip_excluded_output_sections (void)
lang_reset_memory_regions (); lang_reset_memory_regions ();
} }
for (os = &lang_os_list.head->output_section_statement; for (os = (void *) lang_os_list.head;
os != NULL; os != NULL;
os = os->next) os = os->next)
{ {
@ -4390,7 +4390,7 @@ lang_clear_os_map (void)
if (map_head_is_link_order) if (map_head_is_link_order)
return; return;
for (os = &lang_os_list.head->output_section_statement; for (os = (void *) lang_os_list.head;
os != NULL; os != NULL;
os = os->next) os = os->next)
{ {
@ -6728,7 +6728,7 @@ lang_check (void)
bfd *input_bfd; bfd *input_bfd;
const bfd_arch_info_type *compatible; const bfd_arch_info_type *compatible;
for (file = &file_chain.head->input_statement; for (file = (void *) file_chain.head;
file != NULL; file != NULL;
file = file->next) file = file->next)
{ {
@ -7070,7 +7070,7 @@ lang_for_each_input_file (void (*func) (lang_input_statement_type *))
{ {
lang_input_statement_type *f; lang_input_statement_type *f;
for (f = &input_file_chain.head->input_statement; for (f = (void *) input_file_chain.head;
f != NULL; f != NULL;
f = f->next_real_file) f = f->next_real_file)
if (f->flags.real) if (f->flags.real)
@ -7196,7 +7196,7 @@ lang_reset_memory_regions (void)
p->last_os = NULL; p->last_os = NULL;
} }
for (os = &lang_os_list.head->output_section_statement; for (os = (void *) lang_os_list.head;
os != NULL; os != NULL;
os = os->next) os = os->next)
{ {
@ -7433,8 +7433,8 @@ static lang_input_statement_type *
find_replacements_insert_point (bfd_boolean *before) find_replacements_insert_point (bfd_boolean *before)
{ {
lang_input_statement_type *claim1, *lastobject; lang_input_statement_type *claim1, *lastobject;
lastobject = &input_file_chain.head->input_statement; lastobject = (void *) input_file_chain.head;
for (claim1 = &file_chain.head->input_statement; for (claim1 = (void *) file_chain.head;
claim1 != NULL; claim1 != NULL;
claim1 = claim1->next) claim1 = claim1->next)
{ {
@ -7476,7 +7476,7 @@ find_rescan_insertion (lang_input_statement_type *add)
file chain if it is full of archive elements. Archives don't file chain if it is full of archive elements. Archives don't
appear on the file chain, but if an element has been extracted appear on the file chain, but if an element has been extracted
then their input_statement->next points at it. */ then their input_statement->next points at it. */
for (f = &input_file_chain.head->input_statement; for (f = (void *) input_file_chain.head;
f != NULL; f != NULL;
f = f->next_real_file) f = f->next_real_file)
{ {
@ -7609,7 +7609,7 @@ lang_propagate_lma_regions (void)
{ {
lang_output_section_statement_type *os; lang_output_section_statement_type *os;
for (os = &lang_os_list.head->output_section_statement; for (os = (void *) lang_os_list.head;
os != NULL; os != NULL;
os = os->next) os = os->next)
{ {
@ -8286,7 +8286,7 @@ lang_record_phdrs (void)
bfd_vma at; bfd_vma at;
c = 0; c = 0;
for (os = &lang_os_list.head->output_section_statement; for (os = (void *) lang_os_list.head;
os != NULL; os != NULL;
os = os->next) os = os->next)
{ {
@ -8372,7 +8372,7 @@ lang_record_phdrs (void)
free (secs); free (secs);
/* Make sure all the phdr assignments succeeded. */ /* Make sure all the phdr assignments succeeded. */
for (os = &lang_os_list.head->output_section_statement; for (os = (void *) lang_os_list.head;
os != NULL; os != NULL;
os = os->next) os = os->next)
{ {