]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
asan: use of uninitialised value in s_ifeqs
authorAlan Modra <amodra@gmail.com>
Sat, 27 Jun 2026 04:28:46 +0000 (13:58 +0930)
committerAlan Modra <amodra@gmail.com>
Sun, 28 Jun 2026 02:48:35 +0000 (12:18 +0930)
demand_copy_string returns NULL when a double-quoted string is not
found, and calls ignore_rest_of_line.  demand_copy_C_string can also
return NULL when finding an embedded \0, but doesn't call
ignore_rest_of_line for this condition.  This makes it difficult to
handle errors.

I believe ignore_rest_of_line should only be called at the level of
functions handling an entire line.  It will typically appear then only
in functions that call demand_empty_rest_of_line.  So this patch
removes the ignore_rest_of_file call in demand_copy_string, moving it
to callers of these functions.  Missing error handling is added in the
second part of the changelog below.

* read.c (demand_copy_string): Don't call ignore_rest_of_file.
(demand_copy_C_string): Don't zero length on error.
(s_file, s_incbin, s_include): Call ignore_rest_of_file on
demand_copy_string error.
(s_errwarn, s_print): Call ignore_rest_of_file on
demand_copy_C_string error.
(s_linefile): Move ignore_rest_of_line call for negative linenum
earlier and similarly for missing file, reducing block
indentation.
* config/tc-tic54x.c (tic54x_mlib): Call ignore_rest_of_line
after demand_copy_C_string error.
* dwarf2dbg.c (dwarf2_directive_filename): Likewise.
* stabs.c (s_stab_generic, s_xstab): Likewise.

* cond.c (s_ifeqs): Handle NULL return from demand_copy_C_string.
* config/tc-ia64.c (dot_pred_rel): Likewise.
* config/tc-ppc.c (ppc_rename, ppc_stabx, ppc_biei, ppc_bc): Likewise.
* config/tc-tic54x.c (tic54x_asg, tic54x_sect, tic54x_include),
(tic54x_message, tic54x_sblock, subsym_get_arg): Likewise.
* ecoff.c (ecoff_directive_file): Likewise.
* config/tc-alpha.c (s_alpha_file): Handle NULL return from
demand_copy_string.
* config/tc-ppc.c (ppc_file): Likewise.

gas/cond.c
gas/config/tc-alpha.c
gas/config/tc-ia64.c
gas/config/tc-ppc.c
gas/config/tc-tic54x.c
gas/dwarf2dbg.c
gas/ecoff.c
gas/read.c
gas/stabs.c

index 53c6e3e459ba38c696246547456a53f1da7880da..300bb270f76a3873e15750a4e242d836cdfb032f 100644 (file)
@@ -460,6 +460,11 @@ s_ifeqs (int arg)
   struct conditional_frame cframe;
 
   s1 = demand_copy_C_string (&len1);
+  if (s1 == NULL)
+    {
+      ignore_rest_of_line ();
+      return;
+    }
 
   SKIP_WHITESPACE ();
   if (*input_line_pointer != ',')
@@ -472,6 +477,11 @@ s_ifeqs (int arg)
   ++input_line_pointer;
 
   s2 = demand_copy_C_string (&len2);
+  if (s2 == NULL)
+    {
+      ignore_rest_of_line ();
+      return;
+    }
 
   res = len1 == len2 && strncmp (s1, s2, len1) == 0;
 
index f2acb22da5f71599d739c7e53e2fdfdf9715c184..f9f04a8389e0ba7c9ee58c7c86f4987614c4a55a 100644 (file)
@@ -4785,6 +4785,7 @@ static void
 s_alpha_file (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *s;
+  char *name;
   int length;
   static char case_hack[32];
 
@@ -4795,7 +4796,13 @@ s_alpha_file (int ignore ATTRIBUTE_UNUSED)
   symbol_get_bfdsym (s)->flags |= BSF_FILE;
 
   get_absolute_expression ();
-  s = symbol_find_or_make (demand_copy_string (&length));
+  name = demand_copy_string (&length);
+  if (name == NULL)
+    {
+      ignore_rest_of_line ();
+      return;
+    }
+  s = symbol_find_or_make (name);
   symbol_get_bfdsym (s)->flags |= BSF_FILE;
   demand_empty_rest_of_line ();
 }
index d90780c9d041561d25bf66996ba7544bfcd3eda4..a5cfa46fe34a79aa50b7c141c0f1bd8df78028a3 100644 (file)
@@ -4990,6 +4990,11 @@ dot_pred_rel (int type)
        {
          int len;
          char *form = demand_copy_C_string (&len);
+         if (form == NULL)
+           {
+             ignore_rest_of_line ();
+             return;
+           }
 
          if (strcmp (form, "mutex") == 0)
            type = 'm';
index 78e5941484cbcf6fc2d06026733e6005e08863e3..b82ba2eaebdd2d67585d7b11ea46497c0daf3873 100644 (file)
@@ -5059,8 +5059,14 @@ ppc_rename (int ignore ATTRIBUTE_UNUSED)
     }
   ++input_line_pointer;
 
-  symbol_get_tc (sym)->real_name = demand_copy_C_string (&len);
+  name = demand_copy_C_string (&len);
+  if (name == NULL)
+    {
+      ignore_rest_of_line ();
+      return;
+    }
 
+  symbol_get_tc (sym)->real_name = name;
   demand_empty_rest_of_line ();
 }
 
@@ -5080,6 +5086,11 @@ ppc_stabx (int ignore ATTRIBUTE_UNUSED)
   expressionS exp;
 
   name = demand_copy_C_string (&len);
+  if (name == NULL)
+    {
+      ignore_rest_of_line ();
+      return;
+    }
 
   if (*input_line_pointer != ',')
     {
@@ -5199,56 +5210,75 @@ ppc_file (int ignore ATTRIBUTE_UNUSED)
 {
   char *sfname, *s1 = NULL, *s2 = NULL, *s3 = NULL;
   int length, auxnb = 1;
+  coff_symbol_type *coffsym;
 
   /* Some assemblers tolerate immediately following '"'.  */
-  if ((sfname = demand_copy_string (&length)) != 0)
+  sfname = demand_copy_string (&length);
+  if (sfname == NULL)
+    {
+      ignore_rest_of_line ();
+      return;
+    }
+
+  if (*input_line_pointer == ',')
     {
-      coff_symbol_type *coffsym;
+      ++input_line_pointer;
+      s1 = demand_copy_string (&length);
+      if (s1 == NULL)
+       {
+         ignore_rest_of_line ();
+         return;
+       }
+      auxnb++;
+
       if (*input_line_pointer == ',')
        {
          ++input_line_pointer;
-         s1 = demand_copy_string (&length);
+         s2 = demand_copy_string (&length);
+         if (s2 == NULL)
+           {
+             ignore_rest_of_line ();
+             return;
+           }
          auxnb++;
 
          if (*input_line_pointer == ',')
            {
              ++input_line_pointer;
-             s2 = demand_copy_string (&length);
-             auxnb++;
-
-             if (*input_line_pointer == ',')
+             s3 = demand_copy_string (&length);
+             if (s3 == NULL)
                {
-                 ++input_line_pointer;
-                 s3 = demand_copy_string (&length);
-                 auxnb++;
+                 ignore_rest_of_line ();
+                 return;
                }
+             auxnb++;
            }
        }
+    }
 
-      /* Use coff dot_file creation and adjust auxiliary entries.  */
-      c_dot_file_symbol (sfname);
-      S_SET_NUMBER_AUXILIARY (symbol_rootP, auxnb);
-      coffsym = coffsymbol (symbol_get_bfdsym (symbol_rootP));
-      coffsym->native[1].u.auxent.x_file.x_ftype = XFT_FN;
-
-      if (s1)
-       {
-         coffsym->native[2].u.auxent.x_file.x_ftype = XFT_CT;
-         coffsym->native[2].extrap = s1;
-       }
-      if (s2)
-       {
-         coffsym->native[3].u.auxent.x_file.x_ftype = XFT_CV;
-         coffsym->native[3].extrap = s2;
-       }
-      if (s3)
-       {
-         coffsym->native[4].u.auxent.x_file.x_ftype = XFT_CD;
-         coffsym->native[4].extrap = s3;
-       }
+  /* Use coff dot_file creation and adjust auxiliary entries.  */
+  c_dot_file_symbol (sfname);
+  S_SET_NUMBER_AUXILIARY (symbol_rootP, auxnb);
+  coffsym = coffsymbol (symbol_get_bfdsym (symbol_rootP));
+  coffsym->native[1].u.auxent.x_file.x_ftype = XFT_FN;
 
-      demand_empty_rest_of_line ();
+  if (s1)
+    {
+      coffsym->native[2].u.auxent.x_file.x_ftype = XFT_CT;
+      coffsym->native[2].extrap = s1;
+    }
+  if (s2)
+    {
+      coffsym->native[3].u.auxent.x_file.x_ftype = XFT_CV;
+      coffsym->native[3].extrap = s2;
+    }
+  if (s3)
+    {
+      coffsym->native[4].u.auxent.x_file.x_ftype = XFT_CD;
+      coffsym->native[4].extrap = s3;
     }
+
+  demand_empty_rest_of_line ();
 }
 
 /* The .function pseudo-op.  This takes several arguments.  The first
@@ -5414,6 +5444,11 @@ ppc_biei (int ei)
   symbolS *look;
 
   name = demand_copy_C_string (&len);
+  if (name == NULL)
+    {
+      ignore_rest_of_line ();
+      return;
+    }
 
   /* The value of these symbols is actually file offset.  Here we set
      the value to the index into the line number entries.  In
@@ -5573,6 +5608,12 @@ ppc_bc (int ignore ATTRIBUTE_UNUSED)
   symbolS *sym;
 
   name = demand_copy_C_string (&len);
+  if (name == NULL)
+    {
+      ignore_rest_of_line ();
+      return;
+    }
+
   sym = symbol_make (name);
   S_SET_SEGMENT (sym, ppc_coff_debug_section);
   symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
index 7b3b0738a1f476aa180dca71a62248457b69303b..b53571251c4f6bb1a1b90636fe4f6c2241556499 100644 (file)
@@ -353,6 +353,11 @@ tic54x_asg (int x ATTRIBUTE_UNUSED)
     {
       int len;
       str = demand_copy_C_string (&len);
+      if (str == NULL)
+       {
+         ignore_rest_of_line ();
+         return;
+       }
       c = *input_line_pointer;
     }
   else
@@ -1227,6 +1232,11 @@ tic54x_sect (int arg)
       if (*input_line_pointer == '"')
        {
          name = demand_copy_C_string (&len);
+         if (name == NULL)
+           {
+             ignore_rest_of_line ();
+             return;
+           }
          demand_empty_rest_of_line ();
          name = concat (name, flags, (char *) NULL);
        }
@@ -1946,6 +1956,11 @@ tic54x_include (int ignored ATTRIBUTE_UNUSED)
   if (*input_line_pointer == '"')
     {
       filename = demand_copy_C_string (&len);
+      if (filename == NULL)
+       {
+         ignore_rest_of_line ();
+         return;
+       }
       demand_empty_rest_of_line ();
     }
   else
@@ -1983,7 +1998,14 @@ tic54x_message (int type)
   ILLEGAL_WITHIN_STRUCT ();
 
   if (*input_line_pointer == '"')
-    msg = demand_copy_C_string (&len);
+    {
+      msg = demand_copy_C_string (&len);
+      if (msg == NULL)
+       {
+         ignore_rest_of_line ();
+         return;
+       }
+    }
   else
     {
       msg = input_line_pointer;
@@ -2152,6 +2174,11 @@ tic54x_sblock (int ignore ATTRIBUTE_UNUSED)
          int len;
 
          name = demand_copy_C_string (&len);
+         if (name == NULL)
+           {
+             ignore_rest_of_line ();
+             return;
+           }
        }
       else
        {
@@ -2313,7 +2340,10 @@ tic54x_mlib (int ignore ATTRIBUTE_UNUSED)
   if (*input_line_pointer == '"')
     {
       if ((filename = demand_copy_C_string (&len)) == NULL)
-       return;
+       {
+         ignore_rest_of_line ();
+         return;
+       }
     }
   else
     {
@@ -4307,11 +4337,13 @@ subsym_get_arg (char *line, const char *terminators, char **str, int nosub)
 
       input_line_pointer = ptr;
       *str = demand_copy_C_string (&len);
+      if (*str == NULL)
+       ignore_rest_of_line ();
       endp = input_line_pointer;
       input_line_pointer = savedp;
 
       /* Do forced substitutions if requested.  */
-      if (!nosub && **str == ':')
+      if (!nosub && *str && **str == ':')
        *str = subsym_substitute (*str, 1);
     }
   else
index 7b338bb11cd1dfe8ded69f856f0d5b155ad51d44..a1ceab4e4282a1e20cb99bc08d4b44b2d74f788d 100644 (file)
@@ -1199,8 +1199,11 @@ dwarf2_directive_filename (void)
 
   filename = demand_copy_C_string (&filename_len);
   if (filename == NULL)
-    /* demand_copy_C_string will have already generated an error message.  */
-    return NULL;
+    {
+      /* demand_copy_C_string will have already generated an error.  */
+      ignore_rest_of_line ();
+      return NULL;
+    }
 
   /* For DWARF-5 support we also accept:
      .file <NUM> ["<dir>"] "<file>" [md5 <NUM>]  */
@@ -1212,7 +1215,10 @@ dwarf2_directive_filename (void)
          dirname = filename;
          filename = demand_copy_C_string (&filename_len);
          if (filename == NULL)
-           return NULL;
+           {
+             ignore_rest_of_line ();
+             return NULL;
+           }
          SKIP_WHITESPACE ();
        }
 
index 0bd6a4e366ac09278db282b36b5f7dd08f054b26..9890a1fb8b44133ce72f064dad7dd635ff0f1eee 100644 (file)
@@ -3086,6 +3086,11 @@ ecoff_directive_file (int ignore ATTRIBUTE_UNUSED)
 
   /* FIXME: we don't have to save the name here.  */
   name = demand_copy_C_string (&len);
+  if (name == NULL)
+    {
+      ignore_rest_of_line ();
+      return;
+    }
 
   add_file (name, indx - 1, 0);
 
index 56bd222acf08338f6c72f9a19983cf7e88dbed2f..1a7537ba2a19e684030efc591513854800ba5160 100644 (file)
@@ -2045,6 +2045,8 @@ s_file (int ignore ATTRIBUTE_UNUSED)
       demand_empty_rest_of_line ();
       s_file_string (s);
     }
+  else
+    ignore_rest_of_line ();
 }
 
 static bool
@@ -2099,90 +2101,94 @@ s_linefile (int ignore ATTRIBUTE_UNUSED)
     }
 
   if (linenum < 0)
-    /* Some of the back ends can't deal with non-positive line numbers.
-       Besides, it's silly.  GCC however will generate a line number of
-       zero when it is pre-processing builtins for assembler-with-cpp files:
+    {
+      /* Some of the back ends can't deal with non-positive line numbers.
+        Besides, it's silly.  GCC however will generate a line number of
+        zero when it is pre-processing builtins for assembler-with-cpp files:
 
-         # 0 "<built-in>"
+        # 0 "<built-in>"
 
-       We do not want to barf on this, especially since such files are used
-       in the GCC and GDB testsuites.  So we check for negative line numbers
-       rather than non-positive line numbers.  */
-    as_warn (_("line numbers must be positive; line number %d rejected"),
-            linenum);
-  else
-    {
-      int length = 0;
+        We do not want to barf on this, especially since such files are used
+        in the GCC and GDB testsuites.  So we check for negative line numbers
+        rather than non-positive line numbers.  */
+      as_warn (_("line numbers must be positive; line number %d rejected"),
+              linenum);
+      ignore_rest_of_line ();
+      return;
+    }
 
-      SKIP_WHITESPACE ();
+  SKIP_WHITESPACE ();
 
-      if (*input_line_pointer == '"')
-       file = demand_copy_string (&length);
-      else if (*input_line_pointer == '.')
+  if (*input_line_pointer == '"')
+    {
+      int this_flag;
+      int length = 0;
+      file = demand_copy_string (&length);
+      if (file == NULL)
        {
-         /* buffer_and_nest() may insert this form.  */
-         ++input_line_pointer;
-         flags = 1 << 3;
+         ignore_rest_of_line ();
+         return;
        }
 
-      if (file)
-       {
-         int this_flag;
-
-         while (get_linefile_number (&this_flag))
-           switch (this_flag)
-             {
-               /* From GCC's cpp documentation:
-                  1: start of a new file.
-                  2: returning to a file after having included another file.
-                  3: following text comes from a system header file.
-                  4: following text should be treated as extern "C".
-
-                  4 is nonsensical for the assembler; 3, we don't care about,
-                  so we ignore it just in case a system header file is
-                  included while preprocessing assembly.  So 1 and 2 are all
-                  we care about, and they are mutually incompatible.
-                  new_logical_line_flags() demands this.  */
-             case 1:
-             case 2:
-               if (flags && flags != (1 << this_flag))
-                 as_warn (_("incompatible flag %i in line directive"),
-                          this_flag);
-               else
-                 flags |= 1 << this_flag;
-               break;
+      while (get_linefile_number (&this_flag))
+       switch (this_flag)
+         {
+           /* From GCC's cpp documentation:
+              1: start of a new file.
+              2: returning to a file after having included another file.
+              3: following text comes from a system header file.
+              4: following text should be treated as extern "C".
+
+              4 is nonsensical for the assembler; 3, we don't care about,
+              so we ignore it just in case a system header file is
+              included while preprocessing assembly.  So 1 and 2 are all
+              we care about, and they are mutually incompatible.
+              new_logical_line_flags() demands this.  */
+         case 1:
+         case 2:
+           if (flags && flags != (1 << this_flag))
+             as_warn (_("incompatible flag %i in line directive"),
+                      this_flag);
+           else
+             flags |= 1 << this_flag;
+           break;
 
-             case 3:
-             case 4:
-               /* We ignore these.  */
-               break;
+         case 3:
+         case 4:
+           /* We ignore these.  */
+           break;
 
-             default:
-               as_warn (_("unsupported flag %i in line directive"),
-                        this_flag);
-               break;
-             }
+         default:
+           as_warn (_("unsupported flag %i in line directive"),
+                    this_flag);
+           break;
+         }
 
-         if (!is_end_of_stmt (*input_line_pointer))
-           file = NULL;
-        }
+      if (!is_end_of_stmt (*input_line_pointer))
+       file = NULL;
+    }
+  else if (*input_line_pointer == '.')
+    {
+      /* buffer_and_nest() may insert this form.  */
+      ++input_line_pointer;
+      flags = 1 << 3;
+    }
 
-      if (file || flags)
-       {
-         demand_empty_rest_of_line ();
+  if (file || flags)
+    {
+      demand_empty_rest_of_line ();
 
-         /* read_a_source_file() will bump the line number only if the line
-            is terminated by '\n'.  */
-         if (input_line_pointer[-1] == '\n')
-           linenum--;
+      /* read_a_source_file() will bump the line number only if the line
+        is terminated by '\n'.  */
+      if (input_line_pointer[-1] == '\n')
+       linenum--;
 
-         new_logical_line_flags (file, linenum, flags);
+      new_logical_line_flags (file, linenum, flags);
 #ifdef LISTING
-         if (listing)
-           listing_source_line (linenum);
+      if (listing)
+       listing_source_line (linenum);
 #endif
-         return;
-       }
+      return;
     }
   ignore_rest_of_line ();
 }
@@ -2241,7 +2247,10 @@ s_errwarn (int err)
 
       msg = demand_copy_C_string (&len);
       if (msg == NULL)
-       return;
+       {
+         ignore_rest_of_line ();
+         return;
+       }
     }
 
   if (err)
@@ -3135,8 +3144,12 @@ s_print (int ignore ATTRIBUTE_UNUSED)
   int len;
 
   s = demand_copy_C_string (&len);
-  if (s != NULL)
-    printf ("%s\n", s);
+  if (s == NULL)
+    {
+      ignore_rest_of_line ();
+      return;
+    }
+  printf ("%s\n", s);
   demand_empty_rest_of_line ();
 }
 
@@ -6342,8 +6355,7 @@ demand_copy_C_string (int *len_pointer)
        {
          if (s[len - 1] == 0)
            {
-             s = 0;
-             *len_pointer = 0;
+             s = NULL;
              as_bad (_("this string may not contain \'\\0\'"));
              break;
            }
@@ -6383,7 +6395,6 @@ demand_copy_string (int *lenP)
     {
       as_bad (_("missing string"));
       retval = NULL;
-      ignore_rest_of_line ();
     }
   *lenP = len;
   return retval;
@@ -6478,7 +6489,10 @@ s_incbin (int x ATTRIBUTE_UNUSED)
   SKIP_WHITESPACE ();
   filename = demand_copy_string (& len);
   if (filename == NULL)
-    return;
+    {
+      ignore_rest_of_line ();
+      return;
+    }
 
   SKIP_WHITESPACE ();
 
@@ -6578,8 +6592,8 @@ s_include (int arg ATTRIBUTE_UNUSED)
       filename = demand_copy_string (&i);
       if (filename == NULL)
        {
-         /* demand_copy_string has already printed an error and
-            called ignore_rest_of_line.  */
+         /* demand_copy_string has already printed an error.  */
+         ignore_rest_of_line ();
          return;
        }
     }
index 0233cc5e0185bc92202231cf40c0458ecee1524b..3e09e10f045428d4e20fb1fb2c6c7da74c1098a1 100644 (file)
@@ -259,7 +259,10 @@ s_stab_generic (int what,
 
       string = demand_copy_C_string (&length);
       if (string == NULL)
-       goto out2;
+       {
+         ignore_rest_of_line ();
+         goto out2;
+       }
       /* FIXME: We should probably find some other temporary storage
         for string, rather than leaking memory if someone else
         happens to use the notes obstack.  */
@@ -399,8 +402,10 @@ s_xstab (int what)
 
   stab_secname = demand_copy_C_string (&length);
   if (stab_secname == NULL)
-    /* as_bad error has been reported.  */
-    return;
+    {
+      ignore_rest_of_line ();
+      return;
+    }
   SKIP_WHITESPACE ();
   if (*input_line_pointer == ',')
     {