PR24236, Heap buffer overflow in _bfd_archive_64_bit_slurp_armap
PR 24236
* archive64.c (_bfd_archive_64_bit_slurp_armap): Move code adding
sentinel NUL to string buffer nearer to loop where it is used.
Don't go past sentinel when scanning strings, and don't write
NUL again.
* archive.c (do_slurp_coff_armap): Simplify string handling to
archive64.c style.
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 72c87c7..e39bb12 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,13 @@
+2019-02-20 Alan Modra <amodra@gmail.com>
+
+ PR 24236
+ * archive64.c (_bfd_archive_64_bit_slurp_armap): Move code adding
+ sentinel NUL to string buffer nearer to loop where it is used.
+ Don't go past sentinel when scanning strings, and don't write
+ NUL again.
+ * archive.c (do_slurp_coff_armap): Simplify string handling to
+ archive64.c style.
+
2019-02-19 Alan Modra <amodra@gmail.com>
PR 24235
diff --git a/bfd/archive.c b/bfd/archive.c
index d2d9b72..68a92a3 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -1012,6 +1012,7 @@
int *raw_armap, *rawptr;
struct artdata *ardata = bfd_ardata (abfd);
char *stringbase;
+ char *stringend;
bfd_size_type stringsize;
bfd_size_type parsed_size;
carsym *carsyms;
@@ -1071,22 +1072,18 @@
}
/* OK, build the carsyms. */
- for (i = 0; i < nsymz && stringsize > 0; i++)
+ stringend = stringbase + stringsize;
+ *stringend = 0;
+ for (i = 0; i < nsymz; i++)
{
- bfd_size_type len;
-
rawptr = raw_armap + i;
carsyms->file_offset = swap ((bfd_byte *) rawptr);
carsyms->name = stringbase;
- /* PR 17512: file: 4a1d50c1. */
- len = strnlen (stringbase, stringsize);
- if (len < stringsize)
- len ++;
- stringbase += len;
- stringsize -= len;
+ stringbase += strlen (stringbase);
+ if (stringbase != stringend)
+ ++stringbase;
carsyms++;
}
- *stringbase = 0;
ardata->symdef_count = nsymz;
ardata->first_file_filepos = bfd_tell (abfd);
diff --git a/bfd/archive64.c b/bfd/archive64.c
index 312bf82..42f6ed9 100644
--- a/bfd/archive64.c
+++ b/bfd/archive64.c
@@ -100,8 +100,6 @@
return FALSE;
carsyms = ardata->symdefs;
stringbase = ((char *) ardata->symdefs) + carsym_size;
- stringbase[stringsize] = 0;
- stringend = stringbase + stringsize;
raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize);
if (raw_armap == NULL)
@@ -115,15 +113,17 @@
goto release_raw_armap;
}
+ stringend = stringbase + stringsize;
+ *stringend = 0;
for (i = 0; i < nsymz; i++)
{
carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
carsyms->name = stringbase;
- if (stringbase < stringend)
- stringbase += strlen (stringbase) + 1;
+ stringbase += strlen (stringbase);
+ if (stringbase != stringend)
+ ++stringbase;
++carsyms;
}
- *stringbase = '\0';
ardata->symdef_count = nsymz;
ardata->first_file_filepos = bfd_tell (abfd);