Module Name:    src
Committed By:   rillig
Date:           Sat Jul 15 12:24:57 UTC 2023

Modified Files:
        src/distrib/sets/lists/tests: mi
        src/usr.bin/xlint/lint1: tree.c
Added Files:
        src/tests/usr.bin/xlint/lint1: gcc_statement_expression.c

Log Message:
tests/lint: demonstrate use-after-free in GCC statement expression


To generate a diff of this commit:
cvs rdiff -u -r1.1276 -r1.1277 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r0 -r1.1 \
    src/tests/usr.bin/xlint/lint1/gcc_statement_expression.c
cvs rdiff -u -r1.566 -r1.567 src/usr.bin/xlint/lint1/tree.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.1276 src/distrib/sets/lists/tests/mi:1.1277
--- src/distrib/sets/lists/tests/mi:1.1276	Wed Jul 12 18:13:39 2023
+++ src/distrib/sets/lists/tests/mi	Sat Jul 15 12:24:57 2023
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1276 2023/07/12 18:13:39 rillig Exp $
+# $NetBSD: mi,v 1.1277 2023/07/15 12:24:57 rillig Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -6681,6 +6681,7 @@
 ./usr/tests/usr.bin/xlint/lint1/gcc_cast_union.exp		tests-obsolete		obsolete,atf
 ./usr/tests/usr.bin/xlint/lint1/gcc_init_compound_literal.c	tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/gcc_init_compound_literal.exp	tests-obsolete		obsolete,atf
+./usr/tests/usr.bin/xlint/lint1/gcc_statement_expression.c	tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/gcc_stmt_asm.c			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/gcc_stmt_asm.exp		tests-obsolete		obsolete,atf
 ./usr/tests/usr.bin/xlint/lint1/gcc_typeof.c			tests-usr.bin-tests	compattestfile,atf

Index: src/usr.bin/xlint/lint1/tree.c
diff -u src/usr.bin/xlint/lint1/tree.c:1.566 src/usr.bin/xlint/lint1/tree.c:1.567
--- src/usr.bin/xlint/lint1/tree.c:1.566	Fri Jul 14 09:20:23 2023
+++ src/usr.bin/xlint/lint1/tree.c	Sat Jul 15 12:24:57 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: tree.c,v 1.566 2023/07/14 09:20:23 rillig Exp $	*/
+/*	$NetBSD: tree.c,v 1.567 2023/07/15 12:24:57 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID)
-__RCSID("$NetBSD: tree.c,v 1.566 2023/07/14 09:20:23 rillig Exp $");
+__RCSID("$NetBSD: tree.c,v 1.567 2023/07/15 12:24:57 rillig Exp $");
 #endif
 
 #include <float.h>
@@ -4794,6 +4794,8 @@ static stmt_expr *stmt_exprs;
 void
 begin_statement_expr(void)
 {
+	debug_enter();
+
 	stmt_expr *se = xmalloc(sizeof(*se));
 	se->se_mem = expr_save_memory();
 	se->se_sym = NULL;
@@ -4818,13 +4820,21 @@ do_statement_expr(tnode_t *tn)
 tnode_t *
 end_statement_expr(void)
 {
+	tnode_t *tn;
+
 	stmt_expr *se = stmt_exprs;
-	if (se->se_sym == NULL)
-		return NULL;	/* after a syntax error */
-	tnode_t *tn = build_name(se->se_sym, false);
+	if (se->se_sym == NULL) {
+		tn = NULL;	/* after a syntax error */
+		goto end;
+	}
+
+	tn = build_name(se->se_sym, false);
 	(void)expr_save_memory();	/* leak */
 	expr_restore_memory(se->se_mem);
 	stmt_exprs = se->se_enclosing;
 	free(se);
+
+end:
+	debug_leave();
 	return tn;
 }

Added files:

Index: src/tests/usr.bin/xlint/lint1/gcc_statement_expression.c
diff -u /dev/null src/tests/usr.bin/xlint/lint1/gcc_statement_expression.c:1.1
--- /dev/null	Sat Jul 15 12:24:57 2023
+++ src/tests/usr.bin/xlint/lint1/gcc_statement_expression.c	Sat Jul 15 12:24:57 2023
@@ -0,0 +1,27 @@
+/*	$NetBSD: gcc_statement_expression.c,v 1.1 2023/07/15 12:24:57 rillig Exp $	*/
+# 3 "gcc_statement_expression.c"
+
+/*
+ * Tests for the GCC extension 'statement expressions', which allows a block of
+ * statements to occur as part of an expression.
+ */
+
+
+// Ensure that the inner types are accessible from outside the block.
+// Depending on the memory management strategy, the inner types might be freed
+// too early.
+static inline int
+use_inner_type_from_outside(void)
+{
+	int x = ({
+		struct outer {
+			struct inner {
+				int member;
+			} inner;
+		} outer = { { 3 } };
+		// TODO: Move the '.inner.member' out of the statement
+		//  expression, without a use-after-free crash.
+		outer.inner.member;
+	});
+	return x;
+}

Reply via email to