https://sourceware.org/bugzilla/show_bug.cgi?id=34901
Bug ID: 34901
Summary: bfd: archive member name "/x1" is accepted as
extended-name index 0; in a thin archive it resolves
to a different member's file
Product: binutils
Version: 2.48 (HEAD)
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: binutils
Assignee: unassigned at sourceware dot org
Reporter: martin.mirchev at u dot nus.edu
Target Milestone: ---
get_extended_arelt_filename() (bfd/archive.c) parses the index after '/' with
strtol() and checks only errno and the upper bound:
485 table_index = strtol (name + 1, (char **) &endp, 10);
486 if (errno != 0 || table_index >= bfd_ardata
(arch)->extended_names_size)
For a name such as "/x1", strtol consumes nothing, returns 0 and leaves errno
at 0, so the member takes extended_names[0], the first member's name. In a thin
archive that name is the path that gets opened (open_nested_file,
archive.c:760), so tools silently use a different file than the header
describes. Out-of-range indices ("/92", "/-2") are already rejected as
"malformed archive".
Tested on master 1ec1cee48577c7b1960ddce5a6054b3f9fab6ef5. Release: Ubuntu
22.04 gcc 11 -g -O2. ASan: -O1 -g -fsanitize=address,undefined.
Reproducer (attached mk-thin.sh): builds sub/one.o (defines one), two.o
(defines two) and main.o (calls two), runs "ar rcsT lib.a sub/one.o two.o",
then copies lib.a to lib-bad.a with the second member's name "/11" changed to
"/x1" (one byte).
$ ar t lib.a -> sub/one.o two.o
$ ar t lib-bad.a -> sub/one.o sub/one.o
$ nm lib-bad.a -> member 2 is listed as sub/one.o with symbol
"one"
$ ld -o p main.o lib.a (exit 0)
$ ld -o p main.o lib-bad.a
main.c:(.text+0x9): undefined reference to `two' (exit 1)
$ ld -o q main.o --whole-archive lib-bad.a
one.c:(.text+0x0): multiple definition of `one'; sub/one.o:one.c:(.text+0x0):
first defined here
(exit 1)
ld follows the armap entry for "two" to member 2 and loads sub/one.o instead
of two.o. If the substituted file also defines the requested symbols, the link
succeeds with no diagnostic. ASan and valgrind are clean: this is a parsing
bug, not a memory error.
The name should be rejected as a malformed archive unless at least one digit
follows the '/' (i.e. check that strtol consumed something).
This issue was found by an LLM-Enhanced Static Analysis Engine and verified
manually.
--
You are receiving this mail because:
You are on the CC list for the bug.