From 17b9d620e2b48a8fd872cd23a85a5174e8f858e5 Mon Sep 17 00:00:00 2001
From: Michael Tuexen <tuexen@fh-muenster.de>
Date: Sat, 13 Oct 2018 05:36:03 +0200
Subject: [PATCH] Add cleanup routines freeing memory.

---
 gtests/net/packetdrill/config.c      | 28 +++++++++++++++-
 gtests/net/packetdrill/config.h      |  5 ++-
 gtests/net/packetdrill/packetdrill.c |  4 +++
 gtests/net/packetdrill/script.c      | 50 ++++++++++++++++++++++++++++
 gtests/net/packetdrill/script.h      | 11 +++---
 gtests/net/packetdrill/wire_client.c |  2 +-
 6 files changed, 93 insertions(+), 7 deletions(-)

diff --git a/gtests/net/packetdrill/config.c b/gtests/net/packetdrill/config.c
index 77646729..14cd675b 100644
--- a/gtests/net/packetdrill/config.c
+++ b/gtests/net/packetdrill/config.c
@@ -210,7 +210,7 @@ static void set_ipv6_defaults(struct config *config)
 /* Set default configuration before we begin parsing. */
 void set_default_config(struct config *config)
 {
-	memset(config, 0, sizeof(*config));
+	cleanup_config(config);
 #if defined(__FreeBSD__)
 	config->code_command_line	= "/usr/local/bin/python";
 #else
@@ -387,6 +387,32 @@ void finalize_config(struct config *config)
 #endif
 }
 
+void cleanup_config(struct config *config)
+{
+	struct definition *cur_def, *next_def;
+	int i;
+
+	if (config->argv != NULL) {
+		for (i = 0; config->argv[i] != NULL; i++) {
+			free(config->argv[i]);
+		}
+	}
+	free(config->argv);
+	free(config->script_path);
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
+	free(config->tun_device);
+#endif
+	cur_def = config->defines;
+	while (cur_def != NULL) {
+		next_def = cur_def->next;
+		free(cur_def->symbol);
+		free(cur_def->value);
+		free(cur_def);
+		cur_def = next_def;
+	}
+	memset(config, 0, sizeof(struct config));
+}
+
 /* Expect that arg is comma-delimited, allowing for spaces. */
 void parse_non_fatal_arg(char *arg, struct config *config)
 {
diff --git a/gtests/net/packetdrill/config.h b/gtests/net/packetdrill/config.h
index 561785d3..31b5e92a 100644
--- a/gtests/net/packetdrill/config.h
+++ b/gtests/net/packetdrill/config.h
@@ -69,6 +69,7 @@ static inline void definition_set(struct definition **defs,
 	if (def) {
 		free(def->value);
 		def->value = value;
+		free(symbol);
 	} else {
 		def = calloc(1, sizeof(struct definition));
 		def->symbol = symbol;
@@ -87,7 +88,7 @@ static inline char *definition_get(struct definition *defs, char *symbol)
 }
 
 struct config {
-	const char **argv;			/* a copy of process argv */
+	char **argv;			/* a copy of process argv */
 
 	enum ip_version_t ip_version;		/* v4, v4-mapped-v6, v6 */
 	int socket_domain;			/* AF_INET or AF_INET6 */
@@ -187,6 +188,8 @@ extern void parse_non_fatal_arg(char *arg, struct config *config);
  */
 extern void finalize_config(struct config *config);
 
+extern void cleanup_config(struct config *config);
+
 extern void show_usage(void);
 
 /* Parse command line options. Returns a pointer to the first argument
diff --git a/gtests/net/packetdrill/packetdrill.c b/gtests/net/packetdrill/packetdrill.c
index 6450e4b7..81e2ebe7 100644
--- a/gtests/net/packetdrill/packetdrill.c
+++ b/gtests/net/packetdrill/packetdrill.c
@@ -76,6 +76,7 @@ int main(int argc, char *argv[])
 	pthread_set_name_np(pthread_self(), "main thread");
 #endif
 
+	memset(&config, 0, sizeof(struct config));
 	set_default_config(&config);
 	/* Get command line options and list of test scripts. */
 	arg = parse_command_line_options(argc, argv, &config);
@@ -98,6 +99,7 @@ int main(int argc, char *argv[])
 			}
 		}
 		run_wire_server(&config);
+		cleanup_config(&config);
 		return 0;
 	}
 
@@ -126,7 +128,9 @@ int main(int argc, char *argv[])
 
 		run_init_scripts(&config);
 		run_script(&config, &script);
+		free_script(&script);
 	}
 
+	cleanup_config(&config);
 	return 0;
 }
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index 630abcb1..b57d0d62 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -47,6 +47,56 @@ void init_script(struct script *script)
 	script->event_list = NULL;
 }
 
+/* Free resources used by a script object */
+void free_script(struct script *script)
+{
+	struct option_list *cur_option, *next_option;
+	struct event *cur_event, *next_event;
+
+	cur_option = script->option_list;
+	while (cur_option != NULL) {
+		next_option = cur_option->next;
+		free(cur_option->name);
+		free(cur_option->value);
+		free(cur_option);
+		cur_option = next_option;
+	}
+	cur_event = script->event_list;
+	while (cur_event != NULL) {
+		next_event = cur_event->next;
+		switch (cur_event->type) {
+		case PACKET_EVENT:
+			packet_free(cur_event->event.packet);
+			break;
+		case SYSCALL_EVENT:
+			free(cur_event->event.syscall->name);
+			free_expression_list(cur_event->event.syscall->arguments);
+			free_expression(cur_event->event.syscall->result);
+			if (cur_event->event.syscall->error != NULL) {
+				free(cur_event->event.syscall->error->errno_macro);
+				free(cur_event->event.syscall->error->strerror);
+			}
+			free(cur_event->event.syscall->error);
+			free(cur_event->event.syscall->note);
+			free(cur_event->event.syscall);
+			break;
+		case COMMAND_EVENT:
+			free(cur_event->event.command->command_line);
+			free(cur_event->event.command);
+			break;
+		case CODE_EVENT:
+			free(cur_event->event.code);
+			break;
+		default:
+			assert(!"bad event type");
+			break;
+		}
+		free(cur_event);
+		cur_event = next_event;
+	}
+	free(script->buffer);
+}
+
 /* This table maps expression types to human-readable strings */
 struct expression_type_entry {
 	enum expression_t type;
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index 228442b0..5e21a2c5 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -666,8 +666,8 @@ struct sctp_udpencaps_expr {
 
 /* The errno-related info from strace to summarize a system call error */
 struct errno_spec {
-	const char *errno_macro;	/* errno symbol (C macro name) */
-	const char *strerror;		/* strerror translation of errno */
+	char *errno_macro;	/* errno symbol (C macro name) */
+	char *strerror;		/* strerror translation of errno */
 };
 
 /* A system call and its expected result. System calls that should
@@ -677,7 +677,7 @@ struct errno_spec {
  * return.
  */
 struct syscall_spec {
-	const char *name;			/* name of system call */
+	char *name;				/* name of system call */
 	struct expression_list *arguments;	/* arguments to system call */
 	struct expression *result;		/* expected result from call */
 	struct errno_spec *error;		/* errno symbol or NULL */
@@ -693,7 +693,7 @@ static inline bool is_blocking_syscall(struct syscall_spec *syscall)
 
 /* A shell command line to execute using system(3) */
 struct command_spec {
-	const char *command_line;	/* executed with /bin/sh */
+	char *command_line;	/* executed with /bin/sh */
 };
 
 /* An ASCII text snippet of code to insert in the post-processing
@@ -783,6 +783,9 @@ struct flag_name {
 /* Initialize a script object */
 extern void init_script(struct script *script);
 
+/* Free resources used by a script object */
+extern void free_script(struct script *script);
+
 /* Look up the value of the given symbol, and fill it in. On success,
  * return STATUS_OK; if the symbol cannot be found, return
  * STATUS_ERR and fill in an error message in *error.
diff --git a/gtests/net/packetdrill/wire_client.c b/gtests/net/packetdrill/wire_client.c
index b47c54f8..c05d7a56 100644
--- a/gtests/net/packetdrill/wire_client.c
+++ b/gtests/net/packetdrill/wire_client.c
@@ -53,7 +53,7 @@ static void wire_client_die(struct wire_client *wire_client,
  * characters between args. We do not send the -wire_client argument,
  * since we don't want to give the server an identity crisis.
  */
-static void wire_client_serialize_argv(const char **argv, char **args_ptr,
+static void wire_client_serialize_argv(char **argv, char **args_ptr,
 				       int *args_len_ptr)
 {
 	int i;
-- 
GitLab