check_ar_members() builds the "ar_path[member]" string in a heap buffer
full_path allocated with malloc(). When a member name does not fit, the
grow path reallocated current_path instead of full_path:
char *new_path = realloc (current_path, path_size);
...
free (full_path);
On the first archive member current_path still points at ar_path, which
is the caller's path string (an argv[] entry or the getdelim() stdin
buffer), not the malloc'd full_path. Reallocating that non-owned
pointer is invalid -- it is either not heap-allocated at all or aliases
a buffer owned elsewhere -- and the following free(full_path) then
releases the real buffer, corrupting the heap. It is reachable with
eu-elfclassify --elf-archive FILE
on an archive whose first member name is longer than the initial guess
(2 * strlen(ar_path) + 24).
Grow full_path itself and let realloc() release the old block.
Signed-off-by: Matej Smycka <[email protected]>
---
src/elfclassify.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/elfclassify.c b/src/elfclassify.c
index 80a376a4..63caebdc 100644
--- a/src/elfclassify.c
+++ b/src/elfclassify.c
@@ -858,7 +858,7 @@ check_ar_members (void)
if (path_size < strlen (ar_path) + strlen (ar_name) + 3)
{
path_size = strlen (ar_path) + strlen (ar_name) + 24;
- char *new_path = realloc (current_path, path_size);
+ char *new_path = realloc (full_path, path_size);
if (new_path == NULL)
{
issue (ENOMEM, N_("allocating a member string name storage"));
@@ -867,7 +867,6 @@ check_ar_members (void)
break;
}
- free (full_path);
full_path = new_path;
}
--
2.47.3