From 8ce18f9cdf53c846e0486130a66ba55c96fc2b14 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 26 Nov 2019 16:49:44 +1030 Subject: [PATCH] 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. --- ld/ChangeLog | 19 +++++++++++++++++++ ld/emultempl/alphaelf.em | 2 +- ld/emultempl/mmo.em | 2 +- ld/emultempl/pe.em | 2 +- ld/emultempl/pep.em | 2 +- ld/emultempl/ppc32elf.em | 2 +- ld/emultempl/spuelf.em | 4 ++-- ld/ldelf.c | 6 +++--- ld/ldlang.c | 30 +++++++++++++++--------------- 9 files changed, 44 insertions(+), 25 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index cececa09c24..f29913e9cf9 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,22 @@ +2019-12-26 Alan Modra + + * 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 * testsuite/lib/ld-lib.exp (uses_genelf): Remove moxie. diff --git a/ld/emultempl/alphaelf.em b/ld/emultempl/alphaelf.em index 4e7886fcd61..db53d515edb 100644 --- a/ld/emultempl/alphaelf.em +++ b/ld/emultempl/alphaelf.em @@ -47,7 +47,7 @@ alpha_after_open (void) lang_output_section_statement_type *plt_os[2]; num_plt = 0; - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) { diff --git a/ld/emultempl/mmo.em b/ld/emultempl/mmo.em index 85c58639533..247d8a8c0bf 100644 --- a/ld/emultempl/mmo.em +++ b/ld/emultempl/mmo.em @@ -163,7 +163,7 @@ mmo_place_orphan (asection *s, /* We have to find the oss before this one, so we can use that as "after". */ - for (lookup = &lang_os_list.head->output_section_statement; + for (lookup = (void *) lang_os_list.head; lookup != NULL && lookup->next != before; lookup = lookup->next) ; diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index c4c6464c3c0..7e85ede3e23 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -2151,7 +2151,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, NULL); if (after == NULL) /* *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. diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index ec2d83fa633..f9f6a8e98db 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -1950,7 +1950,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, NULL); if (after == NULL) /* *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. diff --git a/ld/emultempl/ppc32elf.em b/ld/emultempl/ppc32elf.em index 056068edb19..78a2eb1cfac 100644 --- a/ld/emultempl/ppc32elf.em +++ b/ld/emultempl/ppc32elf.em @@ -79,7 +79,7 @@ ppc_after_check_relocs (void) num_got = 0; num_plt = 0; - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) { diff --git a/ld/emultempl/spuelf.em b/ld/emultempl/spuelf.em index 40a757a9890..96ac86f3f24 100644 --- a/ld/emultempl/spuelf.em +++ b/ld/emultempl/spuelf.em @@ -290,7 +290,7 @@ spu_before_allocation (void) } /* 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 = os->next) if (os->bfd_section != NULL @@ -512,7 +512,7 @@ embedded_spu_file (lang_input_statement_type *entry, const char *flags) return FALSE; close (fd); - for (search = &input_file_chain.head->input_statement; + for (search = (void *) input_file_chain.head; search != NULL; search = search->next_real_file) if (search->filename != NULL) diff --git a/ld/ldelf.c b/ld/ldelf.c index b27917c5fcd..19ec9085e6f 100644 --- a/ld/ldelf.c +++ b/ld/ldelf.c @@ -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_alloc = NULL; - for (lookup = &lang_os_list.head->output_section_statement; + for (lookup = (void *) lang_os_list.head; lookup != NULL; 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 and sh_info field. */ - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) 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); if (after == NULL) /* *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); diff --git a/ld/ldlang.c b/ld/ldlang.c index 05ea0c881f8..1106ab145fd 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -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 skip it. */ - first = &lang_os_list.head->output_section_statement; + first = (void *) lang_os_list.head; first = first->next; /* 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; 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; *where != NULL; @@ -1904,7 +1904,7 @@ lang_insert_orphan (asection *s, /* Shuffle the bfd section list to make the output file look neater. This is really only cosmetic. */ if (place->section == NULL - && after != &lang_os_list.head->output_section_statement) + && after != (void *) lang_os_list.head) { asection *bfd_section = after->bfd_section; @@ -2846,7 +2846,7 @@ lookup_name (const char *name) { lang_input_statement_type *search; - for (search = &input_file_chain.head->input_statement; + for (search = (void *) input_file_chain.head; search != NULL; search = search->next_real_file) { @@ -4329,7 +4329,7 @@ strip_excluded_output_sections (void) lang_reset_memory_regions (); } - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) { @@ -4390,7 +4390,7 @@ lang_clear_os_map (void) if (map_head_is_link_order) return; - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) { @@ -6728,7 +6728,7 @@ lang_check (void) bfd *input_bfd; const bfd_arch_info_type *compatible; - for (file = &file_chain.head->input_statement; + for (file = (void *) file_chain.head; file != NULL; file = file->next) { @@ -7070,7 +7070,7 @@ lang_for_each_input_file (void (*func) (lang_input_statement_type *)) { lang_input_statement_type *f; - for (f = &input_file_chain.head->input_statement; + for (f = (void *) input_file_chain.head; f != NULL; f = f->next_real_file) if (f->flags.real) @@ -7196,7 +7196,7 @@ lang_reset_memory_regions (void) p->last_os = NULL; } - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) { @@ -7433,8 +7433,8 @@ static lang_input_statement_type * find_replacements_insert_point (bfd_boolean *before) { lang_input_statement_type *claim1, *lastobject; - lastobject = &input_file_chain.head->input_statement; - for (claim1 = &file_chain.head->input_statement; + lastobject = (void *) input_file_chain.head; + for (claim1 = (void *) file_chain.head; claim1 != NULL; 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 appear on the file chain, but if an element has been extracted 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 = f->next_real_file) { @@ -7609,7 +7609,7 @@ lang_propagate_lma_regions (void) { 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 = os->next) { @@ -8286,7 +8286,7 @@ lang_record_phdrs (void) bfd_vma at; c = 0; - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) { @@ -8372,7 +8372,7 @@ lang_record_phdrs (void) free (secs); /* 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 = os->next) { -- 2.30.2