Blame SOURCES/openscap-1.3.3-systemdunit-segfault.patch

0b628f
diff --git a/src/OVAL/probes/unix/linux/systemdunitdependency_probe.c b/src/OVAL/probes/unix/linux/systemdunitdependency_probe.c
0b628f
index 2f194ce07..e2cbdb7d2 100644
0b628f
--- a/src/OVAL/probes/unix/linux/systemdunitdependency_probe.c
0b628f
+++ b/src/OVAL/probes/unix/linux/systemdunitdependency_probe.c
0b628f
@@ -37,6 +37,8 @@
0b628f
 #include <string.h>
0b628f
 #include "systemdunitdependency_probe.h"
0b628f
 
0b628f
+static void get_all_dependencies_by_unit(DBusConnection *conn, const char *unit, SEXP_t *item, struct oscap_htable *visited_units);
0b628f
+
0b628f
 static char *get_property_by_unit_path(DBusConnection *conn, const char *unit_path, const char *property)
0b628f
 {
0b628f
 	DBusMessage *msg = NULL;
0b628f
@@ -135,7 +137,38 @@ static bool is_unit_name_a_target(const char *unit)
0b628f
 	return strncmp(unit + len - suffix_len, suffix, suffix_len) == 0;
0b628f
 }
0b628f
 
0b628f
-static void get_all_dependencies_by_unit(DBusConnection *conn, const char *unit, int(*callback)(const char *, void *), void *cbarg, bool include_requires, bool include_wants)
0b628f
+static int add_unit_dependency(const char *dependency, SEXP_t *item, struct oscap_htable *visited_units)
0b628f
+{
0b628f
+	if (oscap_htable_get(visited_units, dependency) != NULL) {
0b628f
+		return 1;
0b628f
+	}
0b628f
+	oscap_htable_add(visited_units, dependency, (void *) true);
0b628f
+	SEXP_t *se_dependency = SEXP_string_new(dependency, strlen(dependency));
0b628f
+	probe_item_ent_add(item, "dependency", NULL, se_dependency);
0b628f
+	SEXP_free(se_dependency);
0b628f
+	return 0;
0b628f
+}
0b628f
+
0b628f
+static void process_unit_property(const char *property, DBusConnection *conn, const char *path, SEXP_t *item, struct oscap_htable *visited_units)
0b628f
+{
0b628f
+	char *values_s = get_property_by_unit_path(conn, path, property);
0b628f
+	if (values_s) {
0b628f
+		char **values = oscap_split(values_s, ", ");
0b628f
+		for (int i = 0; values[i] != NULL; ++i) {
0b628f
+			if (oscap_strcmp(values[i], "") == 0) {
0b628f
+				continue;
0b628f
+			}
0b628f
+
0b628f
+			if (add_unit_dependency(values[i], item, visited_units) == 0) {
0b628f
+				get_all_dependencies_by_unit(conn, values[i], item, visited_units);
0b628f
+			}
0b628f
+		}
0b628f
+		free(values);
0b628f
+	}
0b628f
+	free(values_s);
0b628f
+}
0b628f
+
0b628f
+static void get_all_dependencies_by_unit(DBusConnection *conn, const char *unit, SEXP_t *item, struct oscap_htable *visited_units)
0b628f
 {
0b628f
 	if (!unit || strcmp(unit, "(null)") == 0)
0b628f
 		return;
0b628f
@@ -146,66 +179,12 @@ static void get_all_dependencies_by_unit(DBusConnection *conn, const char *unit,
0b628f
 
0b628f
 	char *path = get_path_by_unit(conn, unit);
0b628f
 
0b628f
-	if (include_requires) {
0b628f
-		char *requires_s = get_property_by_unit_path(conn, path, "Requires");
0b628f
-		if (requires_s) {
0b628f
-			char **requires = oscap_split(requires_s, ", ");
0b628f
-			for (int i = 0; requires[i] != NULL; ++i) {
0b628f
-				if (oscap_strcmp(requires[i], "") == 0)
0b628f
-					continue;
0b628f
-
0b628f
-				if (callback(requires[i], cbarg) == 0) {
0b628f
-					get_all_dependencies_by_unit(conn, requires[i],
0b628f
-									callback, cbarg,
0b628f
-									include_requires, include_wants);
0b628f
-				} else {
0b628f
-					free(requires);
0b628f
-					free(requires_s);
0b628f
-					free(path);
0b628f
-					return;
0b628f
-				}
0b628f
-			}
0b628f
-			free(requires);
0b628f
-		}
0b628f
-		free(requires_s);
0b628f
-	}
0b628f
-
0b628f
-	if (include_wants) {
0b628f
-		char *wants_s = get_property_by_unit_path(conn, path, "Wants");
0b628f
-		if (wants_s)
0b628f
-		{
0b628f
-			char **wants = oscap_split(wants_s, ", ");
0b628f
-			for (int i = 0; wants[i] != NULL; ++i) {
0b628f
-				if (oscap_strcmp(wants[i], "") == 0)
0b628f
-					continue;
0b628f
-
0b628f
-				if (callback(wants[i], cbarg) == 0) {
0b628f
-					get_all_dependencies_by_unit(conn, wants[i],
0b628f
-									callback, cbarg,
0b628f
-									include_requires, include_wants);
0b628f
-				} else {
0b628f
-					free(wants);
0b628f
-					free(wants_s);
0b628f
-					free(path);
0b628f
-					return;
0b628f
-				}
0b628f
-			}
0b628f
-			free(wants);
0b628f
-		}
0b628f
-		free(wants_s);
0b628f
-	}
0b628f
+	process_unit_property("Requires", conn, path, item, visited_units);
0b628f
+	process_unit_property("Wants", conn, path, item, visited_units);
0b628f
 
0b628f
 	free(path);
0b628f
 }
0b628f
 
0b628f
-static int dependency_callback(const char *dependency, void *cbarg)
0b628f
-{
0b628f
-	SEXP_t *item = (SEXP_t *)cbarg;
0b628f
-	SEXP_t *se_dependency = SEXP_string_new(dependency, strlen(dependency));
0b628f
-	probe_item_ent_add(item, "dependency", NULL, se_dependency);
0b628f
-	return 0;
0b628f
-}
0b628f
-
0b628f
 static int unit_callback(const char *unit, void *cbarg)
0b628f
 {
0b628f
 	struct unit_callback_vars *vars = (struct unit_callback_vars *)cbarg;
0b628f
@@ -221,8 +200,9 @@ static int unit_callback(const char *unit, void *cbarg)
0b628f
 					 "unit", OVAL_DATATYPE_SEXP, se_unit,
0b628f
 					 NULL);
0b628f
 
0b628f
-	get_all_dependencies_by_unit(vars->dbus_conn, unit,
0b628f
-				     dependency_callback, item, true, true);
0b628f
+	struct oscap_htable *visited_units = oscap_htable_new();
0b628f
+	get_all_dependencies_by_unit(vars->dbus_conn, unit, item, visited_units);
0b628f
+	oscap_htable_free(visited_units, NULL);
0b628f
 
0b628f
 	probe_item_collect(vars->ctx, item);
0b628f
 	SEXP_free(se_unit);