]> git.ipfire.org Git - thirdparty/gcc.git/commit
ubsan: d-demangle.c:214 signed integer overflow
authorAlan Modra <amodra@gmail.com>
Wed, 2 Sep 2020 02:53:47 +0000 (12:23 +0930)
committerAlan Modra <amodra@gmail.com>
Tue, 8 Sep 2020 01:15:15 +0000 (10:45 +0930)
commitfff56ce43844d376365c6e057e89bded070f717c
tree22740fc4c05e71669628a5b5d5094a6f3b90c76b
parenta995c40d03ea8829a7c05836c5f4ca557dddfae4
ubsan: d-demangle.c:214 signed integer overflow

Running the libiberty testsuite
./test-demangle < libiberty/testsuite/d-demangle-expected
libiberty/d-demangle.c:214:14: runtime error: signed integer overflow: 922337203 * 10 cannot be represented in type 'long int'

On looking at silencing ubsan, I found a real bug in dlang_number.
For a 32-bit long, some overflows won't be detected.  For example,
21474836480.  Why?  Well 214748364 * 10 is 0x7FFFFFF8 (no overflow so
far).  Adding 8 gives 0x80000000 (which does overflow but there is no
test for that overflow in the code).  Then multiplying 0x80000000 * 10
= 0x500000000 = 0 won't be caught by the multiplication overflow test.
The same holds for a 64-bit long using similarly crafted digit
sequences.

* d-demangle.c: Include limits.h.
(ULONG_MAX, UINT_MAX): Provide fall-back definition.
(dlang_number): Simplify and correct overflow test.  Only
write *ret on returning non-NULL.  Make "ret" an unsigned long*.
Only succeed for result of [0,UINT_MAX].
(dlang_decode_backref): Simplify and correct overflow test.
Only write *ret on returning non-NULL.  Only succeed for
result [1,MAX_LONG].
(dlang_backref): Remove now unnecessary range check.
(dlang_symbol_name_p): Likewise.
(string_need): Take a size_t n arg, and use size_t tem.
(string_append): Use size_t n.
(string_appendn, string_prependn): Take a size_t n arg.
(TEMPLATE_LENGTH_UNKNOWN): Define as -1UL.
(dlang_lname, dlang_parse_template): Take an unsigned long len
arg.
(dlang_symbol_backref, dlang_identifier, dlang_parse_integer),
(dlang_parse_integer, dlang_parse_string),
(dlang_parse_arrayliteral, dlang_parse_assocarray),
(dlang_parse_structlit, dlang_parse_tuple),
(dlang_template_symbol_param, dlang_template_args): Use
unsigned long variables.
* testsuite/d-demangle-expected: Add new tests.
libiberty/d-demangle.c
libiberty/testsuite/d-demangle-expected