From: Alan Modra Date: Sat, 27 Jun 2026 04:28:46 +0000 (+0930) Subject: asan: use of uninitialised value in s_ifeqs X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=756678fc9c04a10b260d1369ef2ff5e6cc9df0ad;p=thirdparty%2Fbinutils-gdb.git asan: use of uninitialised value in s_ifeqs 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 [""] "" [md5 ] */ @@ -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 "" + # 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); - 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; } } 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 == ',') {