Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/indent indent: fix stack overflow, add more tests



details:   https://anonhg.NetBSD.org/src/rev/f4a3b8ac953b
branches:  trunk
changeset: 376333:f4a3b8ac953b
user:      rillig <rillig%NetBSD.org@localhost>
date:      Sat Jun 10 17:35:40 2023 +0000

description:
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.

diffstat:

 tests/usr.bin/indent/opt_cli.c   |  53 +++++++++++++++++++++++++++++++++++++++-
 tests/usr.bin/indent/psym_else.c |  17 ++++++++++++-
 tests/usr.bin/indent/t_errors.sh |  29 +++++++++++++++++++++-
 usr.bin/indent/parse.c           |  37 +++++++++++----------------
 4 files changed, 111 insertions(+), 25 deletions(-)

diffs (251 lines):

diff -r e3f6e677d950 -r f4a3b8ac953b tests/usr.bin/indent/opt_cli.c
--- a/tests/usr.bin/indent/opt_cli.c    Sat Jun 10 17:14:57 2023 +0000
+++ b/tests/usr.bin/indent/opt_cli.c    Sat Jun 10 17:35:40 2023 +0000
@@ -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
diff -r e3f6e677d950 -r f4a3b8ac953b tests/usr.bin/indent/psym_else.c
--- a/tests/usr.bin/indent/psym_else.c  Sat Jun 10 17:14:57 2023 +0000
+++ b/tests/usr.bin/indent/psym_else.c  Sat Jun 10 17:35:40 2023 +0000
@@ -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
diff -r e3f6e677d950 -r f4a3b8ac953b tests/usr.bin/indent/t_errors.sh
--- a/tests/usr.bin/indent/t_errors.sh  Sat Jun 10 17:14:57 2023 +0000
+++ b/tests/usr.bin/indent/t_errors.sh  Sat Jun 10 17:35:40 2023 +0000
@@ -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'
 }
diff -r e3f6e677d950 -r f4a3b8ac953b usr.bin/indent/parse.c
--- a/usr.bin/indent/parse.c    Sat Jun 10 17:14:57 2023 +0000
+++ b/usr.bin/indent/parse.c    Sat Jun 10 17:35:40 2023 +0000
@@ -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_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;
-}
-
-static void
-ps_push_follow(parser_symbol psym)
-{
-       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");



Home | Main Index | Thread Index | Old Index