libiberty: Fix some demangler crashes caused by reading past end of input.

In various situations the cplus_demangle () function could read past the
end of input causing crashes. Add checks in various places to not advance
the demangle string location and fail early when end of string is reached.
Add various examples of input strings to the testsuite that would crash
test-demangle before the fixes.

Found by using the American Fuzzy Lop (afl) fuzzer.

libiberty/ChangeLog:

       * cplus-dem.c (demangle_signature): After 'H', template function,
       no success and don't advance position if end of string reached.
       (demangle_template): After 'z', template name, return zero on
       premature end of string.
       (gnu_special): Guard strchr against searching for zero characters.
       (do_type): If member, only advance mangled string when 'F' found.
       * testsuite/demangle-expected: Add examples of strings that could
       crash the demangler by reading past end of input.

From-SVN: r242450
This commit is contained in:
Mark Wielaard 2016-11-15 19:31:50 +00:00 committed by Mark Wielaard
parent 6f959acccb
commit 0d0bfbf47c
3 changed files with 41 additions and 4 deletions

View File

@ -1,3 +1,14 @@
2016-11-14 Mark Wielaard <mark@klomp.org>
* cplus-dem.c (demangle_signature): After 'H', template function,
no success and don't advance position if end of string reached.
(demangle_template): After 'z', template name, return zero on
premature end of string.
(gnu_special): Guard strchr against searching for zero characters.
(do_type): If member, only advance mangled string when 'F' found.
* testsuite/demangle-expected: Add examples of strings that could
crash the demangler by reading past end of input.
2016-11-06 Mark Wielaard <mark@klomp.org>
* configure.ac (ac_libiberty_warn_cflags): Add -Wshadow=local.

View File

@ -1654,7 +1654,10 @@ demangle_signature (struct work_stuff *work,
0);
if (!(work->constructor & 1))
expect_return_type = 1;
(*mangled)++;
if (!**mangled)
success = 0;
else
(*mangled)++;
break;
}
/* fall through */
@ -2133,6 +2136,8 @@ demangle_template (struct work_stuff *work, const char **mangled,
{
int idx;
(*mangled)++;
if (**mangled == '\0')
return (0);
(*mangled)++;
idx = consume_count_with_underscores (mangled);
@ -2977,7 +2982,7 @@ gnu_special (struct work_stuff *work, const char **mangled, string *declp)
int success = 1;
const char *p;
if ((*mangled)[0] == '_'
if ((*mangled)[0] == '_' && (*mangled)[1] != '\0'
&& strchr (cplus_markers, (*mangled)[1]) != NULL
&& (*mangled)[2] == '_')
{
@ -2991,7 +2996,7 @@ gnu_special (struct work_stuff *work, const char **mangled, string *declp)
&& (*mangled)[3] == 't'
&& (*mangled)[4] == '_')
|| ((*mangled)[1] == 'v'
&& (*mangled)[2] == 't'
&& (*mangled)[2] == 't' && (*mangled)[3] != '\0'
&& strchr (cplus_markers, (*mangled)[3]) != NULL)))
{
/* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
@ -3761,11 +3766,12 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
break;
}
if (*(*mangled)++ != 'F')
if (*(*mangled) != 'F')
{
success = 0;
break;
}
(*mangled)++;
}
if ((member && !demangle_nested_args (work, mangled, &decl))
|| **mangled != '_')

View File

@ -4606,3 +4606,23 @@ void f<void, int, false>(void (*)(int) noexcept)
_Z1fIvJiELb0EEvPDwiEFT_DpT0_E
void f<void, int, false>(void (*)(int) throw(int))
# Could crash
_
_
# Could crash
_vt
_vt
# Could crash
_$_1Acitz
_$_1Acitz
# Could crash
_$_H1R
_$_H1R
# Could crash
_Q8ccQ4M2e.
_Q8ccQ4M2e.