From a4553534dfcccf992d30307a8bdbb5405ecd01f7 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 12 Feb 2019 01:09:31 +0000 Subject: linemap_line_start: protect against location_t overflow (PR lto/88147) PR lto/88147 reports an assertion failure due to a bogus location_t value when adding a line to a pre-existing line map, when there's a large difference between the two line numbers. For some "large differences", this leads to a location_t value that exceeds LINE_MAP_MAX_LOCATION, in which case linemap_line_start returns 0. This isn't ideal, but at least should lead to safe degradation of location information. However, if the difference is very large, it's possible for the line number offset (relative to the start of the map) to be sufficiently large that overflow occurs when left-shifted by the column-bits, and hence the check against the LINE_MAP_MAX_LOCATION limit fails, leading to a seemingly-valid location_t value, but encoding the wrong location. This triggers the assertion failure: linemap_assert (SOURCE_LINE (map, r) == to_line); The fix (thanks to Martin) is to check for overflow when determining whether to reuse an existing map, and to not reuse it if it would occur. gcc/ChangeLog: David Malcolm PR lto/88147 * input.c (selftest::test_line_offset_overflow): New selftest. (selftest::input_c_tests): Call it. libcpp/ChangeLog: Martin Liska PR lto/88147 * line-map.c (linemap_line_start): Don't reuse the existing line map if the line offset is sufficiently large to cause overflow when computing location_t values. From-SVN: r268789 --- libcpp/ChangeLog | 7 +++++++ libcpp/line-map.c | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index ae05d6b..8af9846 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,10 @@ +2019-02-11 Martin Liska + + PR lto/88147 + * line-map.c (linemap_line_start): Don't reuse the existing line + map if the line offset is sufficiently large to cause overflow + when computing location_t values. + 2019-01-26 Jakub Jelinek PR preprocessor/88974 diff --git a/libcpp/line-map.c b/libcpp/line-map.c index ff679ed..0e30b4b 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -742,6 +742,10 @@ linemap_line_start (struct line_maps *set, linenum_type to_line, if (line_delta < 0 || last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (map) || SOURCE_COLUMN (map, highest) >= (1U << (column_bits - range_bits)) + || ( /* We can't reuse the map if the line offset is sufficiently + large to cause overflow when computing location_t values. */ + (to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map)) + >= (1U << (CHAR_BIT * sizeof (linenum_type) - column_bits))) || range_bits < map->m_range_bits) map = linemap_check_ordinary (const_cast -- cgit v1.1