PR27716, build failure for msdosdjgpp: PATH_MAX undeclared

We shouldn't be using arbitrary limits like PATH_MAX in GNU programs.
This patch also fixes some memory leaks in readelf when processing
separate debug info.

	PR 27716
binutils/
	* objdump.c (show_line): Don't limit paths to PATH_MAX.
	* readelf.c (struct filedata): Change program_interpreter from
	a char array to a char pointer.
	(process_program_headers): Sanity check PT_INTERP p_filesz.
	Malloc program_interpreter using p_filesz and read directly from
	file.
	(process_dynamic_section): Check program_interpreter is non-NULL.
	(free_filedata): New function, split out from..
	(process_object): ..here.
	(close_debug_file): Call free_filedata.
	* sysdep.h: Don't include sys/param.h.
	(PATH_MAX): Don't define.
	* configure.ac: Don't check for sys/param.h.
	* configure: Regenerate.
gprof/
	* gprof.h (PATH_MAX): Don't define.
	* corefile.c (core_create_line_syms): Don't use PATH_MAX for initial
	file name size.
	* source.c (annotate_source): Malloc file name buffer.  Always
	trim off "-ann" when dos 8.3 annotate file matches original.
	* utils.c (print_name_only): Malloc file name buffer.
This commit is contained in:
Alan Modra 2021-04-14 12:42:27 +09:30
parent d20eb46617
commit 13acb58d42
11 changed files with 132 additions and 104 deletions

View File

@ -1,3 +1,21 @@
2021-04-14 Alan Modra <amodra@gmail.com>
PR 27716
* objdump.c (show_line): Don't limit paths to PATH_MAX.
* readelf.c (struct filedata): Change program_interpreter from
a char array to a char pointer.
(process_program_headers): Sanity check PT_INTERP p_filesz.
Malloc program_interpreter using p_filesz and read directly from
file.
(process_dynamic_section): Check program_interpreter is non-NULL.
(free_filedata): New function, split out from..
(process_object): ..here.
(close_debug_file): Call free_filedata.
* sysdep.h: Don't include sys/param.h.
(PATH_MAX): Don't define.
* configure.ac: Don't check for sys/param.h.
* configure: Regenerate.
2021-04-13 Frederic Cambus <fred@statdns.com> 2021-04-13 Frederic Cambus <fred@statdns.com>
* readelf.c (process_netbsd_elf_note): Remove now unneeded #ifdef * readelf.c (process_netbsd_elf_note): Remove now unneeded #ifdef

2
binutils/configure vendored
View File

@ -12983,7 +12983,7 @@ _ACEOF
# guarantees they are available. # guarantees they are available.
# plugin-api.h tests HAVE_STDINT_H and HAVE_INTTYPES_H # plugin-api.h tests HAVE_STDINT_H and HAVE_INTTYPES_H
# Besides those, we need to check anything used in binutils/ not in C99. # Besides those, we need to check anything used in binutils/ not in C99.
for ac_header in fcntl.h inttypes.h stdint.h sys/file.h sys/param.h \ for ac_header in fcntl.h inttypes.h stdint.h sys/file.h \
sys/stat.h sys/types.h unistd.h sys/stat.h sys/types.h unistd.h
do : do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`

View File

@ -181,7 +181,7 @@ AC_CHECK_SIZEOF([long long])
# guarantees they are available. # guarantees they are available.
# plugin-api.h tests HAVE_STDINT_H and HAVE_INTTYPES_H # plugin-api.h tests HAVE_STDINT_H and HAVE_INTTYPES_H
# Besides those, we need to check anything used in binutils/ not in C99. # Besides those, we need to check anything used in binutils/ not in C99.
AC_CHECK_HEADERS(fcntl.h inttypes.h stdint.h sys/file.h sys/param.h \ AC_CHECK_HEADERS(fcntl.h inttypes.h stdint.h sys/file.h \
sys/stat.h sys/types.h unistd.h) sys/stat.h sys/types.h unistd.h)
AC_HEADER_SYS_WAIT AC_HEADER_SYS_WAIT
AC_FUNC_MMAP AC_FUNC_MMAP

View File

@ -1739,7 +1739,7 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset)
char *path_up; char *path_up;
const char *fname = filename; const char *fname = filename;
path = xmalloc (prefix_length + PATH_MAX + 1); path = xmalloc (prefix_length + 1 + strlen (filename));
if (prefix_length) if (prefix_length)
memcpy (path, prefix, prefix_length); memcpy (path, prefix, prefix_length);
@ -1762,8 +1762,7 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset)
} }
/* Update complete filename. */ /* Update complete filename. */
strncpy (path_up, fname, PATH_MAX); strcpy (path_up, fname);
path_up[PATH_MAX] = '\0';
filename = path; filename = path;
reloc = true; reloc = true;

View File

@ -292,7 +292,7 @@ typedef struct filedata
bfd_vma * gnuchains; bfd_vma * gnuchains;
bfd_vma * mipsxlat; bfd_vma * mipsxlat;
bfd_vma gnusymidx; bfd_vma gnusymidx;
char program_interpreter[PATH_MAX]; char * program_interpreter;
bfd_vma dynamic_info[DT_ENCODING]; bfd_vma dynamic_info[DT_ENCODING];
bfd_vma dynamic_info_DT_GNU_HASH; bfd_vma dynamic_info_DT_GNU_HASH;
bfd_vma dynamic_info_DT_MIPS_XHASH; bfd_vma dynamic_info_DT_MIPS_XHASH;
@ -5538,22 +5538,21 @@ the .dynamic section is not the same as the dynamic segment\n"));
break; break;
case PT_INTERP: case PT_INTERP:
if (fseek (filedata->handle, if (segment->p_offset >= filedata->file_size
filedata->archive_file_offset + (long) segment->p_offset, || segment->p_filesz > filedata->file_size - segment->p_offset
SEEK_SET)) || segment->p_filesz - 1 >= (size_t) -2
|| fseek (filedata->handle,
filedata->archive_file_offset + (long) segment->p_offset,
SEEK_SET))
error (_("Unable to find program interpreter name\n")); error (_("Unable to find program interpreter name\n"));
else else
{ {
char fmt [32]; size_t len = segment->p_filesz;
int ret = snprintf (fmt, sizeof (fmt), "%%%ds", PATH_MAX - 1); free (filedata->program_interpreter);
filedata->program_interpreter = xmalloc (len + 1);
if (ret >= (int) sizeof (fmt) || ret < 0) len = fread (filedata->program_interpreter, 1, len,
error (_("Internal error: failed to create format string to display program interpreter\n")); filedata->handle);
filedata->program_interpreter[len] = 0;
filedata->program_interpreter[0] = 0;
if (fscanf (filedata->handle, fmt,
filedata->program_interpreter) <= 0)
error (_("Unable to read program interpreter name\n"));
if (do_segments) if (do_segments)
printf (_(" [Requesting program interpreter: %s]\n"), printf (_(" [Requesting program interpreter: %s]\n"),
@ -11094,7 +11093,8 @@ the .dynstr section doesn't match the DT_STRTAB and DT_STRSZ tags\n"));
case DT_NEEDED: case DT_NEEDED:
printf (_("Shared library: [%s]"), name); printf (_("Shared library: [%s]"), name);
if (streq (name, filedata->program_interpreter)) if (filedata->program_interpreter
&& streq (name, filedata->program_interpreter))
printf (_(" program interpreter")); printf (_(" program interpreter"));
break; break;
@ -21050,6 +21050,70 @@ get_file_header (Filedata * filedata)
return true; return true;
} }
static void
free_filedata (Filedata *filedata)
{
free (filedata->program_interpreter);
filedata->program_interpreter = NULL;
free (filedata->program_headers);
filedata->program_headers = NULL;
free (filedata->section_headers);
filedata->section_headers = NULL;
free (filedata->string_table);
filedata->string_table = NULL;
filedata->string_table_length = 0;
free (filedata->dump.dump_sects);
filedata->dump.dump_sects = NULL;
filedata->dump.num_dump_sects = 0;
free (filedata->dynamic_strings);
filedata->dynamic_strings = NULL;
filedata->dynamic_strings_length = 0;
free (filedata->dynamic_symbols);
filedata->dynamic_symbols = NULL;
filedata->num_dynamic_syms = 0;
free (filedata->dynamic_syminfo);
filedata->dynamic_syminfo = NULL;
free (filedata->dynamic_section);
filedata->dynamic_section = NULL;
while (filedata->symtab_shndx_list != NULL)
{
elf_section_list *next = filedata->symtab_shndx_list->next;
free (filedata->symtab_shndx_list);
filedata->symtab_shndx_list = next;
}
free (filedata->section_headers_groups);
filedata->section_headers_groups = NULL;
if (filedata->section_groups)
{
size_t i;
struct group_list * g;
struct group_list * next;
for (i = 0; i < filedata->group_count; i++)
{
for (g = filedata->section_groups [i].root; g != NULL; g = next)
{
next = g->next;
free (g);
}
}
free (filedata->section_groups);
filedata->section_groups = NULL;
}
}
static void static void
close_file (Filedata * filedata) close_file (Filedata * filedata)
{ {
@ -21064,6 +21128,7 @@ close_file (Filedata * filedata)
void void
close_debug_file (void * data) close_debug_file (void * data)
{ {
free_filedata ((Filedata *) data);
close_file ((Filedata *) data); close_file ((Filedata *) data);
} }
@ -21277,61 +21342,7 @@ process_object (Filedata * filedata)
if (! process_arch_specific (filedata)) if (! process_arch_specific (filedata))
res = false; res = false;
free (filedata->program_headers); free_filedata (filedata);
filedata->program_headers = NULL;
free (filedata->section_headers);
filedata->section_headers = NULL;
free (filedata->string_table);
filedata->string_table = NULL;
filedata->string_table_length = 0;
free (filedata->dump.dump_sects);
filedata->dump.dump_sects = NULL;
filedata->dump.num_dump_sects = 0;
free (filedata->dynamic_strings);
filedata->dynamic_strings = NULL;
filedata->dynamic_strings_length = 0;
free (filedata->dynamic_symbols);
filedata->dynamic_symbols = NULL;
filedata->num_dynamic_syms = 0;
free (filedata->dynamic_syminfo);
filedata->dynamic_syminfo = NULL;
free (filedata->dynamic_section);
filedata->dynamic_section = NULL;
while (filedata->symtab_shndx_list != NULL)
{
elf_section_list *next = filedata->symtab_shndx_list->next;
free (filedata->symtab_shndx_list);
filedata->symtab_shndx_list = next;
}
free (filedata->section_headers_groups);
filedata->section_headers_groups = NULL;
if (filedata->section_groups)
{
struct group_list * g;
struct group_list * next;
for (i = 0; i < filedata->group_count; i++)
{
for (g = filedata->section_groups [i].root; g != NULL; g = next)
{
next = g->next;
free (g);
}
}
free (filedata->section_groups);
filedata->section_groups = NULL;
}
free_debug_memory (); free_debug_memory ();

View File

@ -124,23 +124,8 @@ extern char **environ;
/* Used by ar.c and objcopy.c. */ /* Used by ar.c and objcopy.c. */
#define BUFSIZE 8192 #define BUFSIZE 8192
/* For PATH_MAX. */
#include <limits.h> #include <limits.h>
#ifndef PATH_MAX
/* For MAXPATHLEN. */
# ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
# endif
# ifndef PATH_MAX
# ifdef MAXPATHLEN
# define PATH_MAX MAXPATHLEN
# else
# define PATH_MAX 1024
# endif
# endif
#endif
#if SIZEOF_LONG_LONG > SIZEOF_LONG #if SIZEOF_LONG_LONG > SIZEOF_LONG
/* We can't use any bfd types here since readelf may define BFD64 and /* We can't use any bfd types here since readelf may define BFD64 and
objdump may not. */ objdump may not. */

View File

@ -1,3 +1,13 @@
2021-04-14 Alan Modra <amodra@gmail.com>
PR 27716
* gprof.h (PATH_MAX): Don't define.
* corefile.c (core_create_line_syms): Don't use PATH_MAX for initial
file name size.
* source.c (annotate_source): Malloc file name buffer. Always
trim off "-ann" when dos 8.3 annotate file matches original.
* utils.c (print_name_only): Malloc file name buffer.
2021-04-05 Alan Modra <amodra@gmail.com> 2021-04-05 Alan Modra <amodra@gmail.com>
* configure.ac: Check for sys/time.h and setitimer. Don't invoke * configure.ac: Check for sys/time.h and setitimer. Don't invoke

View File

@ -781,8 +781,8 @@ core_create_line_syms (void)
Of course, this is rather slow and it would be better if Of course, this is rather slow and it would be better if
BFD would provide an iterator for enumerating all line infos. */ BFD would provide an iterator for enumerating all line infos. */
prev_name_len = PATH_MAX; prev_name_len = 1024;
prev_filename_len = PATH_MAX; prev_filename_len = 1024;
prev_name = (char *) xmalloc (prev_name_len); prev_name = (char *) xmalloc (prev_name_len);
prev_filename = (char *) xmalloc (prev_filename_len); prev_filename = (char *) xmalloc (prev_filename_len);
ltab.len = 0; ltab.len = 0;

View File

@ -54,10 +54,6 @@
/* AIX defines hz as a macro. */ /* AIX defines hz as a macro. */
#undef hz #undef hz
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#define A_OUTNAME "a.out" /* default core filename */ #define A_OUTNAME "a.out" /* default core filename */
#define GMONNAME "gmon.out" /* default profile filename */ #define GMONNAME "gmon.out" /* default profile filename */
#define GMONSUM "gmon.sum" /* profile summary filename */ #define GMONSUM "gmon.sum" /* profile summary filename */

View File

@ -97,14 +97,14 @@ annotate_source (Source_File *sf, unsigned int max_width,
int i, line_num, nread; int i, line_num, nread;
bool new_line; bool new_line;
char buf[8192]; char buf[8192];
char fname[PATH_MAX]; char *fname;
char *annotation, *name_only; char *annotation, *name_only;
FILE *ifp, *ofp; FILE *ifp, *ofp;
Search_List_Elem *sle = src_search_list.head; Search_List_Elem *sle = src_search_list.head;
/* Open input file. If open fails, walk along search-list until /* Open input file. If open fails, walk along search-list until
open succeeds or reaching end of list. */ open succeeds or reaching end of list. */
strcpy (fname, sf->name); fname = (char *) sf->name;
if (IS_ABSOLUTE_PATH (sf->name)) if (IS_ABSOLUTE_PATH (sf->name))
sle = 0; /* Don't use search list for absolute paths. */ sle = 0; /* Don't use search list for absolute paths. */
@ -116,6 +116,8 @@ annotate_source (Source_File *sf, unsigned int max_width,
sf->name, fname)); sf->name, fname));
ifp = fopen (fname, FOPEN_RB); ifp = fopen (fname, FOPEN_RB);
if (fname != sf->name)
free (fname);
if (ifp) if (ifp)
break; break;
@ -141,6 +143,8 @@ annotate_source (Source_File *sf, unsigned int max_width,
if (sle) if (sle)
{ {
fname = xmalloc (strlen (sle->path) + 3
+ strlen (name_only ? name_only : sf->name));
strcpy (fname, sle->path); strcpy (fname, sle->path);
#ifdef HAVE_DOS_BASED_FILE_SYSTEM #ifdef HAVE_DOS_BASED_FILE_SYSTEM
/* d:foo is not the same thing as d:/foo! */ /* d:foo is not the same thing as d:/foo! */
@ -191,6 +195,7 @@ annotate_source (Source_File *sf, unsigned int max_width,
else else
filename = sf->name; filename = sf->name;
fname = xmalloc (strlen (filename) + strlen (EXT_ANNO) + 1);
strcpy (fname, filename); strcpy (fname, filename);
strcat (fname, EXT_ANNO); strcat (fname, EXT_ANNO);
#ifdef __MSDOS__ #ifdef __MSDOS__
@ -205,9 +210,9 @@ annotate_source (Source_File *sf, unsigned int max_width,
{ {
char *dot = strrchr (fname, '.'); char *dot = strrchr (fname, '.');
if (dot) if (!dot)
*dot = '\0'; dot = fname + strlen (filename);
strcat (fname, ".ann"); strcpy (dot, ".ann");
} }
} }
#endif #endif
@ -216,8 +221,10 @@ annotate_source (Source_File *sf, unsigned int max_width,
if (!ofp) if (!ofp)
{ {
perror (fname); perror (fname);
free (fname);
return 0; return 0;
} }
free (fname);
} }
/* Print file names if output goes to stdout /* Print file names if output goes to stdout

View File

@ -43,9 +43,7 @@ int
print_name_only (Sym *self) print_name_only (Sym *self)
{ {
const char *name = self->name; const char *name = self->name;
const char *filename;
char *demangled = 0; char *demangled = 0;
char buf[PATH_MAX];
int size = 0; int size = 0;
if (name) if (name)
@ -60,7 +58,9 @@ print_name_only (Sym *self)
size = strlen (name); size = strlen (name);
if ((line_granularity || inline_file_names) && self->file) if ((line_granularity || inline_file_names) && self->file)
{ {
filename = self->file->name; const char *filename = self->file->name;
char *buf;
if (!print_path) if (!print_path)
{ {
filename = strrchr (filename, '/'); filename = strrchr (filename, '/');
@ -73,6 +73,7 @@ print_name_only (Sym *self)
filename = self->file->name; filename = self->file->name;
} }
} }
buf = xmalloc (strlen (filename) + 8 + 20 + 16);
if (line_granularity) if (line_granularity)
{ {
sprintf (buf, " (%s:%d @ %lx)", filename, self->line_num, sprintf (buf, " (%s:%d @ %lx)", filename, self->line_num,
@ -84,6 +85,7 @@ print_name_only (Sym *self)
} }
printf ("%s", buf); printf ("%s", buf);
size += strlen (buf); size += strlen (buf);
free (buf);
} }
free (demangled); free (demangled);
DBG (DFNDEBUG, printf ("{%d} ", self->cg.top_order)); DBG (DFNDEBUG, printf ("{%d} ", self->cg.top_order));