diff options
author | Tristan Gingold <tgingold@free.fr> | 2023-05-31 11:20:55 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2023-05-31 11:20:55 +0100 |
commit | 768d1d879be2d134e049521f28d4d5e03b69bafc (patch) | |
tree | 0f3eb8bab0eac4aa5909bef7aaf590ab138c4c25 /bfd/coffcode.h | |
parent | a15891aaea006d06066573449efbda353dd2863e (diff) | |
download | binutils-768d1d879be2d134e049521f28d4d5e03b69bafc.zip binutils-768d1d879be2d134e049521f28d4d5e03b69bafc.tar.gz binutils-768d1d879be2d134e049521f28d4d5e03b69bafc.tar.bz2 |
pe/coff - add support for base64 encoded long section names
PR 30444
* coffcode.h (coff_write_object_contents): Handle base64 encoding on PE. Also check for too large string table.
* coffgen.c (extract_long_section_name): New function extracted from ... (make_a_section_from_file): ... here. Add support for base64 long section names. (decode_base64): New function.
Diffstat (limited to 'bfd/coffcode.h')
-rw-r--r-- | bfd/coffcode.h | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/bfd/coffcode.h b/bfd/coffcode.h index e52d652..4756271 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -3568,18 +3568,55 @@ coff_write_object_contents (bfd * abfd) len = strlen (current->name); if (len > SCNNMLEN) { - /* The s_name field is defined to be NUL-padded but need not be - NUL-terminated. We use a temporary buffer so that we can still - sprintf all eight chars without splatting a terminating NUL - over the first byte of the following member (s_paddr). */ - /* PR 21096: The +20 is to stop a bogus warning from gcc7 about - a possible buffer overflow. */ - char s_name_buf[SCNNMLEN + 1 + 20]; /* An inherent limitation of the /nnnnnnn notation used to indicate the offset of the long name in the string table is that we cannot address entries beyone the ten million byte boundary. */ - if (string_size >= 10000000) + if (string_size < 10000000) + { + /* The s_name field is defined to be NUL-padded but need not + be NUL-terminated. We use a temporary buffer so that we + can still sprintf all eight chars without splatting a + terminating NUL over the first byte of the following + member (s_paddr). */ + /* PR 21096: The +20 is to stop a bogus warning from gcc7 + about a possible buffer overflow. */ + char s_name_buf[SCNNMLEN + 1 + 20]; + + /* We do not need to use snprintf here as we have already + verified that string_size is not too big, plus we have + an overlarge buffer, just in case. */ + sprintf (s_name_buf, "/%lu", (unsigned long) string_size); + /* Then strncpy takes care of any padding for us. */ + strncpy (section.s_name, s_name_buf, SCNNMLEN); + } + else +#ifdef COFF_WITH_PE + { + /* PE use a base 64 encoding for long section names whose + index is very large. But contrary to RFC 4648, there is + no padding: 6 characters must be generated. */ + static const char base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + unsigned long off = string_size; + unsigned i; + + section.s_name[0] = '/'; + section.s_name[1] = '/'; + for (i = SCNNMLEN - 1; i >= 2; i--) + { + section.s_name[i] = base64[off & 0x3f]; + off >>= 6; + } + } +#endif + if (string_size > 0xffffffffUL - (len + 1) +#ifndef COFF_WITH_PE + || string_size >= 10000000 +#endif + ) { bfd_set_error (bfd_error_file_too_big); _bfd_error_handler @@ -3589,12 +3626,6 @@ coff_write_object_contents (bfd * abfd) return false; } - /* We do not need to use snprintf here as we have already verfied - that string_size is not too big, plus we have an overlarge - buffer, just in case. */ - sprintf (s_name_buf, "/%lu", (unsigned long) string_size); - /* Then strncpy takes care of any padding for us. */ - strncpy (section.s_name, s_name_buf, SCNNMLEN); string_size += len + 1; long_section_names = true; } |