summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorAaron Merey <[email protected]>2025-08-10 20:26:35 -0400
committerAaron Merey <[email protected]>2025-08-20 10:26:25 -0400
commitcc459edfe10f2e76b82cccb8543c2f264f478209 (patch)
treeee797c318a8d942a8f42e55ebb32f22fa9b052e3 /tests
parent36602dbd840532b9ca6d31c1612bf1d539241e7a (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.c70
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