summaryrefslogtreecommitdiffstats
path: root/generator
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2012-03-08 12:21:09 +0000
committerRichard W.M. Jones <rjones@redhat.com>2012-03-08 13:21:59 +0000
commit4dd26c28a3786f756c20f204488bfbcfc5e75309 (patch)
tree13c4356d955fdf8ea8d2e322ece7308de17d51b9 /generator
parentd0453c02545c825810fec6e5874c55d7ac5ec678 (diff)
downloadlibguestfs-4dd26c28a3786f756c20f204488bfbcfc5e75309.tar.gz
libguestfs-4dd26c28a3786f756c20f204488bfbcfc5e75309.tar.xz
libguestfs-4dd26c28a3786f756c20f204488bfbcfc5e75309.zip
fish: Properly free up strings, lists along all error paths (found by Coverity).
This also includes some tidying up of the generated code. Error: RESOURCE_LEAK: /builddir/build/BUILD/libguestfs-1.16.5/fish/cmds.c:13254: alloc_fn: Calling allocation function "parse_string_list". /builddir/build/BUILD/libguestfs-1.16.5/fish/fish.c:1386: alloc_fn: Storage is returned from allocation function "realloc". /builddir/build/BUILD/libguestfs-1.16.5/fish/fish.c:1386: var_assign: Assigning: "argv_new" = "realloc(argv, 8UL * argv_len)". /builddir/build/BUILD/libguestfs-1.16.5/fish/fish.c:1392: var_assign: Assigning: "argv" = "argv_new". /builddir/build/BUILD/libguestfs-1.16.5/fish/fish.c:1396: return_alloc: Returning allocated memory "argv". /builddir/build/BUILD/libguestfs-1.16.5/fish/cmds.c:13254: var_assign: Assigning: "devices" = storage returned from "parse_string_list(argv[i++])". /builddir/build/BUILD/libguestfs-1.16.5/fish/cmds.c:13271: leaked_storage: Variable "devices" going out of scope leaks the storage it points to. /builddir/build/BUILD/libguestfs-1.16.5/fish/cmds.c:13288: leaked_storage: Variable "devices" going out of scope leaks the storage it points to. /builddir/build/BUILD/libguestfs-1.16.5/fish/cmds.c:13293: leaked_storage: Variable "devices" going out of scope leaks the storage it points to. /builddir/build/BUILD/libguestfs-1.16.5/fish/cmds.c:13311: leaked_storage: Variable "devices" going out of scope leaks the storage it points to. /builddir/build/BUILD/libguestfs-1.16.5/fish/cmds.c:13316: leaked_storage: Variable "devices" going out of scope leaks the storage it points to. /builddir/build/BUILD/libguestfs-1.16.5/fish/cmds.c:13334: leaked_storage: Variable "devices" going out of scope leaks the storage it points to. /builddir/build/BUILD/libguestfs-1.16.5/fish/cmds.c:13349: leaked_storage: Variable "devices" going out of scope leaks the storage it points to. /builddir/build/BUILD/libguestfs-1.16.5/fish/cmds.c:13355: leaked_storage: Variable "devices" going out of scope leaks the storage it points to.
Diffstat (limited to 'generator')
-rw-r--r--generator/generator_fish.ml190
1 files changed, 106 insertions, 84 deletions
diff --git a/generator/generator_fish.ml b/generator/generator_fish.ml
index 2ce08d5e..84f2208d 100644
--- a/generator/generator_fish.ml
+++ b/generator/generator_fish.ml
@@ -305,6 +305,7 @@ Guestfish will prompt for these separately."
pr "static int\n";
pr "run_%s (const char *cmd, size_t argc, char *argv[])\n" name;
pr "{\n";
+ pr " int ret = -1;\n";
(match ret with
| RErr
| RInt _
@@ -367,34 +368,35 @@ Guestfish will prompt for these separately."
argc_minimum argc_maximum;
);
pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
- pr " return -1;\n";
+ pr " goto out_noargs;\n";
pr " }\n";
- let parse_integer expr fn fntyp rtyp range name =
- pr " {\n";
- pr " strtol_error xerr;\n";
- pr " %s r;\n" fntyp;
+ let parse_integer ?(indent = " ") expr fn fntyp rtyp range name out =
+ pr "%s{\n" indent;
+ pr "%s strtol_error xerr;\n" indent;
+ pr "%s %s r;\n" indent fntyp;
pr "\n";
- pr " xerr = %s (%s, NULL, 0, &r, xstrtol_suffixes);\n" fn expr;
- pr " if (xerr != LONGINT_OK) {\n";
- pr " fprintf (stderr,\n";
- pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
- pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
- pr " return -1;\n";
- pr " }\n";
+ pr "%s xerr = %s (%s, NULL, 0, &r, xstrtol_suffixes);\n"
+ indent fn expr;
+ pr "%s if (xerr != LONGINT_OK) {\n" indent;
+ pr "%s fprintf (stderr,\n" indent;
+ pr "%s _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n" indent;
+ pr "%s cmd, \"%s\", \"%s\", xerr);\n" indent name fn;
+ pr "%s goto %s;\n" indent out;
+ pr "%s }\n" indent;
(match range with
| None -> ()
| Some (min, max, comment) ->
- pr " /* %s */\n" comment;
- pr " if (r < %s || r > %s) {\n" min max;
- pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
- name;
- pr " return -1;\n";
- pr " }\n";
- pr " /* The check above should ensure this assignment does not overflow. */\n";
+ pr "%s /* %s */\n" indent comment;
+ pr "%s if (r < %s || r > %s) {\n" indent min max;
+ pr "%s fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
+ indent name;
+ pr "%s goto %s;\n" indent out;
+ pr "%s }\n" indent;
+ pr "%s /* The check above should ensure this assignment does not overflow. */\n" indent;
);
- pr " %s = r;\n" name;
- pr " }\n";
+ pr "%s %s = r;\n" indent name;
+ pr "%s}\n" indent;
in
List.iter (
@@ -405,7 +407,7 @@ Guestfish will prompt for these separately."
| Pathname name
| Dev_or_Path name ->
pr " %s = win_prefix (argv[i++]); /* process \"win:\" prefix */\n" name;
- pr " if (%s == NULL) return -1;\n" name
+ pr " if (%s == NULL) goto out_%s;\n" name name
| OptString name ->
pr " %s = STRNEQ (argv[i], \"\") ? argv[i] : NULL;\n" name;
pr " i++;\n"
@@ -415,18 +417,18 @@ Guestfish will prompt for these separately."
pr " i++;\n"
| FileIn name ->
pr " %s = file_in (argv[i++]);\n" name;
- pr " if (%s == NULL) return -1;\n" name
+ pr " if (%s == NULL) goto out_%s;\n" name name
| FileOut name ->
pr " %s = file_out (argv[i++]);\n" name;
- pr " if (%s == NULL) return -1;\n" name
+ pr " if (%s == NULL) goto out_%s;\n" name name
| StringList name | DeviceList name ->
pr " %s = parse_string_list (argv[i++]);\n" name;
- pr " if (%s == NULL) return -1;\n" name
+ pr " if (%s == NULL) goto out_%s;\n" name name
| Key name ->
pr " %s = read_key (\"%s\");\n" name name;
pr " if (keys_from_stdin)\n";
pr " input_lineno++;\n";
- pr " if (%s == NULL) return -1;\n" name
+ pr " if (%s == NULL) goto out_%s;\n" name name
| Bool name ->
pr " %s = is_true (argv[i++]) ? 1 : 0;\n" name
| Int name ->
@@ -436,9 +438,11 @@ Guestfish will prompt for these separately."
and comment =
"The Int type in the generator is a signed 31 bit int." in
Some (min, max, comment) in
- parse_integer "argv[i++]" "xstrtoll" "long long" "int" range name
+ parse_integer "argv[i++]" "xstrtoll" "long long" "int" range
+ name (sprintf "out_%s" name)
| Int64 name ->
- parse_integer "argv[i++]" "xstrtoll" "long long" "int64_t" None name
+ parse_integer "argv[i++]" "xstrtoll" "long long" "int64_t" None
+ name (sprintf "out_%s" name)
| Pointer _ -> assert false
) args;
@@ -472,12 +476,14 @@ Guestfish will prompt for these separately."
"The Int type in the generator is a signed 31 bit int." in
Some (min, max, comment) in
let expr = sprintf "&argv[i][%d]" (len+1) in
- parse_integer expr "xstrtoll" "long long" "int" range
- (sprintf "optargs_s.%s" n)
+ parse_integer ~indent:" "
+ expr "xstrtoll" "long long" "int" range
+ (sprintf "optargs_s.%s" n) "out"
| OInt64 n ->
let expr = sprintf "&argv[i][%d]" (len+1) in
- parse_integer expr "xstrtoll" "long long" "int64_t" None
- (sprintf "optargs_s.%s" n)
+ parse_integer ~indent:" "
+ expr "xstrtoll" "long long" "int64_t" None
+ (sprintf "optargs_s.%s" n) "out"
| OString n ->
pr " optargs_s.%s = &argv[i][%d];\n" n (len+1);
);
@@ -490,13 +496,13 @@ Guestfish will prompt for these separately."
pr "{\n";
pr " fprintf (stderr, _(\"%%s: unknown optional argument \\\"%%s\\\"\\n\"),\n";
pr " cmd, argv[i]);\n";
- pr " return -1;\n";
+ pr " goto out;\n";
pr " }\n";
pr "\n";
pr " if (optargs_s.bitmask & this_mask) {\n";
pr " fprintf (stderr, _(\"%%s: optional argument \\\"%%s\\\" given twice\\n\"),\n";
pr " cmd, this_arg);\n";
- pr " return -1;\n";
+ pr " goto out;\n";
pr " }\n";
pr " optargs_s.bitmask |= this_mask;\n";
pr " }\n";
@@ -511,22 +517,6 @@ Guestfish will prompt for these separately."
generate_c_call_args ~handle:"g" style;
pr ";\n";
- List.iter (
- function
- | Device _ | String _
- | OptString _ | Bool _
- | Int _ | Int64 _
- | BufferIn _ -> ()
- | Pathname name | Dev_or_Path name | FileOut name
- | Key name ->
- pr " free (%s);\n" name
- | FileIn name ->
- pr " free_file_in (%s);\n" name
- | StringList name | DeviceList name ->
- pr " free_strings (%s);\n" name
- | Pointer _ -> assert false
- ) args;
-
(* Any output flags? *)
let fish_output =
let flags = filter_map (
@@ -540,73 +530,105 @@ Guestfish will prompt for these separately."
(* Check return value for errors and display command results. *)
(match ret with
- | RErr -> pr " return r;\n"
+ | RErr ->
+ pr " if (r == -1) goto out;\n";
+ pr " ret = 0;\n"
| RInt _ ->
- pr " if (r == -1) return -1;\n";
+ pr " if (r == -1) goto out;\n";
+ pr " ret = 0;\n";
(match fish_output with
| None ->
pr " printf (\"%%d\\n\", r);\n";
| Some FishOutputOctal ->
pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
| Some FishOutputHexadecimal ->
- pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
- pr " return 0;\n"
+ pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n"
+ )
| RInt64 _ ->
- pr " if (r == -1) return -1;\n";
+ pr " if (r == -1) goto out;\n";
+ pr " ret = 0;\n";
(match fish_output with
| None ->
pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
| Some FishOutputOctal ->
pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
| Some FishOutputHexadecimal ->
- pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
- pr " return 0;\n"
+ pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n"
+ )
| RBool _ ->
- pr " if (r == -1) return -1;\n";
- pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
- pr " return 0;\n"
+ pr " if (r == -1) goto out;\n";
+ pr " ret = 0;\n";
+ pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n"
| RConstString _ ->
- pr " if (r == NULL) return -1;\n";
- pr " printf (\"%%s\\n\", r);\n";
- pr " return 0;\n"
+ pr " if (r == NULL) goto out;\n";
+ pr " ret = 0;\n";
+ pr " printf (\"%%s\\n\", r);\n"
| RConstOptString _ ->
- pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
- pr " return 0;\n"
+ pr " ret = 0;\n";
+ pr " printf (\"%%s\\n\", r ? : \"(null)\");\n"
| RString _ ->
- pr " if (r == NULL) return -1;\n";
+ pr " if (r == NULL) goto out;\n";
+ pr " ret = 0;\n";
pr " printf (\"%%s\\n\", r);\n";
- pr " free (r);\n";
- pr " return 0;\n"
+ pr " free (r);\n"
| RStringList _ ->
- pr " if (r == NULL) return -1;\n";
+ pr " if (r == NULL) goto out;\n";
+ pr " ret = 0;\n";
pr " print_strings (r);\n";
- pr " free_strings (r);\n";
- pr " return 0;\n"
+ pr " free_strings (r);\n"
| RStruct (_, typ) ->
- pr " if (r == NULL) return -1;\n";
+ pr " if (r == NULL) goto out;\n";
+ pr " ret = 0;\n";
pr " print_%s (r);\n" typ;
- pr " guestfs_free_%s (r);\n" typ;
- pr " return 0;\n"
+ pr " guestfs_free_%s (r);\n" typ
| RStructList (_, typ) ->
- pr " if (r == NULL) return -1;\n";
+ pr " if (r == NULL) goto out;\n";
+ pr " ret = 0;\n";
pr " print_%s_list (r);\n" typ;
- pr " guestfs_free_%s_list (r);\n" typ;
- pr " return 0;\n"
+ pr " guestfs_free_%s_list (r);\n" typ
| RHashtable _ ->
- pr " if (r == NULL) return -1;\n";
+ pr " if (r == NULL) goto out;\n";
+ pr " ret = 0;\n";
pr " print_table (r);\n";
- pr " free_strings (r);\n";
- pr " return 0;\n"
+ pr " free_strings (r);\n"
| RBufferOut _ ->
- pr " if (r == NULL) return -1;\n";
+ pr " if (r == NULL) goto out;\n";
pr " if (full_write (1, r, size) != size) {\n";
pr " perror (\"write\");\n";
pr " free (r);\n";
- pr " return -1;\n";
+ pr " goto out;\n";
pr " }\n";
- pr " free (r);\n";
- pr " return 0;\n"
+ pr " ret = 0;\n";
+ pr " free (r);\n"
);
+
+ (* Free arguments in reverse order. *)
+ (match ret with
+ | RConstOptString _ -> ()
+ | _ -> pr " out:\n");
+ List.iter (
+ function
+ | Device _ | String _
+ | OptString _ | Bool _
+ | BufferIn _ -> ()
+ | Int name | Int64 name ->
+ pr " out_%s:\n" name
+ | Pathname name | Dev_or_Path name | FileOut name
+ | Key name ->
+ pr " free (%s);\n" name;
+ pr " out_%s:\n" name
+ | FileIn name ->
+ pr " free_file_in (%s);\n" name;
+ pr " out_%s:\n" name
+ | StringList name | DeviceList name ->
+ pr " free_strings (%s);\n" name;
+ pr " out_%s:\n" name
+ | Pointer _ -> assert false
+ ) (List.rev args);
+
+ (* Return. *)
+ pr " out_noargs:\n";
+ pr " return ret;\n";
pr "}\n";
pr "\n"
) all_functions;