In my last PPH change, I eliminated the redundancy in the preprocessor identifier lookaside table by removing the name of the identifier from the head of the macro value. This later led to a buffer overrun in libcpp/symtab.c cpp_lt_replay. The buffer was allocated based on the value string size, which is was no longer large enough to hold the definition string.
Split cpp_idents_used::max_length and cpp_lookaside::max_length into max_ident_len and max_value_len. In cpp_lt_replay, allocate the buffer based on the sum of max_ident_len and max_value_len. -- Lawrence Crowl
src.change
Description: Binary data
Index: gcc/cp/pph.c =================================================================== *** gcc/cp/pph.c (revision 170837) --- gcc/cp/pph.c (working copy) *************** pth_dump_identifiers (FILE *stream, cpp_ *** 502,509 **** { unsigned int idx, col = 1; ! fprintf (stream, "%u identifiers up to %u chars\n", ! identifiers->num_entries, identifiers->max_length); for (idx = 0; idx < identifiers->num_entries; ++idx) { cpp_ident_use *ident = identifiers->entries + idx; --- 502,510 ---- { unsigned int idx, col = 1; ! fprintf (stream, "%u identifiers up to %u chars, vals to %u chars\n", ! identifiers->num_entries, identifiers->max_ident_len, ! identifiers->max_value_len); for (idx = 0; idx < identifiers->num_entries; ++idx) { cpp_ident_use *ident = identifiers->entries + idx; *************** pth_save_identifiers (cpp_idents_used *i *** 793,814 **** unsigned int num_entries, id; num_entries = identifiers->num_entries; ! pph_output_uint (stream, identifiers->max_length); pph_output_uint (stream, num_entries); for ( id = 0; id < num_entries; ++id ) { cpp_ident_use *entry = identifiers->entries + id; ! gcc_assert (entry->ident_len <= identifiers->max_length); pph_output_string_with_length (stream, entry->ident_str, entry->ident_len); ! gcc_assert (entry->before_len <= identifiers->max_length); pph_output_string_with_length (stream, entry->before_str, entry->before_len); ! gcc_assert (entry->after_len <= identifiers->max_length); pph_output_string_with_length (stream, entry->after_str, entry->after_len); } --- 794,816 ---- unsigned int num_entries, id; num_entries = identifiers->num_entries; ! pph_output_uint (stream, identifiers->max_ident_len); ! pph_output_uint (stream, identifiers->max_value_len); pph_output_uint (stream, num_entries); for ( id = 0; id < num_entries; ++id ) { cpp_ident_use *entry = identifiers->entries + id; ! gcc_assert (entry->ident_len <= identifiers->max_ident_len); pph_output_string_with_length (stream, entry->ident_str, entry->ident_len); ! gcc_assert (entry->before_len <= identifiers->max_value_len); pph_output_string_with_length (stream, entry->before_str, entry->before_len); ! gcc_assert (entry->after_len <= identifiers->max_value_len); pph_output_string_with_length (stream, entry->after_str, entry->after_len); } *************** static void *** 1025,1035 **** pth_load_identifiers (cpp_idents_used *identifiers, pph_stream *stream) { unsigned int j; ! unsigned int max_length, num_entries; unsigned int ident_len, before_len, after_len; ! max_length = pph_input_uint (stream); ! identifiers->max_length = max_length; num_entries = pph_input_uint (stream); identifiers->num_entries = num_entries; identifiers->entries = XCNEWVEC (cpp_ident_use, num_entries); --- 1027,1039 ---- pth_load_identifiers (cpp_idents_used *identifiers, pph_stream *stream) { unsigned int j; ! unsigned int max_ident_len, max_value_len, num_entries; unsigned int ident_len, before_len, after_len; ! max_ident_len = pph_input_uint (stream); ! identifiers->max_ident_len = max_ident_len; ! max_value_len = pph_input_uint (stream); ! identifiers->max_value_len = max_value_len; num_entries = pph_input_uint (stream); identifiers->num_entries = num_entries; identifiers->entries = XCNEWVEC (cpp_ident_use, num_entries); Index: libcpp/symtab.c =================================================================== *** libcpp/symtab.c (revision 170837) --- libcpp/symtab.c (working copy) *************** cpp_lt_create (unsigned int order, unsig *** 411,417 **** table->sticky_order = order; table->active = 0; ! table->max_length = 0; table->strings = XCNEW (struct obstack); /* Strings need no alignment. */ _obstack_begin (table->strings, 0, 0, --- 411,418 ---- table->sticky_order = order; table->active = 0; ! table->max_ident_len = 0; ! table->max_value_len = 0; table->strings = XCNEW (struct obstack); /* Strings need no alignment. */ _obstack_begin (table->strings, 0, 0, *************** lt_macro_value (const char** string, cpp *** 556,563 **** const char *definition = lt_query_macro (reader, cpp_node); size_t macro_len = strlen (definition); *string = (const char *) obstack_copy0 (aside->strings, definition, macro_len); ! if (macro_len > aside->max_length) ! aside->max_length = macro_len; ++aside->macrovalue; return macro_len; } --- 557,564 ---- const char *definition = lt_query_macro (reader, cpp_node); size_t macro_len = strlen (definition); *string = (const char *) obstack_copy0 (aside->strings, definition, macro_len); ! if (macro_len > aside->max_value_len) ! aside->max_value_len = macro_len; ++aside->macrovalue; return macro_len; } *************** cpp_lt_capture (cpp_reader *reader) *** 606,612 **** /* Take the strings from the table and give to the summary. */ used.strings = aside->strings; aside->strings = NULL; ! used.max_length = aside->max_length; aside->iterations += slots; ++aside->empties; --- 607,614 ---- /* Take the strings from the table and give to the summary. */ used.strings = aside->strings; aside->strings = NULL; ! used.max_ident_len = aside->max_ident_len; ! used.max_value_len = aside->max_value_len; aside->iterations += slots; ++aside->empties; *************** cpp_lt_capture (cpp_reader *reader) *** 635,641 **** aside->active = 0; /* Create a new string table. */ ! aside->max_length = 0; aside->strings = XCNEW (struct obstack); /* Strings need no alignment. */ _obstack_begin (aside->strings, 0, 0, --- 637,644 ---- aside->active = 0; /* Create a new string table. */ ! aside->max_ident_len = 0; ! aside->max_value_len = 0; aside->strings = XCNEW (struct obstack); /* Strings need no alignment. */ _obstack_begin (aside->strings, 0, 0, *************** cpp_lt_replay (cpp_reader *reader, cpp_i *** 815,821 **** unsigned int i; unsigned int num_entries = identifiers->num_entries; cpp_ident_use *entries = identifiers->entries; ! char *buffer = XCNEWVEC (char, identifiers->max_length + 1); /* Prevent the lexer from invalidating the tokens we've read so far. */ reader->keep_tokens++; --- 818,825 ---- unsigned int i; unsigned int num_entries = identifiers->num_entries; cpp_ident_use *entries = identifiers->entries; ! char *buffer = XCNEWVEC (char, identifiers->max_ident_len ! + identifiers->max_value_len + 1); /* Prevent the lexer from invalidating the tokens we've read so far. */ reader->keep_tokens++; *************** lt_lookup (cpp_reader *reader, *** 968,980 **** ++aside->active; entries[index].node = node; entries[index].hash = hash; ! if (length > aside->max_length) ! aside->max_length = length; /* Capture any macro value. */ if (cpp_node->type == NT_MACRO) entries[index].length = lt_macro_value ! (&entries[index].value, aside, reader, cpp_node); /* else .value and .length are still zero from initialization. */ /* Check table load factor. */ --- 972,984 ---- ++aside->active; entries[index].node = node; entries[index].hash = hash; ! if (length > aside->max_ident_len) ! aside->max_ident_len = length; /* Capture any macro value. */ if (cpp_node->type == NT_MACRO) entries[index].length = lt_macro_value ! (&entries[index].value, aside, reader, cpp_node); /* else .value and .length are still zero from initialization. */ /* Check table load factor. */ Index: libcpp/include/symtab.h =================================================================== *** libcpp/include/symtab.h (revision 170837) --- libcpp/include/symtab.h (working copy) *************** typedef struct GTY(()) cpp_ident_use *** 120,126 **** typedef struct GTY(()) cpp_idents_used { ! unsigned int max_length; unsigned int num_entries; cpp_ident_use *entries; struct obstack * GTY((skip)) strings; --- 120,127 ---- typedef struct GTY(()) cpp_idents_used { ! unsigned int max_ident_len; ! unsigned int max_value_len; unsigned int num_entries; cpp_ident_use *entries; struct obstack * GTY((skip)) strings; Index: libcpp/internal.h =================================================================== *** libcpp/internal.h (revision 170837) --- libcpp/internal.h (working copy) *************** struct cpp_lookaside { *** 341,347 **** unsigned int sticky_order; /* For resizing when capturing the entries. */ unsigned int active; /* Number of active entries. */ struct obstack *strings; /* For macro value storage. */ ! unsigned int max_length; /* Largest string encountered. */ /* Table usage statistics. */ unsigned long long searches; /* Number of calls to lt_lookup. */ --- 341,348 ---- unsigned int sticky_order; /* For resizing when capturing the entries. */ unsigned int active; /* Number of active entries. */ struct obstack *strings; /* For macro value storage. */ ! unsigned int max_ident_len; /* Largest identifier encountered. */ ! unsigned int max_value_len; /* Largest macro value encountered. */ /* Table usage statistics. */ unsigned long long searches; /* Number of calls to lt_lookup. */