Subject: bin/28: /usr/bin/ld doesn't deal with long name archive components
To: None <gnats-admin>
From: None <sommerfeld@orchard.medford.ma.us>
List: netbsd-bugs
Date: 11/29/1993 06:50:01
>Number:         28
>Category:       bin
>Synopsis:       /usr/bin/ld doesn't deal with long name archive components
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    gnats-admin (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Nov 29 06:50:01 1993
>Originator:     Bill Sommerfeld
>Organization:
	none
>Release:        NetBSD-current
>Environment:
	i486/NetBSD; happens with third-party software which doesn't use
	ar cT to create archives.
    	 
System: NetBSD orchard.medford.ma.us 0.9a ORCHARD#11 i386


>Description:
	If given an archive component with a name longer than 15 characters
	or containing spaces, the 4.4BSD "ar" in NetBSD prepends the real
	file name to the file in the archive, adjusts the file length
	appropriately, and stores a filename of "#1/<name length>".
	ld can't deal with this and reports a bad magic number if you 
	attempt to pull something with this form out of a library.
>How-To-Repeat:
	echo 'foo(){}' >funkelhausersteinweitz.c
	cc -c funkelhausersteinweitz.c
	ar cruv funkelhausersteinweitz.SIPBADMIN.a funkelhausersteinweitz.o
	echo 'main() { foo(); }' >main.c
	cc -c main.c
	cc -o main main.o funkelhausersteinweitz.SIPBADMIN.a

the final "cc" command will complain:
ld: bad magic number in funkelhausersteinweitz.SIPBADMIN.a(#1)

This is a contrived ( :-) ) example.
However, it affects third party software such as Kerberos.

>Fix:
Apply the following patch to src/gnu/usr.bin/ld/lib.c:

*** 1.1	1993/11/29 02:32:13
--- 1.2	1993/11/29 03:00:12
***************
*** 78,88 ****
  {
  	int             bytes_read;
  	register int    namelen;
! 	int             member_length;
  	register char  *name;
  	struct ar_hdr   hdr1;
  	register struct file_entry *subentry;
! 
  	lseek(desc, subfile_offset, 0);
  
  	bytes_read = read(desc, &hdr1, sizeof hdr1);
--- 78,88 ----
  {
  	int             bytes_read;
  	register int    namelen;
! 	int             member_length, content_length;
  	register char  *name;
  	struct ar_hdr   hdr1;
  	register struct file_entry *subentry;
! 	int starting_offset;
  	lseek(desc, subfile_offset, 0);
  
  	bytes_read = read(desc, &hdr1, sizeof hdr1);
***************
*** 104,125 ****
  	     && hdr1.ar_name[namelen] != '/';
  	     namelen++);
  
! 	name = (char *) xmalloc(namelen + 1);
! 	strncpy(name, hdr1.ar_name, namelen);
! 	name[namelen] = 0;
! 
  	subentry->filename = name;
  	subentry->local_sym_name = name;
  	subentry->symbols = 0;
  	subentry->strings = 0;
  	subentry->subfiles = 0;
! 	subentry->starting_offset = subfile_offset + sizeof hdr1;
  	subentry->superfile = library_entry;
  	subentry->library_flag = 0;
  	subentry->header_read_flag = 0;
  	subentry->just_syms_flag = 0;
  	subentry->chain = 0;
! 	subentry->total_size = member_length;
  
  	(*length_loc) = member_length;
  
--- 104,147 ----
  	     && hdr1.ar_name[namelen] != '/';
  	     namelen++);
  
! 	starting_offset = subfile_offset + sizeof hdr1;	
! 	content_length = member_length;
! #ifdef AR_EFMT1
! 	/*
! 	 * BSD 4.4 extended AR format: #1/<namelen>, with name as the
! 	 * first <namelen> bytes of the file
! 	 */
! 	if ((hdr1.ar_name[0]=='#') &&
! 	    (hdr1.ar_name[1]=='1') &&
! 	    (hdr1.ar_name[2]=='/') && 
! 	    (isdigit(hdr1.ar_name[3])))
! 	{
! 	    namelen = atoi (&hdr1.ar_name[3]);
! 	    name = (char *) xmalloc(namelen + 1);
! 	    read (desc, name, namelen);
! 	    name[namelen] = 0;
! 	    content_length -= namelen;
! 	    starting_offset += namelen;
! 	} else 
! #endif
! 	{
! 	    name = (char *) xmalloc(namelen + 1);
! 	    strncpy(name, hdr1.ar_name, namelen);
! 	    name[namelen] = 0;
! 	}
! 	
  	subentry->filename = name;
  	subentry->local_sym_name = name;
  	subentry->symbols = 0;
  	subentry->strings = 0;
  	subentry->subfiles = 0;
! 	subentry->starting_offset = starting_offset;
  	subentry->superfile = library_entry;
  	subentry->library_flag = 0;
  	subentry->header_read_flag = 0;
  	subentry->just_syms_flag = 0;
  	subentry->chain = 0;
! 	subentry->total_size = content_length;
  
  	(*length_loc) = member_length;
  




>Audit-Trail:
>Unformatted:

------------------------------------------------------------------------------