Module Name: src Committed By: rillig Date: Sat Jun 10 17:35:41 UTC 2023
Modified Files: src/tests/usr.bin/indent: opt_cli.c psym_else.c t_errors.sh src/usr.bin/indent: parse.c Log Message: indent: fix stack overflow, add more tests For several parser symbols, 2 symbols are pushed in a row, which led to an out-of-bounds write. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/tests/usr.bin/indent/opt_cli.c cvs rdiff -u -r1.4 -r1.5 src/tests/usr.bin/indent/psym_else.c cvs rdiff -u -r1.34 -r1.35 src/tests/usr.bin/indent/t_errors.sh cvs rdiff -u -r1.71 -r1.72 src/usr.bin/indent/parse.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/usr.bin/indent/opt_cli.c diff -u src/tests/usr.bin/indent/opt_cli.c:1.6 src/tests/usr.bin/indent/opt_cli.c:1.7 --- src/tests/usr.bin/indent/opt_cli.c:1.6 Tue Jun 6 04:37:27 2023 +++ src/tests/usr.bin/indent/opt_cli.c Sat Jun 10 17:35:41 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: opt_cli.c,v 1.6 2023/06/06 04:37:27 rillig Exp $ */ +/* $NetBSD: opt_cli.c,v 1.7 2023/06/10 17:35:41 rillig Exp $ */ /* * Tests for the option '-cli' ("case label indentation"), which sets the @@ -97,3 +97,54 @@ classify(int n) } } //indent end + + +/* + * Test the combination of left-aligned braces and a deep case indentation. + * + * When the 'case' labels are that deeply indented, the distance between the + * braces and the 'case' is between 1 and 2 indentation levels. + */ +//indent input +{ +switch (expr) +{ +case 1: +} +} +//indent end + +//indent run -br -cli3.25 +{ + switch (expr) { + case 1: + } +} +//indent end + +//indent run -bl -cli3.25 +{ + switch (expr) + { + case 1: + } +} +//indent end + +//indent run -bl -cli2.75 +{ + switch (expr) + { + case 1: + } +} +//indent end + +//indent run -bl -cli1.25 +{ + switch (expr) + { + case 1: + } +} +//indent end Index: src/tests/usr.bin/indent/psym_else.c diff -u src/tests/usr.bin/indent/psym_else.c:1.4 src/tests/usr.bin/indent/psym_else.c:1.5 --- src/tests/usr.bin/indent/psym_else.c:1.4 Sun Apr 24 10:36:37 2022 +++ src/tests/usr.bin/indent/psym_else.c Sat Jun 10 17:35:41 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: psym_else.c,v 1.4 2022/04/24 10:36:37 rillig Exp $ */ +/* $NetBSD: psym_else.c,v 1.5 2023/06/10 17:35:41 rillig Exp $ */ /* * Tests for the parser symbol psym_else, which represents the keyword 'else' @@ -71,3 +71,18 @@ function(void) (var = 3); } //indent end + + +//indent input +{ + else +} +//indent end + +//indent run +error: Standard Input:2: Unmatched 'else' +{ + else +} +exit 1 +//indent end Index: src/tests/usr.bin/indent/t_errors.sh diff -u src/tests/usr.bin/indent/t_errors.sh:1.34 src/tests/usr.bin/indent/t_errors.sh:1.35 --- src/tests/usr.bin/indent/t_errors.sh:1.34 Fri Jun 9 11:22:31 2023 +++ src/tests/usr.bin/indent/t_errors.sh Sat Jun 10 17:35:41 2023 @@ -1,5 +1,5 @@ #! /bin/sh -# $NetBSD: t_errors.sh,v 1.34 2023/06/09 11:22:31 rillig Exp $ +# $NetBSD: t_errors.sh,v 1.35 2023/06/10 17:35:41 rillig Exp $ # # Copyright (c) 2021 The NetBSD Foundation, Inc. # All rights reserved. @@ -485,6 +485,32 @@ EOF "$indent" -l34 code.c -st } +atf_test_case 'stack_overflow' +stack_overflow_body() +{ + cat <<-EOF > code.c + {{{{{{{{{{ {{{{{{{{{{ {{{{{{{{{{ {{{{{{{{{{ {{{{{{{{{{ + {{{{{{{{{{ {{{{{{{{{{ {{{{{{{{{{ {{{{{{{{{{ {{{{{{{{{{ + {{{{{{{{{{ {{{{{{{{{{ {{{{{{{ + EOF + + atf_check \ + -s 'exit:1' \ + -e 'inline:error: code.c:3: Stuff missing from end of file\n' \ + "$indent" code.c + + cat <<-EOF > code.c + {{{{{{{{{{ {{{{{{{{{{ {{{{{{{{{{ {{{{{{{{{{ {{{{{{{{{{ + {{{{{{{{{{ {{{{{{{{{{ {{{{{{{{{{ {{{{{{{{{{ {{{{{{{{{{ + {{{{{{{{{{ {{{{{{{{{{ {{{{{{{ { + EOF + + atf_check \ + -s 'exit:1' \ + -e 'inline:indent: Parser stack overflow\n' \ + "$indent" code.c +} + atf_init_test_cases() { @@ -524,4 +550,5 @@ atf_init_test_cases() atf_add_test_case 'gcc_statement_expression' atf_add_test_case 'crash_comment_after_controlling_expression' atf_add_test_case 'comment_fits_in_one_line' + atf_add_test_case 'stack_overflow' } Index: src/usr.bin/indent/parse.c diff -u src/usr.bin/indent/parse.c:1.71 src/usr.bin/indent/parse.c:1.72 --- src/usr.bin/indent/parse.c:1.71 Sat Jun 10 16:43:56 2023 +++ src/usr.bin/indent/parse.c Sat Jun 10 17:35:40 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.71 2023/06/10 16:43:56 rillig Exp $ */ +/* $NetBSD: parse.c,v 1.72 2023/06/10 17:35:40 rillig Exp $ */ /*- * SPDX-License-Identifier: BSD-4-Clause @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: parse.c,v 1.71 2023/06/10 16:43:56 rillig Exp $"); +__RCSID("$NetBSD: parse.c,v 1.72 2023/06/10 17:35:40 rillig Exp $"); #include <err.h> @@ -101,17 +101,13 @@ decl_level(void) } static void -ps_push(parser_symbol psym) -{ - ps.psyms.sym[++ps.psyms.top] = psym; - ps.psyms.ind_level[ps.psyms.top] = ps.ind_level; -} - -static void -ps_push_follow(parser_symbol psym) +ps_push(parser_symbol psym, bool follow) { + if (ps.psyms.top + 1 >= STACKSIZE) + errx(1, "Parser stack overflow"); ps.psyms.sym[++ps.psyms.top] = psym; - ps.psyms.ind_level[ps.psyms.top] = ps.ind_level_follow; + ps.psyms.ind_level[ps.psyms.top] = + follow ? ps.ind_level_follow : ps.ind_level; } /* @@ -180,8 +176,8 @@ parse(parser_symbol psym) --ps.ind_level; } - ps_push(psym); - ps_push_follow(psym_stmt); + ps_push(psym, false); + ps_push(psym_stmt, true); break; case psym_rbrace: @@ -201,7 +197,7 @@ parse(parser_symbol psym) break; /* only put one declaration onto stack */ ps.break_after_comma = true; - ps_push_follow(psym_decl); + ps_push(psym_decl, true); if (opt.left_justify_decl) ps.ind_level_follow = ps.ind_level = decl_level(); @@ -209,7 +205,7 @@ parse(parser_symbol psym) case psym_stmt: ps.break_after_comma = false; - ps_push(psym_stmt); + ps_push(psym_stmt, false); break; case psym_if_expr: @@ -220,7 +216,7 @@ parse(parser_symbol psym) case psym_do: case psym_for_exprs: ps.ind_level = ps.ind_level_follow++; - ps_push(psym); + ps_push(psym, false); break; case psym_else: @@ -234,7 +230,7 @@ parse(parser_symbol psym) break; case psym_switch_expr: - ps_push_follow(psym_switch_expr); + ps_push(psym_switch_expr, true); ps.ind_level_follow += (int)opt.case_indent + 1; break; @@ -242,9 +238,9 @@ parse(parser_symbol psym) if (psyms->sym[psyms->top] == psym_do_stmt) { ps.ind_level = ps.ind_level_follow = psyms->ind_level[psyms->top]; - ps_push(psym_while_expr); + ps_push(psym_while_expr, false); } else { - ps_push_follow(psym_while_expr); + ps_push(psym_while_expr, true); ++ps.ind_level_follow; } break; @@ -254,9 +250,6 @@ parse(parser_symbol psym) return; } - if (psyms->top >= STACKSIZE - 1) - errx(1, "Parser stack overflow"); - debug_psyms_stack("before reduction"); psyms_reduce(&ps.psyms); debug_psyms_stack("after reduction");