-Wmisleading-indentation: fix ICE in get_visual_column (PR c++/70693)
commit10fcc1429cfad8b453712fe55319807769fa6370
authorDavid Malcolm <dmalcolm@redhat.com>
Thu, 16 Aug 2018 17:07:15 +0000 (16 17:07 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Thu, 16 Aug 2018 17:07:15 +0000 (16 17:07 +0000)
tree06a490d2e4fe9e8d28d89eba5bc097b27b811ad6
parent012d429b84046483721291425c9fcdbd167bbaf4
-Wmisleading-indentation: fix ICE in get_visual_column (PR c++/70693)

PR c++/70693 reports a crash within -Wmisleading-indentation in
get_visual_column, reading past the end of a source line.

The issue occurs due to a stray carriage return aka '\r' aka ^M, occurring
towards the end of line 35 of attachment 38289 - but not at the end itself.

This carriage return confuses our line numbering: from that point in the
file, the lexer (and thus location_t values) use line numbers that are
one larger than those seen by input.c, "cat -n" and emacs.

This discrepancy between the lexer's line numbering and input.c's line
numbering leads to an out-of-range read in get_visual_column (trying to
read column 8, to locate the first non-whitespace on the line containing
"break;", but finding the next line, which is only 4 characters long).

This patch fixes the ICE by adding a range check to get_visual_column
before accessing the input.c line buffer.  This is arguably papering
over the root cause, but there are presumably other ways of triggering
such an out-of-range read by writing to the source file after the lexer
but before -Wmisleading-indentation, and we ought to be not ICE in the
face of that.

gcc/c-family/ChangeLog:
PR c++/70693
* c-common.c (selftest::c_family_tests): Call
selftest::c_indentation_c_tests.
* c-common.h (selftest::c_indentation_c_tests): New decl.
* c-indentation.c: Include "selftest.h".
(next_tab_stop): Add "tab_width" param, rather than accessing
cpp_opts.
(get_visual_column): Likewise.  Clarify comment.  Bulletproof
against reading past the end of the line.
(get_first_nws_vis_column): Add "tab_width" param.
(detect_intervening_unindent): Likewise.
(should_warn_for_misleading_indentation): Read tab width from
cpp_opts and pass around.
(selftest::test_next_tab_stop): New test.
(selftest::assert_get_visual_column_succeeds): New function.
(ASSERT_GET_VISUAL_COLUMN_SUCCEEDS): New macro.
(selftest::assert_get_visual_column_fails): New function.
(ASSERT_GET_VISUAL_COLUMN_FAILS): New macro.
(selftest::test_get_visual_column): New test.
(selftest::c_indentation_c_tests): New function.

gcc/testsuite/ChangeLog:
PR c++/70693
* c-c++-common/Wmisleading-indentation-pr70693.c: New test.

From-SVN: r263595
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-family/c-indentation.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/Wmisleading-indentation-pr70693.c [new file with mode: 0644]