From e264b5b7a57dab997776ae845f9e0b3e5f20c713 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 7 Nov 2019 11:56:54 +0000 Subject: [PATCH] Allow the --output option of the "ar" prorgam to extract files to locations outside of the current directory. * ar.c (open_output_file): Check for filename validity before prefixing with output directory. Display the constructed output filename if in verbose mode. (extract_file): Let open_output_file display the filename. --- binutils/ChangeLog | 7 +++++++ binutils/ar.c | 29 +++++++++++++++-------------- binutils/doc/binutils.texi | 9 +++------ 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index fb1a99d5ae..06823b27ab 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,10 @@ +2019-11-07 Nick Clifton + + * ar.c (open_output_file): Check for filename validity before + prefixing with output directory. + Display the constructed output filename if in verbose mode. + (extract_file): Let open_output_file display the filename. + 2019-11-07 Nick Clifton * objcopy.c (copy_object): Skip note sections that do not have diff --git a/binutils/ar.c b/binutils/ar.c index 0af7954a47..b8342ce65a 100644 --- a/binutils/ar.c +++ b/binutils/ar.c @@ -1070,6 +1070,18 @@ open_output_file (bfd * abfd) { output_filename = bfd_get_filename (abfd); + /* PR binutils/17533: Do not allow directory traversal + outside of the current directory tree - unless the + user has explicitly specified an output directory. */ + if (! is_valid_archive_path (output_filename)) + { + char * base = (char *) lbasename (output_filename); + + non_fatal (_("illegal output pathname for archive member: %s, using '%s' instead"), + output_filename, base); + output_filename = base; + } + if (output_dir) { size_t len = strlen (output_dir); @@ -1083,18 +1095,10 @@ open_output_file (bfd * abfd) output_filename = concat (output_dir, "/", output_filename, NULL); } } - - /* PR binutils/17533: Do not allow directory traversal - outside of the current directory tree. */ - if (! is_valid_archive_path (output_filename)) - { - char * base = (char *) lbasename (output_filename); - - non_fatal (_("illegal output pathname for archive member: %s, using '%s' instead"), - output_filename, base); - output_filename = base; - } + if (verbose) + printf ("x - %s\n", output_filename); + FILE * ostream = fopen (output_filename, FOPEN_WB); if (ostream == NULL) { @@ -1126,9 +1130,6 @@ extract_file (bfd *abfd) fatal (_("internal stat error on %s"), bfd_get_filename (abfd)); size = buf.st_size; - if (verbose) - printf ("x - %s\n", bfd_get_filename (abfd)); - bfd_seek (abfd, (file_ptr) 0, SEEK_SET); output_file = NULL; diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 2a86b92033..11de2d3deb 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -390,7 +390,9 @@ are extracted. Files cannot be extracted from a thin archive, and there are restrictions on extracting from archives created with @option{P}: The paths must not be absolute, may not contain @code{..}, and any -subdirectories in the paths must exist. +subdirectories in the paths must exist. If it is desired to avoid +these restrictions then used the @option{--output} option to specify +an output directory. @end table A number of modifiers (@var{mod}) may immediately follow the @var{p} @@ -589,11 +591,6 @@ Note - although the presence of this option does imply a @option{x} extraction operation that option must still be included on the command line. -Note - using this option does not allow archive members to be -extracted to locations outside of the current directory, or one of its -sub-directories. This is a security feature to prevent archives -created with the @option{P} option from maliciously overwriting user -files. @end table @c man end -- 2.34.1