Re: [PATCH v3 8/9] config API: add "string" version of *_value_multi(), fix segfaults

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ævar Arnfjörð Bjarmason         <avarab@xxxxxxxxx> writes:

> Fix numerous and mostly long-standing segfaults in consumers of
> the *_config_*value_multi() API. As discussed in the preceding commit
> an empty key in the config syntax yields a "NULL" string, which these
> users would give to strcmp() (or similar), resulting in segfaults.
>
> As this change shows, most users users of the *_config_*value_multi()
> API didn't really want such an an unsafe and low-level API, let's give
> them something with the safety of git_config_get_string() instead.

I think the low-level API argument makes sense. All of the other
*_get_*() functions perform some kind of validation, e.g.
config_parse_*() for non-string types and config_error_nonbool() for
strings. In effect, *_get_value_multi() was returning raw output from
the config parser without any concern for the caller.

> This fix is similar to what the *_string() functions and others
> acquired in[1] and [2]. Namely introducing and using a safer
> "*_get_string_multi()" variant of the low-level "_*value_multi()"
> function.

This suggests to me that we should really get rid of
*_get_value_multi(), since nobody outside of config.c should need it. I
don't think we'd ever end up in a situation where the caller wants the
raw strings from the config parser (unless we had a config
key which accepted values of different types? but that sounds like a
terrible mistake).

> There are now three remaining files using the low-level API:
>
> - Two cases in "builtin/submodule--helper.c", where it's used safely
>   to see if any config exists.
> - One in "builtin/for-each-repo.c", which we'll convert in a
>   subsequent commit.
> - The "t/helper/test-config.c" code added in [3].

As you noted, the only remaining non-test caller of the low-level API is
builtin/submodule--helper.c, which maybe we could safely convert anyway
and get rid of the API altogether. I'm okay with that being a leftover
bit, but maybe that's worth noting in the CL.

> The callback pattern being used here will make it easy to introduce
> e.g. a "multi" variant which coerces its values to "bool", "int",
> "path" etc.

I like that this is quite easily extensible, e.g.

> diff --git a/config.c b/config.c
> index 0b07045ed8c..9bd43189c02 100644
> --- a/config.c
> +++ b/config.c
> @@ -2437,6 +2437,25 @@ int git_configset_get_value_multi(struct config_set *cs, const char *key,
>  	return 0;
>  }
>  
> +static int check_multi_string(struct string_list_item *item, void *util)
> +{
> +	return item->string ? 0 : config_error_nonbool(util);
> +}
> +
> +int git_configset_get_string_multi(struct config_set *cs, const char *key,
> +				   const struct string_list **dest)
> +{
> +	int ret;
> +
> +	if ((ret = git_configset_get_value_multi(cs, key, dest)))
> +		return ret;
> +	if ((ret = for_each_string_list((struct string_list *)*dest,
> +					check_multi_string, (void *)key)))
> +		return ret;
> +
> +	return 0;
> +}

we could just use config_parse_<typename>() if we want to add, e.g.
*_get_bool_multi().

And as a reasonableness check, config_error_nonbool() is what we use to
validate the *_get_string() functions, so it makes sense to reuse it for
the string list version.




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux