opt: fix memory leak in tests.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 22 Mar 2011 01:19:36 +0000 (11:49 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 22 Mar 2011 01:19:36 +0000 (11:49 +1030)
No only does this give us one more ccanlint point, it clears the way
to see if we introduce a *real* memory leak later.

ccan/opt/test/run-correct-reporting.c
ccan/opt/test/run-helpers.c
ccan/opt/test/run-no-options.c
ccan/opt/test/run-usage.c
ccan/opt/test/run.c
ccan/opt/test/utils.c
ccan/opt/test/utils.h

index 4f775a29c47fb0fa819417a0690c01a294034cd9..8534f291ac3e9accfeafb0685fc61286b6adf4b6 100644 (file)
@@ -42,6 +42,8 @@ int main(int argc, char *argv[])
        free(err_output);
        err_output = NULL;
 
+       /* parse_args allocates argv */
+       free(argv);
        return exit_status();
 }
 
index 081d27a9d1e62f90b7a86dc8dc9657b41d429ba5..a58e4d91797d2c56befa958b40fb08a14fac3594 100644 (file)
@@ -19,6 +19,9 @@ static int saved_fprintf(FILE *ignored, const char *fmt, ...);
 #define vfprintf(f, fmt, ap) saved_vprintf(fmt, ap)
 static int saved_vprintf(const char *fmt, va_list ap);
 
+#define malloc(size) saved_malloc(size)
+static void *saved_malloc(size_t size);
+
 #include <ccan/opt/helpers.c>
 #include <ccan/opt/opt.c>
 #include <ccan/opt/usage.c>
@@ -69,6 +72,13 @@ static int saved_fprintf(FILE *ignored, const char *fmt, ...)
        return ret;
 }      
 
+#undef malloc
+static void *last_allocation;
+static void *saved_malloc(size_t size)
+{
+       return last_allocation = malloc(size);
+}
+
 /* Test helpers. */
 int main(int argc, char *argv[])
 {
@@ -220,15 +230,25 @@ int main(int argc, char *argv[])
                reset_options();
                opt_register_noarg("-a",
                                   opt_version_and_exit, "1.2.3", "");
+               /* parse_args allocates argv */
+               free(argv);
+
+               argc = 2;
+               argv = malloc(sizeof(argv[0]) * 3);
+               argv[0] = "thisprog";
+               argv[1] = "-a";
+               argv[2] = NULL;
+
                exitval = setjmp(exited);
                if (exitval == 0) {
-                       parse_args(&argc, &argv, "-a", NULL);
+                       opt_parse(&argc, argv, save_err_output);
                        fail("opt_show_version_and_exit returned?");
                } else {
                        ok1(exitval - 1 == 0);
                }
                ok1(strcmp(output, "1.2.3\n") == 0);
                free(output);
+               free(argv);
                output = NULL;
        }
 
@@ -238,9 +258,16 @@ int main(int argc, char *argv[])
                reset_options();
                opt_register_noarg("-a",
                                   opt_usage_and_exit, "[args]", "");
+
+               argc = 2;
+               argv = malloc(sizeof(argv[0]) * 3);
+               argv[0] = "thisprog";
+               argv[1] = "-a";
+               argv[2] = NULL;
+
                exitval = setjmp(exited);
                if (exitval == 0) {
-                       parse_args(&argc, &argv, "-a", NULL);
+                       opt_parse(&argc, argv, save_err_output);
                        fail("opt_usage_and_exit returned?");
                } else {
                        ok1(exitval - 1 == 0);
@@ -249,6 +276,9 @@ int main(int argc, char *argv[])
                ok1(strstr(output, argv[0]));
                ok1(strstr(output, "[-a]"));
                free(output);
+               free(argv);
+               /* It exits without freeing usage string. */
+               free(last_allocation);
                output = NULL;
        }
 
@@ -377,6 +407,7 @@ int main(int argc, char *argv[])
                ok1(!strcmp(output,
                            "thisprog: --garbage: unrecognized option\n"));
                free(output);
+               free(argv);
                output = NULL;
        }
 
@@ -386,18 +417,19 @@ int main(int argc, char *argv[])
                reset_options();
                opt_register_noarg("-a",
                                   opt_usage_and_exit, "[args]", "");
+               argc = 2;
+               argv = malloc(sizeof(argv[0]) * 3);
+               argv[0] = "thisprog";
+               argv[1] = "--garbage";
+               argv[2] = NULL;
                exitval = setjmp(exited);
                if (exitval == 0) {
-                       argc = 2;
-                       argv = malloc(sizeof(argv[0]) * 3);
-                       argv[0] = "thisprog";
-                       argv[1] = "--garbage";
-                       argv[2] = NULL;
                        opt_parse(&argc, argv, opt_log_stderr_exit);
                        fail("opt_log_stderr_exit returned?");
                } else {
                        ok1(exitval - 1 == 1);
                }
+               free(argv);
                ok1(!strcmp(output,
                            "thisprog: --garbage: unrecognized option\n"));
                free(output);
index 5ae2dd35f1ccb256159462cad98edb16bd36f7f2..cf255fee0aee7c6d4c02d93581c9cdf531a508c9 100644 (file)
@@ -25,6 +25,9 @@ int main(int argc, char *argv[])
        ok1(strcmp(argv[1], "extra") == 0);
        ok1(strcmp(argv[2], "args") == 0);
 
+       /* parse_args allocates argv */
+       free(argv);
+
        return exit_status();
 }
 
index 73e6a949e912a161ea916adfcb46b73c500e304c..2af2c7eebab773c770f21f7ae4a63bce81cfe97e 100644 (file)
@@ -106,5 +106,7 @@ int main(int argc, char *argv[])
        ok1(strstr(output, "AAAAll"));
        free(output);
 
+       free(shortname);
+       free(longname);
        return exit_status();
 }
index 8982baa048de8cbed2c4de0f32a799b61388defb..9a769bad12d1a5dca1d74a1db2db1c2e16fd57b3 100644 (file)
@@ -291,5 +291,7 @@ int main(int argc, char *argv[])
        ok1(strcmp(argv[4], "-a") == 0);
        ok1(!argv[5]);
 
+       /* parse_args allocates argv */
+       free(argv);
        return exit_status();
 }
index fa0a2022e0987368e398161bbce28d60fd43b028..9544fa77bd3493382c07e72f77f770d09b3d4cc7 100644 (file)
@@ -29,7 +29,7 @@ void show_arg(char buf[OPT_SHOW_LEN], const char *arg)
 
 char *err_output = NULL;
 
-static void save_err_output(const char *fmt, ...)
+void save_err_output(const char *fmt, ...)
 {
        va_list ap;
        char *p;
@@ -49,7 +49,8 @@ static void save_err_output(const char *fmt, ...)
                err_output = p;
 }      
 
-/* FIXME: This leaks, BTW. */
+static bool allocated = false;
+
 bool parse_args(int *argc, char ***argv, ...)
 {
        char **a;
@@ -63,7 +64,12 @@ bool parse_args(int *argc, char ***argv, ...)
                (*argc)++;
                a = realloc(a, sizeof(*a) * (*argc + 1));
        }
+
+       if (allocated)
+               free(*argv);
+
        *argv = a;
+       allocated = true;
        /* Re-set before parsing. */
        optind = 0;
 
index b5192f7c0bf8ae22bacdf83d6aaa6533ac618794..f7c18967abc946615b309c6a573282fccb5576a6 100644 (file)
@@ -5,6 +5,7 @@
 
 bool parse_args(int *argc, char ***argv, ...);
 extern char *err_output;
+void save_err_output(const char *fmt, ...);
 
 extern unsigned int test_cb_called;
 char *test_noarg(void *arg);