Avoid ubsan bug complaining about &p->field
authorAlan Modra <amodra@gmail.com>
Tue, 26 Nov 2019 06:19:44 +0000 (16:49 +1030)
committerAlan Modra <amodra@gmail.com>
Thu, 26 Dec 2019 07:19:03 +0000 (17:49 +1030)
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
ld/emultempl/alphaelf.em
ld/emultempl/mmo.em
ld/emultempl/pe.em
ld/emultempl/pep.em
ld/emultempl/ppc32elf.em
ld/emultempl/spuelf.em
ld/ldelf.c
ld/ldlang.c

index cececa09c24199045365ae67050cf36cc1b8dac6..f29913e9cf924adeb9ffb5f9acb567a780427d14 100644 (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>
 
        * testsuite/lib/ld-lib.exp (uses_genelf): Remove moxie.
index 4e7886fcd612e827565b57a8c63d4ff64ad52a3c..db53d515edbb0d76a2dec66f0620b6b298f5022d 100644 (file)
@@ -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)
        {
index 85c5863953396bd97692ad3d0ae23cbaf2613fc1..247d8a8c0bf3f0452773c33d29f0078d6b7c516e 100644 (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
             "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)
            ;
index c4c6464c3c01a7b5e2da39fc62fa084565df0abf..7e85ede3e2330f6fb4caf47ff1244bae7adb7021 100644 (file)
@@ -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.
index ec2d83fa633527589a60ff03ed5eb36b8c57f068..f9f6a8e98db4430c291c058614bf343cc5759782 100644 (file)
@@ -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.
index 056068edb1989bd85fda0663912edf7d9751984c..78a2eb1cfacb45e528ea5eaecf56b9c9ff4e6097 100644 (file)
@@ -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)
        {
index 40a757a98902d8be4eda258cfcf2892e0b5405ca..96ac86f3f24ab65014afde9305eeebd9c61544dc 100644 (file)
@@ -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)
index b27917c5fcd0e7d0b25043b869df735e302917d2..19ec9085e6f0b968eb8bc1dcb83125308389aeb2 100644 (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_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);
index 05ea0c881f825d12bd7cd0e3117fd8cf02c9f2a6..1106ab145fd67ca9bb158cd806a84bd552a27f21 100644 (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
      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)
     {