summaryrefslogtreecommitdiff
path: root/lto-plugin
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2020-09-09 15:54:20 +0100
committerNick Clifton <nickc@redhat.com>2020-09-09 15:54:20 +0100
commitad2a37157d3476dffb3baf93ca5001c9f6c44bda (patch)
tree8d0820d582070a50354f4c873fb0704914e9c0b7 /lto-plugin
parent5d3c12e4184a5e8d0cfda41e90bb2fcd98e7ddae (diff)
If the lto plugin encounters a file with multiple symbol sections, each of which also has a v1 symbol extension section[1] then it will attempt to read the extension data for *every* symbol from each of the extension sections. This results in reading off the end of a buffer with the associated memory corruption that that entails. This patch fixes that problem.
2020-09-09 Nick Clifton <nickc@redhat.com> * lto-plugin.c (struct plugin_symtab): Add last_sym field. (parse_symtab_extension): Only read as many entries as are available in the buffer. Store the data read into the symbol table indexed from last_sym. Increment last_sym.
Diffstat (limited to 'lto-plugin')
-rw-r--r--lto-plugin/lto-plugin.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
index a65c2801b9b..6f67552d075 100644
--- a/lto-plugin/lto-plugin.c
+++ b/lto-plugin/lto-plugin.c
@@ -115,6 +115,7 @@ struct sym_aux
struct plugin_symtab
{
int nsyms;
+ int last_sym;
struct sym_aux *aux;
struct ld_plugin_symbol *syms;
unsigned long long id;
@@ -382,19 +383,30 @@ translate (char *data, char *end, struct plugin_symtab *out)
static void
parse_symtab_extension (char *data, char *end, struct plugin_symtab *out)
{
- unsigned i;
+ unsigned long i;
+ unsigned char version;
+
+ if (data >= end)
+ /* FIXME: Issue an error ? */
+ return;
- unsigned char version = *data;
+ version = *data;
data++;
+ if (version != 1)
+ return;
+
/* Version 1 contains the following data per entry:
- symbol_type
- section_kind
. */
- if (version == 1)
- for (i = 0; i < out->nsyms; i++)
- data = parse_table_entry_extension (data, &out->syms[i]);
+ unsigned long nsyms = (end - data) / 2;
+
+ for (i = 0; i < nsyms; i++)
+ data = parse_table_entry_extension (data, out->syms + i + out->last_sym);
+
+ out->last_sym += nsyms;
}
/* Free all memory that is no longer needed after writing the symbol
@@ -1172,9 +1184,12 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
/* Parsing symtab extension should be done only for add_symbols_v2 and
later versions. */
if (!errmsg && add_symbols_v2 != NULL)
- errmsg = simple_object_find_sections (obj.objfile,
- process_symtab_extension,
- &obj, &err);
+ {
+ obj.out->last_sym = 0;
+ errmsg = simple_object_find_sections (obj.objfile,
+ process_symtab_extension,
+ &obj, &err);
+ }
}
if (!obj.objfile || errmsg)