diff mbox

Stale expression reference causing use-after-free

Message ID AANLkTim1EmMOFERs7rwG=zg_AZrXtojE7dKV7Rhf17Ww@mail.gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Arnaud Lacombe Sept. 19, 2010, 4:56 a.m. UTC
None
diff mbox

Patch

diff --git a/Kconfig.testcase b/Kconfig.testcase
new file mode 100644
index 0000000..cb663e9
--- /dev/null
+++ b/Kconfig.testcase
@@ -0,0 +1 @@ 
+source "Kconfig.testcase.l1"
diff --git a/Kconfig.testcase.l1 b/Kconfig.testcase.l1
new file mode 100644
index 0000000..79ec19e
--- /dev/null
+++ b/Kconfig.testcase.l1
@@ -0,0 +1,216 @@ 
+config DUMMY_BOOL_0
+	bool
+
+config DUMMY_BOOL_1
+	bool
+
+config DUMMY_BOOL_2
+	bool
+
+config DUMMY_BOOL_3
+	bool
+	default y
+
+config DUMMY_BOOL_4
+	bool
+	default (DUMMY_COND_5 || DUMMY_COND_6)
+
+config DUMMY_STRING_0
+	string
+	default "string0" if DUMMY_COND_7
+	default "string1" if DUMMY_COND_8
+
+config DUMMY_BOOL_5 # maybe unneeded
+	bool
+	default y
+
+config DUMMY_BOOL_6
+	bool
+	default y
+
+config DUMMY_BOOL_7
+	bool
+	default y
+	select DUMMY_SELECT_0 if DUMMY_COND_0
+	select DUMMY_SELECT_1
+	select DUMMY_SELECT_2
+	select DUMMY_SELECT_3
+	select DUMMY_SELECT_4
+
+config DUMMY_BOOL_8
+	bool
+	default y
+	depends on DUMMY_COND_9 || (DUMMY_COND_10 && DUMMY_COND_11)
+
+config DUMMY_BOOL_9
+	bool
+	default y
+	select DUMMY_SELECT_5
+	select DUMMY_SELECT_6
+	select DUMMY_SELECT_7 if (!DUMMY_COND_1 || !DUMMY_COND_2)
+	select DUMMY_SELECT_8
+	select DUMMY_SELECT_9
+
+config DUMMY_BOOL_10
+	bool
+	default y
+	select DUMMY_SELECT_10
+	select DUMMY_SELECT_11
+	select DUMMY_SELECT_12
+	select DUMMY_SELECT_13
+	select DUMMY_SELECT_14
+
+config DUMMY_BOOL_11
+	bool
+	default y
+	select DUMMY_SELECT_15
+	select DUMMY_SELECT_16
+	select DUMMY_SELECT_17
+	select DUMMY_SELECT_18
+	select DUMMY_SELECT_19
+
+config DUMMY_BOOL_12
+	bool
+	default y
+	select DUMMY_SELECT_20 if DUMMY_COND_3
+	select DUMMY_SELECT_21
+	select DUMMY_SELECT_22
+	select DUMMY_SELECT_23
+	select DUMMY_SELECT_24
+
+config DUMMY_BOOL_13
+	bool
+	default (DUMMY_COND_12 || DUMMY_COND_13 || DUMMY_COND_14)
+	select DUMMY_SELECT_25
+	select DUMMY_SELECT_26 if DUMMY_COND_4
+	select DUMMY_SELECT_27
+	select DUMMY_SELECT_28
+	select DUMMY_SELECT_29
+
+config DUMMY_BOOL_14
+	bool
+	default y
+	depends on DUMMY_COND_15
+	select DUMMY_SELECT_30
+	select DUMMY_SELECT_31
+	select DUMMY_SELECT_32
+	select DUMMY_SELECT_33
+	select DUMMY_SELECT_34 if DUMMY_COND_16
+
+config DUMMY_BOOL_16
+	bool
+	default y
+
+config DUMMY_BOOL_17
+	bool
+	default y
+
+config DUMMY_BOOL_18
+	bool
+	default y
+
+config DUMMY_BOOL_19
+	bool
+	default y
+
+config DUMMY_BOOL_20
+	bool
+	default y
+
+config DUMMY_BOOL_21
+	bool
+	default y
+
+config DUMMY_BOOL_22
+	bool
+	default y
+
+config DUMMY_BOOL_23
+	bool
+	default y
+
+config DUMMY_BOOL_24
+	bool
+	default y
+
+config DUMMY_BOOL_30
+	bool
+	default y
+
+config DUMMY_BOOL_25
+	bool
+	default y
+
+config DUMMY_BOOL_26
+	bool
+	default y
+
+config DUMMY_BOOL_27
+	bool
+	default y
+
+config DUMMY_BOOL_28
+	bool
+	default y
+
+config DUMMY_BOOL_29
+	bool
+	default y
+
+config DUMMY_BOOL_30
+	bool
+	default y
+	depends on DUMMY_COND_17 && DUMMY_COND_18 && DUMMY_COND_19
+
+config DUMMY_STRING_1
+	string
+	option env="ENV0"
+
+config DUMMY_STRING_2
+	string
+	option env="ENV1"
+
+config DUMMY_STRING_3
+	string
+	depends on !UML
+	option defconfig_list
+	default "string2"
+	default "string3"
+	default "string4"
+	default "_string5"
+	default "string6"
+
+menu "dummy menu 0"
+
+config DUMMY_BOOL_31
+	bool "prompt0"
+
+config DUMMY_BOOL_32
+	bool
+
+menuconfig DUMMY_BOOL_33
+	bool "prompt1"
+	depends on DUMMY_COND_20
+
+if DUMMY_BOOL_33
+
+config DUMMY_BOOL_34
+	bool "prompt2"
+	depends on DUMMY_BOOL_33
+
+config DUMMY_BOOL_35
+	bool "prompt3"
+	depends on DUMMY_COND_21
+
+config DUMMY_BOOL_36
+	bool "prompt4"
+	depends on DUMMY_COND_22 && DUMMY_COND_23
+
+menuconfig DUMMY_BOOL_37
+	bool "prompt5"
+	depends on DUMMY_COND_24
+
+endif
+
+endmenu
+
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index 330e7c0..65f7ab3 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -71,6 +71,8 @@  struct expr *expr_copy(struct expr *org)
 	if (!org)
 		return NULL;
 
+	EXPR_CHECK(org);
+
 	e = malloc(sizeof(*org));
 	memcpy(e, org, sizeof(*org));
 	switch (org->type) {
@@ -101,11 +103,13 @@  struct expr *expr_copy(struct expr *org)
 	return e;
 }
 
-void expr_free(struct expr *e)
+void _expr_free(struct expr *e)
 {
 	if (!e)
 		return;
 
+	EXPR_CHECK(e);
+
 	switch (e->type) {
 	case E_SYMBOL:
 		break;
@@ -124,6 +128,9 @@  void expr_free(struct expr *e)
 		printf("how to free type %d?\n", e->type);
 		break;
 	}
+
+	memset(e, 'A', sizeof(e));
+
 	free(e);
 }
 
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 6ee2e4f..0adc104 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -48,6 +48,26 @@  struct expr {
 #define EXPR_AND(dep1, dep2)	(((dep1)<(dep2))?(dep1):(dep2))
 #define EXPR_NOT(dep)		(2-(dep))
 
+#if 1
+#define expr_free(e)							\
+({									\
+	fprintf(stderr, "%s: %p:%d\n", __func__, e, __LINE__);		\
+	_expr_free(e);							\
+	e = NULL;							\
+})
+#else
+#define expr_free(e)	_expr_free(e);
+#endif
+
+#define EXPR_CHECK(e)							\
+({									\
+	if ((e) != NULL && ((e)->type < E_NONE || (e)->type > E_RANGE)) { \
+		fprintf(stderr, "Invalid expr %p at %s:%d in %s(): %x\n", \
+		    e, __FILE__, __LINE__, __func__, (e)->type);	\
+		abort();						\
+	}								\
+})
+
 #define expr_list_for_each_sym(l, e, s) \
 	for (e = (l); e && (s = e->right.sym); e = e->left.expr)
 
@@ -193,7 +213,7 @@  struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symb
 struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
 struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
 struct expr *expr_copy(struct expr *org);
-void expr_free(struct expr *e);
+void _expr_free(struct expr *e);
 int expr_eq(struct expr *e1, struct expr *e2);
 void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
 tristate expr_calc_value(struct expr *e);
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 4fb5902..3563239 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -292,6 +292,7 @@  void menu_finalize(struct menu *parent)
 			menu_finalize(menu);
 	} else if (sym) {
 		/* ignore inherited dependencies for dir_dep */
+		EXPR_CHECK(parent->dir_dep);
 		sym->dir_dep.expr = expr_transform(expr_copy(parent->dir_dep));
 		sym->dir_dep.expr = expr_eliminate_dups(sym->dir_dep.expr);