diff mbox series

[2/2] libsepol/cil: Only reset AST if optional has a declaration

Message ID 20210624195815.148698-2-jwcart2@gmail.com (mailing list archive)
State Accepted
Headers show
Series [1/2] libsepol/cil: Add function to determine if a subtree has a declaration | expand

Commit Message

James Carter June 24, 2021, 7:58 p.m. UTC
When disabling optionals, the AST needs to be reset only if one
of the optional blocks being disabled contains a declaration.

Call the function cil_tree_subtree_has_decl() for each optional
block being disabled and only reset the AST if one of them has
a declaration in it.

Signed-off-by: James Carter <jwcart2@gmail.com>
---
 libsepol/cil/src/cil_resolve_ast.c | 58 +++++++++++++++++-------------
 1 file changed, 34 insertions(+), 24 deletions(-)
diff mbox series

Patch

diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 5245cc15..0ea5b169 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -4230,33 +4230,43 @@  int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
 		if (changed) {
 			struct cil_list_item *item;
 			if (pass > CIL_PASS_CALL1) {
-				/* Need to re-resolve because an optional was disabled that contained
-				 * one or more declarations. We only need to reset to the call1 pass
-				 * because things done in the preceding passes aren't allowed in
-				 * optionals, and thus can't be disabled.
-				 * Note: set pass to CIL_PASS_CALL1 because the pass++ will increment
-				 * it to CIL_PASS_CALL2
-				 */
-				cil_log(CIL_INFO, "Resetting declarations\n");
-
-				if (pass >= CIL_PASS_MISC1) {
-					__cil_ordered_lists_reset(&extra_args.sidorder_lists);
-					__cil_ordered_lists_reset(&extra_args.classorder_lists);
-					__cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
-					__cil_ordered_lists_reset(&extra_args.catorder_lists);
-					__cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
-					cil_list_destroy(&db->sidorder, CIL_FALSE);
-					cil_list_destroy(&db->classorder, CIL_FALSE);
-					cil_list_destroy(&db->catorder, CIL_FALSE);
-					cil_list_destroy(&db->sensitivityorder, CIL_FALSE);
+				int has_decls = CIL_FALSE;
+
+				cil_list_for_each(item, extra_args.to_destroy) {
+					has_decls = cil_tree_subtree_has_decl(item->data);
+					if (has_decls) {
+						break;
+					}
 				}
 
-				pass = CIL_PASS_CALL1;
+				if (has_decls) {
+					/* Need to re-resolve because an optional was disabled that
+					 * contained one or more declarations.
+					 * Everything that needs to be reset comes after the
+					 * CIL_PASS_CALL2 pass. We set pass to CIL_PASS_CALL1 because
+					 * the pass++ will increment it to CIL_PASS_CALL2
+					 */
+					cil_log(CIL_INFO, "Resetting declarations\n");
+
+					if (pass >= CIL_PASS_MISC1) {
+						__cil_ordered_lists_reset(&extra_args.sidorder_lists);
+						__cil_ordered_lists_reset(&extra_args.classorder_lists);
+						__cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
+						__cil_ordered_lists_reset(&extra_args.catorder_lists);
+						__cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
+						cil_list_destroy(&db->sidorder, CIL_FALSE);
+						cil_list_destroy(&db->classorder, CIL_FALSE);
+						cil_list_destroy(&db->catorder, CIL_FALSE);
+						cil_list_destroy(&db->sensitivityorder, CIL_FALSE);
+					}
 
-				rc = cil_reset_ast(current);
-				if (rc != SEPOL_OK) {
-					cil_log(CIL_ERR, "Failed to reset declarations\n");
-					goto exit;
+					pass = CIL_PASS_CALL1;
+
+					rc = cil_reset_ast(current);
+					if (rc != SEPOL_OK) {
+						cil_log(CIL_ERR, "Failed to reset declarations\n");
+						goto exit;
+					}
 				}
 			}
 			cil_list_for_each(item, extra_args.to_destroy) {