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:
------------------------------------------------------------------------------