Created attachment 6865 [details] Testcase Says binutils documentation: > Thin archives are also flattened, so that adding > one or more archives to a thin archive will add > the elements of the nested archive individually. > If it already exists and is a regular archive, > the existing members must be present in the same > directory as archive.
Created attachment 6866 [details] Backtrace
Created attachment 6867 [details] Another testcase A slightly modified testcase causes SIGSEGV in readelf.
Created attachment 6868 [details] Backtrace from readelf
Additional comment about the 2nd testcase: $ strip libbarfoo.a causes the archive to be empty.
CVSROOT: /cvs/src Module name: src Changes by: nickc@sourceware.org 2013-02-15 14:37:39 Modified files: binutils : ChangeLog readelf.c ar.c elfcomm.c bfd : ChangeLog archive.c binutils/doc : binutils.texi Log message: PR binutils/15140 * ar.c (open_inarch): Fail on attempts to convert a normal archive to a thin archive or vice versa. * elfcomm.c (make_qualified_name): Handle corrupted thin archives. * readelf.c (process_archive): Likewise. * doc/binutils.texi: Clarify documentation describing thin archives. * archive.c (_bfd_get_elt_at_filepos): Prevent an infinite loop accessing a corrupt nested archive. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/ChangeLog.diff?cvsroot=src&r1=1.1990&r2=1.1991 http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/readelf.c.diff?cvsroot=src&r1=1.594&r2=1.595 http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/ar.c.diff?cvsroot=src&r1=1.86&r2=1.87 http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/elfcomm.c.diff?cvsroot=src&r1=1.4&r2=1.5 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/ChangeLog.diff?cvsroot=src&r1=1.5966&r2=1.5967 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/archive.c.diff?cvsroot=src&r1=1.95&r2=1.96 http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/doc/binutils.texi.diff?cvsroot=src&r1=1.197&r2=1.198
Hi Dmitry, The problem here is not the flattening of thin archives, but rather the fact that you are trying to convert a normal, non-thin, archive into a thin one. This is not supported, but ar should have produced an error message when the attempt was made. I have checked in a patch which fixes ar so that it will produce an error message. It also updates the documentation to make it clear that archives cannot be converted between normal and thin types. Finally the patch fixes readelf so that it no longer segfaults on the corrupted archive and nm so that it no longer goes into an infinite loop trying to read its symbol table. Cheers Nick
This patch: @@ -619,6 +617,7 @@ _bfd_append_relative_path (bfd *arch, char *elt_name) bfd * _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos) { + static file_ptr prev_filepos; struct areltdata *new_areldata; bfd *n_nfd; char *filename; @@ -626,6 +625,12 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos) n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos); if (n_nfd) return n_nfd; + /* PR15140: Prevent an inifnite recursion scanning a malformed nested archive. */ + if (filepos == prev_filepos) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } if (0 > bfd_seek (archive, filepos, SEEK_SET)) return NULL; @@ -634,6 +639,7 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos) return NULL; filename = new_areldata->filename; + prev_filepos = filepos; if (bfd_is_thin_archive (archive)) { has 2 problems: 1. It sets prev_filepos on success. The next call on the same filepos returns NULL. 2. It checks prev_filepos without checking if archive is the same. It caused PR 15151.
A different fix checked in.