* cplus-dem.c (ada_demangle): Correctly calculate the demangled size by using two passes.
Fixes #92453 --- libiberty/ChangeLog | 5 + libiberty/cplus-dem.c | 408 +++++++++++++++++++++++------------------- 2 files changed, 226 insertions(+), 187 deletions(-) diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 95cb1525f2..085b7b3fbf 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,8 @@ +2019-11-16 Tim Ruehsen <tim.rueh...@gmx.de> + + * cplus-dem.c (ada_demangle): Correctly calculate the demangled + size by using two passes. Fixes #92453. + 2019-08-08 Martin Liska <mli...@suse.cz> PR bootstrap/91352 diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c index a39e2bf2ed..be76e691b0 100644 --- a/libiberty/cplus-dem.c +++ b/libiberty/cplus-dem.c @@ -230,7 +230,7 @@ rust_demangle (const char *mangled, int options) char * ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) { - int len0; + int len0 = 0, run; const char* p; char *d; char *demangled = NULL; @@ -243,236 +243,270 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) if (!ISLOWER (mangled[0])) goto unknown; - /* Most of the demangling will trivially remove chars. Operator names - may add one char but because they are always preceeded by '__' which is - replaced by '.', they eventually never expand the size. - A few special names such as '___elabs' add a few chars (at most 7), but - they occur only once. */ - len0 = strlen (mangled) + 7 + 1; - demangled = XNEWVEC (char, len0); - - d = demangled; - p = mangled; - while (1) + for (run = 0; run <= 1; run++) { - /* An entity names is expected. */ - if (ISLOWER (*p)) + if (run == 1) { - /* An identifier, which is always lower case. */ - do - *d++ = *p++; - while (ISLOWER(*p) || ISDIGIT (*p) - || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1])))); + demangled = XNEWVEC (char, len0 + 1); } - else if (p[0] == 'O') + + p = mangled; + d = demangled; + + while (1) { - /* An operator name. */ - static const char * const operators[][2] = - {{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"}, - {"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"}, - {"Oxor", "xor"}, {"Oeq", "="}, {"One", "/="}, - {"Olt", "<"}, {"Ole", "<="}, {"Ogt", ">"}, - {"Oge", ">="}, {"Oadd", "+"}, {"Osubtract", "-"}, - {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"}, - {"Oexpon", "**"}, {NULL, NULL}}; - int k; - - for (k = 0; operators[k][0] != NULL; k++) + /* An entity names is expected. */ + if (ISLOWER (*p)) { - size_t slen = strlen (operators[k][0]); - if (strncmp (p, operators[k][0], slen) == 0) + /* An identifier, which is always lower case. */ + do + run ? (*d++ = *p++) : (p++, len0++); + while (ISLOWER (*p) || ISDIGIT (*p) + || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1])))); + } + else if (p[0] == 'O') + { + /* An operator name. */ + static const char * const operators[][2] ={ + {"Oabs", "abs"}, + {"Oand", "and"}, + {"Omod", "mod"}, + {"Onot", "not"}, + {"Oor", "or"}, + {"Orem", "rem"}, + {"Oxor", "xor"}, + {"Oeq", "="}, + {"One", "/="}, + {"Olt", "<"}, + {"Ole", "<="}, + {"Ogt", ">"}, + {"Oge", ">="}, + {"Oadd", "+"}, + {"Osubtract", "-"}, + {"Oconcat", "&"}, + {"Omultiply", "*"}, + {"Odivide", "/"}, + {"Oexpon", "**"}, + {NULL, NULL}}; + int k; + + for (k = 0; operators[k][0] != NULL; k++) { - p += slen; - slen = strlen (operators[k][1]); - *d++ = '"'; - memcpy (d, operators[k][1], slen); - d += slen; - *d++ = '"'; - break; + size_t slen = strlen (operators[k][0]); + if (strncmp (p, operators[k][0], slen) == 0) + { + p += slen; + slen = strlen (operators[k][1]); + if (run) + { + *d++ = '"'; + memcpy (d, operators[k][1], slen); + d += slen; + *d++ = '"'; + } + else + len0 += slen + 2; + break; + } } + /* Operator not found. */ + if (operators[k][0] == NULL) + goto unknown; } - /* Operator not found. */ - if (operators[k][0] == NULL) - goto unknown; - } - else - { - /* Not a GNAT encoding. */ - goto unknown; - } - - /* The name can be directly followed by some uppercase letters. */ - if (p[0] == 'T' && p[1] == 'K') - { - /* Task stuff. */ - if (p[2] == 'B' && p[3] == 0) + else { - /* Subprogram for task body. */ - break; + /* Not a GNAT encoding. */ + goto unknown; } - else if (p[2] == '_' && p[3] == '_') + + /* The name can be directly followed by some uppercase letters. */ + if (p[0] == 'T' && p[1] == 'K') { - /* Inner declarations in a task. */ - p += 4; - *d++ = '.'; - continue; + /* Task stuff. */ + if (p[2] == 'B' && p[3] == 0) + { + /* Subprogram for task body. */ + break; + } + else if (p[2] == '_' && p[3] == '_') + { + /* Inner declarations in a task. */ + p += 4; + run ? *d++ = '.' : len0++; + continue; + } + else + goto unknown; } - else - goto unknown; - } - if (p[0] == 'E' && p[1] == 0) - { - /* Exception name. */ - goto unknown; - } - if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0) - { - /* Protected type subprogram. */ - break; - } - if ((*p == 'N' || *p == 'S') && p[1] == 0) - { - /* Enumerated type name table. */ - goto unknown; - } - if (p[0] == 'X') - { - /* Body nested. */ - p++; - while (p[0] == 'n' || p[0] == 'b') - p++; - } - if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0)) - { - /* Stream operations. */ - const char *name; - switch (p[1]) + if (p[0] == 'E' && p[1] == 0) { - case 'R': - name = "'Read"; - break; - case 'W': - name = "'Write"; - break; - case 'I': - name = "'Input"; - break; - case 'O': - name = "'Output"; - break; - default: + /* Exception name. */ goto unknown; } - p += 2; - strcpy (d, name); - d += strlen (name); - } - else if (p[0] == 'D') - { - /* Controlled type operation. */ - const char *name; - switch (p[1]) + if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0) { - case 'F': - name = ".Finalize"; - break; - case 'A': - name = ".Adjust"; + /* Protected type subprogram. */ break; - default: + } + if ((*p == 'N' || *p == 'S') && p[1] == 0) + { + /* Enumerated type name table. */ goto unknown; } - strcpy (d, name); - d += strlen (name); - break; - } - - if (p[0] == '_') - { - /* Separator. */ - if (p[1] == '_') + if (p[0] == 'X') + { + /* Body nested. */ + p++; + while (p[0] == 'n' || p[0] == 'b') + p++; + } + if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0)) { - /* Standard separator. Handled first. */ + /* Stream operations. */ + const char *name; + switch (p[1]) + { + case 'R': + name = "'Read"; + break; + case 'W': + name = "'Write"; + break; + case 'I': + name = "'Input"; + break; + case 'O': + name = "'Output"; + break; + default: + goto unknown; + } p += 2; + if (run) + { + strcpy (d, name); + d += strlen (name); + } + else + len0 += strlen (name); + } + else if (p[0] == 'D') + { + /* Controlled type operation. */ + const char *name; + switch (p[1]) + { + case 'F': + name = ".Finalize"; + break; + case 'A': + name = ".Adjust"; + break; + default: + goto unknown; + } + if (run) + { + strcpy (d, name); + d += strlen (name); + } + else + len0 += strlen (name); + break; + } - if (ISDIGIT (*p)) + if (p[0] == '_') + { + /* Separator. */ + if (p[1] == '_') { - /* Overloading number. */ - do - p++; - while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1]))); - if (*p == 'X') + /* Standard separator. Handled first. */ + p += 2; + + if (ISDIGIT (*p)) { - p++; - while (p[0] == 'n' || p[0] == 'b') + /* Overloading number. */ + do p++; + while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1]))); + if (*p == 'X') + { + p++; + while (p[0] == 'n' || p[0] == 'b') + p++; + } } - } - else if (p[0] == '_' && p[1] != '_') - { - /* Special names. */ - static const char * const special[][2] = { - { "_elabb", "'Elab_Body" }, - { "_elabs", "'Elab_Spec" }, - { "_size", "'Size" }, - { "_alignment", "'Alignment" }, - { "_assign", ".\":=\"" }, - { NULL, NULL } - }; - int k; - - for (k = 0; special[k][0] != NULL; k++) + else if (p[0] == '_' && p[1] != '_') { - size_t slen = strlen (special[k][0]); - if (strncmp (p, special[k][0], slen) == 0) + /* Special names. */ + static const char * const special[][2] = { + { "_elabb", "'Elab_Body"}, + { "_elabs", "'Elab_Spec"}, + { "_size", "'Size"}, + { "_alignment", "'Alignment"}, + { "_assign", ".\":=\""}, + { NULL, NULL} + }; + int k; + + for (k = 0; special[k][0] != NULL; k++) { - p += slen; - slen = strlen (special[k][1]); - memcpy (d, special[k][1], slen); - d += slen; - break; + size_t slen = strlen (special[k][0]); + if (strncmp (p, special[k][0], slen) == 0) + { + p += slen; + slen = strlen (special[k][1]); + if (run) + { + memcpy (d, special[k][1], slen); + d += slen; + } + else + len0 += slen; + break; + } } + if (special[k][0] != NULL) + break; + else + goto unknown; + } + else + { + run ? *d++ = '.' : len0++; + continue; } - if (special[k][0] != NULL) + } + else if (p[1] == 'B' || p[1] == 'E') + { + /* Entry Body or barrier Evaluation. */ + p += 2; + while (ISDIGIT (*p)) + p++; + if (p[0] == 's' && p[1] == 0) break; else goto unknown; } else - { - *d++ = '.'; - continue; - } + goto unknown; } - else if (p[1] == 'B' || p[1] == 'E') + + if (p[0] == '.' && ISDIGIT (p[1])) { - /* Entry Body or barrier Evaluation. */ + /* Nested subprogram. */ p += 2; while (ISDIGIT (*p)) p++; - if (p[0] == 's' && p[1] == 0) - break; - else - goto unknown; + } + if (*p == 0) + { + /* End of mangled name. */ + break; } else goto unknown; } - - if (p[0] == '.' && ISDIGIT (p[1])) - { - /* Nested subprogram. */ - p += 2; - while (ISDIGIT (*p)) - p++; - } - if (*p == 0) - { - /* End of mangled name. */ - break; - } - else - goto unknown; } *d = 0; return demangled; -- 2.24.0