asan: use of uninitialised value in s_ifeqs

Alan Modra <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
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.

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 == ',')
     {

-- 
Alan Modra
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.