Skip to content

Commit

Permalink
Free conf_opt, conf_arg upon error in config-file parsing
Browse files Browse the repository at this point in the history
This moves conf_opt and conf_arg into the "global" bsdtar struct because if
there's a config file error, we'll exit inside dooption(), leaving the
previous local variables conf_opt and conf_arg un-freed.
  • Loading branch information
gperciva committed Feb 25, 2016
1 parent 837c692 commit 5130e81
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 19 deletions.
43 changes: 24 additions & 19 deletions tar/bsdtar.c
Expand Up @@ -169,6 +169,8 @@ bsdtar_init(void)
bsdtar->substitution = NULL;
bsdtar->keyfile = NULL;
bsdtar->conffile = NULL;
bsdtar->conf_opt = NULL;
bsdtar->conf_arg = NULL;

/* We don't have bsdtar->progname yet, so we can't use bsdtar_errc. */
if (atexit(bsdtar_atexit)) {
Expand Down Expand Up @@ -196,6 +198,8 @@ bsdtar_atexit(void)
free(bsdtar->option_csv_filename);
free(bsdtar->keyfile);
free(bsdtar->conffile);
free(bsdtar->conf_opt);
free(bsdtar->conf_arg);

/* Free matching and (if applicable) substitution patterns. */
cleanup_exclusions(bsdtar);
Expand Down Expand Up @@ -1294,8 +1298,6 @@ configfile(struct bsdtar *bsdtar, const char *fname)
static int
configfile_helper(struct bsdtar *bsdtar, const char *line)
{
char * conf_opt;
char * conf_arg;
size_t optlen;
char * conf_arg_malloced;
size_t len;
Expand All @@ -1309,70 +1311,73 @@ configfile_helper(struct bsdtar *bsdtar, const char *line)
return (0);

/* Duplicate line. */
if ((conf_opt = strdup(line)) == NULL)
if ((bsdtar->conf_opt = strdup(line)) == NULL)
bsdtar_errc(bsdtar, 1, errno, "Out of memory");

/*
* Detect any trailing whitespace. This could happen before string
* duplication, but to reduce the number of diffs to a later version,
* we'll do it here.
*/
len = strlen(conf_opt);
len = strlen(bsdtar->conf_opt);
if ((len > 0) &&
((conf_opt[len - 1] == ' ') || (conf_opt[len - 1] == '\t'))) {
((bsdtar->conf_opt[len - 1] == ' ') ||
(bsdtar->conf_opt[len - 1] == '\t'))) {
bsdtar_warnc(bsdtar, 0,
"option contains trailing whitespace; future behaviour"
" may change for:\n %s", line);
}

/* Split line into option and argument if possible. */
optlen = strcspn(conf_opt, " \t");
optlen = strcspn(bsdtar->conf_opt, " \t");

/* Is there an argument? */
if (conf_opt[optlen]) {
if (bsdtar->conf_opt[optlen]) {
/* NUL-terminate the option name. */
conf_opt[optlen] = '\0';
bsdtar->conf_opt[optlen] = '\0';

/* Find the start of the argument. */
conf_arg = conf_opt + optlen + 1;
conf_arg += strspn(conf_arg, " \t");
bsdtar->conf_arg = bsdtar->conf_opt + optlen + 1;
bsdtar->conf_arg += strspn(bsdtar->conf_arg, " \t");

/*
* If the line is whitespace-terminated, there might not be
* an argument here after all.
*/
if (conf_arg[0] == '\0')
conf_arg = NULL;
if (bsdtar->conf_arg[0] == '\0')
bsdtar->conf_arg = NULL;
} else {
/* No argument. */
conf_arg = NULL;
bsdtar->conf_arg = NULL;
}

/*
* If we have an argument which starts with ~, and ${HOME} is
* defined, expand ~ to $HOME.
*/
if ((conf_arg != NULL) && (conf_arg[0] == '~') &&
if ((bsdtar->conf_arg != NULL) && (bsdtar->conf_arg[0] == '~') &&
(bsdtar->homedir != NULL)) {
/* Construct expanded argument string. */
if (asprintf(&conf_arg_malloced, "%s%s",
bsdtar->homedir, &conf_arg[1]) == -1)
bsdtar->homedir, &bsdtar->conf_arg[1]) == -1)
bsdtar_errc(bsdtar, 1, errno, "Out of memory");

/* Use the expanded argument string hereafter. */
conf_arg = conf_arg_malloced;
bsdtar->conf_arg = conf_arg_malloced;
} else {
conf_arg_malloced = NULL;
}

/* Process the configuration option. */
dooption(bsdtar, conf_opt, conf_arg, 1);
dooption(bsdtar, bsdtar->conf_opt, bsdtar->conf_arg, 1);

/* Free expanded argument or NULL. */
free(conf_arg_malloced);
free(bsdtar->conf_arg);
bsdtar->conf_arg = NULL;

/* Free memory allocated by strdup. */
free(conf_opt);
free(bsdtar->conf_opt);
bsdtar->conf_opt = NULL;

return (0);
}
Expand Down
2 changes: 2 additions & 0 deletions tar/bsdtar.h
Expand Up @@ -132,6 +132,8 @@ struct bsdtar {

/* Config-file parsing strings. */
char *conffile;
char *conf_opt;
char *conf_arg;

/* Used for --dryrun with tarsnap.conf.sample with a missing keyfile. */
int config_file_keyfile_failed;
Expand Down

0 comments on commit 5130e81

Please sign in to comment.