asan: use of uninitialised value in s_ifeqs

Message ID akCMS7j2mROTsVIV@squeak.grove.modra.org
State New
Headers
Series asan: use of uninitialised value in s_ifeqs |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply

Commit Message

Alan Modra June 28, 2026, 2:51 a.m. UTC
  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.
  

Patch

diff --git a/gas/cond.c b/gas/cond.c
index 53c6e3e459b..300bb270f76 100644
--- a/gas/cond.c
+++ b/gas/cond.c
@@ -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;
 
diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c
index f2acb22da5f..f9f04a8389e 100644
--- a/gas/config/tc-alpha.c
+++ b/gas/config/tc-alpha.c
@@ -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 ();
 }
diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c
index d90780c9d04..a5cfa46fe34 100644
--- a/gas/config/tc-ia64.c
+++ b/gas/config/tc-ia64.c
@@ -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';
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index 78e5941484c..b82ba2eaebd 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -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;
diff --git a/gas/config/tc-tic54x.c b/gas/config/tc-tic54x.c
index 7b3b0738a1f..b53571251c4 100644
--- a/gas/config/tc-tic54x.c
+++ b/gas/config/tc-tic54x.c
@@ -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
diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c
index 7b338bb11cd..a1ceab4e428 100644
--- a/gas/dwarf2dbg.c
+++ b/gas/dwarf2dbg.c
@@ -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 ();
 	}
 
diff --git a/gas/ecoff.c b/gas/ecoff.c
index 0bd6a4e366a..9890a1fb8b4 100644
--- a/gas/ecoff.c
+++ b/gas/ecoff.c
@@ -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);
 
diff --git a/gas/read.c b/gas/read.c
index 56bd222acf0..1a7537ba2a1 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -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".
+      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;
+	       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;
 	}
     }
diff --git a/gas/stabs.c b/gas/stabs.c
index 0233cc5e018..3e09e10f045 100644
--- a/gas/stabs.c
+++ b/gas/stabs.c
@@ -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 == ',')
     {