From: yumkam@gmail.com (Yuriy M. Kaminskiy)
To: util-linux@vger.kernel.org
Subject: Re: [PATCH 02/10] getopt: fix memory leaks and integer overflows [ASAN & valgrind]
Date: Sun, 13 Mar 2016 15:11:54 +0300 [thread overview]
Message-ID: <m37fh6inlh.fsf@gmail.com> (raw)
In-Reply-To: 1457865109-2881-3-git-send-email-kerolasa@iki.fi
On 03/13/16 13:31 , Sami Kerola wrote:
> The getopt(1) is short living command, and one could argue ensuring all
> allocations are freed at end of execution is waste of time. There is a
> point in that, but making test-suite runs to be less noisy with ASAN is also
> nice as it encourages reading the errors when/if they happen.
>
> Signed-off-by: Sami Kerola <kerolasa@iki.fi>
> ---
> misc-utils/getopt.c | 36 ++++++++++++++++++++++++++++--------
> 1 file changed, 28 insertions(+), 8 deletions(-)
>
> diff --git a/misc-utils/getopt.c b/misc-utils/getopt.c
> index c4144f6..be2ed38 100644
> --- a/misc-utils/getopt.c
> +++ b/misc-utils/getopt.c
> @@ -79,13 +79,23 @@
> /* The shells recognized. */
> typedef enum { BASH, TCSH } shell_t;
>
> +/* This is a copy of getopt_long(3) structure, in which *name does not have
> + * const, so that is can be free'd at end of execution. */
> +struct getoption {
> + char *name;
> + int has_arg;
> + int *flag;
> + int val;
> +};
What will happen if some implementation will add new fields in `struct
option`? (Sure, unlikely, but).
IMO, `free((char *)option->name)` is *much* safer.
> struct getopt_control {
> shell_t shell; /* the shell we generate output for */
> char *optstr; /* getopt(3) optstring */
> - struct option *long_options; /* long options */
> + struct getoption *long_options; /* long options */
> int long_options_length; /* length of options array */
> int long_options_nr; /* number of used elements in array */
> unsigned int
> + free_name:1, /* free up argv[0] after printout */
> compatible:1, /* compatibility mode for 'difficult' programs */
> quiet_errors:1, /* print errors */
> quiet_output:1, /* print output */
> @@ -181,7 +191,7 @@ static void print_normalized(const struct getopt_control *ctl, const char *arg)
> * optstr must contain the short options, and longopts the long options.
> * Other settings are found in global variables.
> */
> -static int generate_output(const struct getopt_control *ctl, char *argv[], int argc)
> +static int generate_output(struct getopt_control *ctl, char *argv[], int argc)
> {
> int exit_code = EXIT_SUCCESS; /* Assume everything will be OK */
> int opt;
> @@ -195,8 +205,10 @@ static int generate_output(const struct getopt_control *ctl, char *argv[], int a
> optind = 0;
>
> while ((opt =
> - (getopt_long_fp(argc, argv, ctl->optstr, ctl->long_options, &longindex)))
> - != EOF)
> + (getopt_long_fp
> + (argc, argv, ctl->optstr,
> + (const struct option *)ctl->long_options, &longindex)))
> + != EOF) {
> if (opt == '?' || opt == ':')
> exit_code = GETOPT_EXIT_CODE;
> else if (!ctl->quiet_output) {
> @@ -216,13 +228,19 @@ static int generate_output(const struct getopt_control *ctl, char *argv[], int a
> print_normalized(ctl, optarg ? optarg : "");
> }
> }
> -
> + }
> if (!ctl->quiet_output) {
> printf(" --");
> while (optind < argc)
> print_normalized(ctl, argv[optind++]);
> printf("\n");
> }
> + for (longindex = 0; longindex < ctl->long_options_nr; longindex++)
> + free(ctl->long_options[longindex].name);
> + free(ctl->long_options);
> + free(ctl->optstr);
> + if (ctl->free_name)
> + free(argv[0]);
> return exit_code;
> }
>
> @@ -373,9 +391,6 @@ int main(int argc, char *argv[])
> textdomain(PACKAGE);
> atexit(close_stdout);
>
> - add_longopt(&ctl, NULL, 0); /* init */
> - getopt_long_fp = getopt_long;
> -
> if (getenv("GETOPT_COMPATIBLE"))
> ctl.compatible = 1;
>
> @@ -391,6 +406,9 @@ int main(int argc, char *argv[])
> parse_error(_("missing optstring argument"));
> }
>
> + add_longopt(&ctl, NULL, 0); /* init */
> + getopt_long_fp = getopt_long;
> +
> if (argv[1][0] != '-' || ctl.compatible) {
> ctl.quote = 0;
> ctl.optstr = xmalloc(strlen(argv[1]) + 1);
> @@ -417,6 +435,7 @@ int main(int argc, char *argv[])
> case 'n':
> free(name);
> name = xstrdup(optarg);
> + ctl.free_name = 1;
> break;
> case 'q':
> ctl.quiet_errors = 1;
> @@ -428,6 +447,7 @@ int main(int argc, char *argv[])
> ctl.shell = shell_type(optarg);
> break;
> case 'T':
> + free(ctl.long_options);
> return TEST_EXIT_CODE;
> case 'u':
> ctl.quote = 0;
> --
> 2.7.2
next prev parent reply other threads:[~2016-03-13 12:12 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-13 10:31 [PATCH 00/10] pull: release v2.28 prep work Sami Kerola
2016-03-13 10:31 ` [PATCH 01/10] logger: fix memory leak [ASAN and valgrind] Sami Kerola
2016-03-13 10:31 ` [PATCH 02/10] getopt: fix memory leaks and integer overflows [ASAN & valgrind] Sami Kerola
2016-03-13 12:11 ` Yuriy M. Kaminskiy [this message]
2016-03-14 21:24 ` Sami Kerola
2016-03-13 10:31 ` [PATCH 03/10] lsipc, lslogins, rtcwake: replace asctime() with strftime() Sami Kerola
2016-03-13 11:28 ` Ruediger Meier
2016-03-13 13:20 ` Yuriy M. Kaminskiy
2016-03-14 12:08 ` Karel Zak
2016-03-13 10:31 ` [PATCH 04/10] isosize: stop unmeaningful printing errno message Sami Kerola
2016-03-13 10:31 ` [PATCH 05/10] setsid: fix argument count bug Sami Kerola
2016-03-13 10:31 ` [PATCH 06/10] bash-completion: fsck.cramfs, isosize: find files an argument Sami Kerola
2016-03-13 10:31 ` [PATCH 07/10] bash-completion: ipcmk: add missing completion file Sami Kerola
2016-03-13 10:31 ` [PATCH 08/10] bash-completion: lslogins: " Sami Kerola
2016-03-13 10:31 ` [PATCH 09/10] bash-completion: lsns: " Sami Kerola
2016-03-13 10:31 ` [PATCH 10/10] docs: update AUTHORS file Sami Kerola
2016-03-14 12:17 ` [PATCH 00/10] pull: release v2.28 prep work Karel Zak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=m37fh6inlh.fsf@gmail.com \
--to=yumkam@gmail.com \
--cc=util-linux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox