diff options
| author | Aaron Merey <[email protected]> | 2025-08-10 20:26:35 -0400 |
|---|---|---|
| committer | Aaron Merey <[email protected]> | 2025-08-20 10:26:25 -0400 |
| commit | cc459edfe10f2e76b82cccb8543c2f264f478209 (patch) | |
| tree | ee797c318a8d942a8f42e55ebb32f22fa9b052e3 /tests | |
| parent | 36602dbd840532b9ca6d31c1612bf1d539241e7a (diff) | |
elf_getarhdr: Replace per-archive Elf_Arhdr storage with per-member storageupstream/users/amerey/try-arhdr
Currently each archive descriptor maintains a single Elf_Arhdr for the
current archive member (as determined by elf_next or elf_rand) which is
returned by elf_getarhdr.
A single per-archive Elf_Arhdr is not ideal since elf_next and elf_rand
can invalidate an archive member's reference to its own Elf_Arhdr.
Avoid this possible invalidation by storing each Elf_Arhdr in its
archive member descriptor.
The existing Elf_Arhdr parsing and storage in the archive descriptor
internal state is left mostly untouched. When an archive member is
created with elf_begin it is given its own copy of its Elf_Arhdr from
the archive descriptor.
Also update tests/arextract.c with verification that each Elf_Arhdr
is distinct and remains valid after calls to elf_next that would
have previously invalidated the Elf_Arhdr.
Signed-off-by: Aaron Merey <[email protected]>
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/arextract.c | 70 |
1 files changed, 62 insertions, 8 deletions
diff --git a/tests/arextract.c b/tests/arextract.c index 936d7f55..fced8827 100644 --- a/tests/arextract.c +++ b/tests/arextract.c @@ -27,6 +27,13 @@ #include <unistd.h> #include <system.h> +typedef struct hdr_node { + Elf *elf; + Elf_Arhdr *hdr; + struct hdr_node *next; +} hdr_node; + +hdr_node *hdr_list = NULL; int main (int argc, char *argv[]) @@ -80,6 +87,27 @@ main (int argc, char *argv[]) exit (1); } + /* Keep a list of subelfs and their Elf_Arhdr. This is used to + verifiy that each archive member descriptor stores its own + Elf_Ahdr as opposed to the archive descriptor storing one + Elf_Ahdr at a time for all archive members. */ + hdr_node *node = calloc (1, sizeof (hdr_node)); + if (node == NULL) + { + printf ("calloc failed: %s\n", strerror (errno)); + exit (1); + } + node->elf = subelf; + node->hdr = arhdr; + + if (hdr_list != NULL) + { + node->next = hdr_list; + hdr_list = node; + } + else + hdr_list = node; + if (strcmp (arhdr->ar_name, argv[2]) == 0) { int outfd; @@ -128,8 +156,40 @@ Failed to get base address for the archive element: %s\n", exit (1); } - /* Close the descriptors. */ - if (elf_end (subelf) != 0 || elf_end (elf) != 0) + /* Verify each subelf descriptor contains a unique copy of its arhdr + and then close each subelf descriptor. */ + hdr_node *cur; + while ((cur = hdr_list) != NULL) + { + /* Verify that arhdr names are unique. */ + for (hdr_node *n = cur->next; n != NULL; n = n->next) + { + if (strcmp (cur->hdr->ar_name, n->hdr->ar_name) == 0) + { + puts ("Duplicate ar_name"); + exit (1); + } + + if (strcmp (cur->hdr->ar_rawname, n->hdr->ar_rawname) == 0) + { + puts ("Duplicate ar_rawname"); + exit (1); + } + } + + if (elf_end (cur->elf) != 0) + { + printf ("Error while freeing subELF descriptor: %s\n", + elf_errmsg (-1)); + exit (1); + } + + hdr_list = cur->next; + free (cur); + } + + /* Close the archive descriptor. */ + if (elf_end (elf) != 0) { printf ("Freeing ELF descriptors failed: %s", elf_errmsg (-1)); exit (1); @@ -144,12 +204,6 @@ Failed to get base address for the archive element: %s\n", /* Get next archive element. */ cmd = elf_next (subelf); - if (elf_end (subelf) != 0) - { - printf ("error while freeing sub-ELF descriptor: %s\n", - elf_errmsg (-1)); - exit (1); - } } /* When we reach this point we haven't found the given file in the |
