git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: Glen Choo <chooglen@google.com>
Cc: git@vger.kernel.org
Subject: Re: ab/config-multi-and-nonbool (was Re: What's cooking in git.git (Feb 2023, #04; Wed, 22))
Date: Thu, 23 Feb 2023 14:57:57 -0800	[thread overview]
Message-ID: <xmqqa61456ru.fsf@gitster.g> (raw)
In-Reply-To: <kl6lfsaw84vo.fsf@chooglen-macbookpro.roam.corp.google.com> (Glen Choo's message of "Thu, 23 Feb 2023 13:10:35 -0800")

Glen Choo <chooglen@google.com> writes:

> I would prefer to eject 06/10 [1] for now and leave it in for a future
> cleanup series. I haven't confirmed whether it's safe (the practical
> effect of that patch is that the *_get() functions can now return -1
> instead of 1, so the patch is safe if all callers only check if the
> return value is zero, and not whether it has a particular sign), and I
> don't think 06/10 is absolutely necessary to the series.

If somebody wants to help auditing potential breakage the patch in
question causes, "are callers happy to declare an error upon
non-zero return?" is not exactly sufficient.  While all of these
functions return 0 upon success, some of them return 1 on certain
cases while error() on other cases, and we need to ensure that the
callers are not behaving differently upon these values.

So let's see how many functions does the patch in question touch.

> diff --git a/config.c b/config.c
> index 1f654daf6f..74d453f5f9 100644
> --- a/config.c
> +++ b/config.c
> @@ -2449,86 +2449,93 @@ int git_configset_get(struct config_set *cs, const char *key)
>  int git_configset_get_string(struct config_set *cs, const char *key, char **dest)
>  {
>  	const char *value;
> -	if (!git_configset_get_value(cs, key, &value))
> -		return git_config_string((const char **)dest, key, value);
> -	else
> -		return 1;
> +	int ret;
> +
> +	if ((ret = git_configset_get_value(cs, key, &value)))
> +		return ret;
> +	return git_config_string((const char **)dest, key, value);
>  }

This used to return 1 when there is no such value, and get whatever
error signal git_config_string() gave if git_config_string() failed.

Luckily, git_configset_get_value() returns 1 when there is no such
value, so I think this hunk is an expensive-to-audit no-op.

>  static int git_configset_get_string_tmp(struct config_set *cs, const char *key,
>  					const char **dest)
>  {
>  	const char *value;
> -	if (!git_configset_get_value(cs, key, &value)) {
> -		if (!value)
> -			return config_error_nonbool(key);
> -		*dest = value;
> -		return 0;
> -	} else {
> -		return 1;
> -	}
> +	int ret;
> +
> +	if ((ret = git_configset_get_value(cs, key, &value)))
> +		return ret;
> +	if (!value)
> +		return config_error_nonbool(key);
> +	*dest = value;
> +	return 0;
>  }

Ditto.

>  int git_configset_get_int(struct config_set *cs, const char *key, int *dest)
>  {
>  	const char *value;
> -	if (!git_configset_get_value(cs, key, &value)) {
> -		*dest = git_config_int(key, value);
> -		return 0;
> -	} else
> -		return 1;
> +	int ret;
> +
> +	if ((ret = git_configset_get_value(cs, key, &value)))
> +		return ret;
> +	*dest = git_config_int(key, value);
> +	return 0;
>  }

Ditto.

>  int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned long *dest)
>  {
>  	const char *value;
> -	if (!git_configset_get_value(cs, key, &value)) {
> -		*dest = git_config_ulong(key, value);
> -		return 0;
> -	} else
> -		return 1;
> +	int ret;
> +
> +	if ((ret = git_configset_get_value(cs, key, &value)))
> +		return ret;
> +	*dest = git_config_ulong(key, value);
> +	return 0;
>  }

Ditto.

>  int git_configset_get_bool(struct config_set *cs, const char *key, int *dest)
>  {
>  	const char *value;
> -	if (!git_configset_get_value(cs, key, &value)) {
> -		*dest = git_config_bool(key, value);
> -		return 0;
> -	} else
> -		return 1;
> +	int ret;
> +
> +	if ((ret = git_configset_get_value(cs, key, &value)))
> +		return ret;
> +	*dest = git_config_bool(key, value);
> +	return 0;
>  }

Ditto.

>  int git_configset_get_bool_or_int(struct config_set *cs, const char *key,
>  				int *is_bool, int *dest)
>  {
>  	const char *value;
> -	if (!git_configset_get_value(cs, key, &value)) {
> -		*dest = git_config_bool_or_int(key, value, is_bool);
> -		return 0;
> -	} else
> -		return 1;
> +	int ret;
> +
> +	if ((ret = git_configset_get_value(cs, key, &value)))
> +		return ret;
> +	*dest = git_config_bool_or_int(key, value, is_bool);
> +	return 0;
>  }

Ditto.

>  int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest)
>  {
>  	const char *value;
> -	if (!git_configset_get_value(cs, key, &value)) {
> -		*dest = git_parse_maybe_bool(value);
> -		if (*dest == -1)
> -			return -1;
> -		return 0;
> -	} else
> -		return 1;
> +	int ret;
> +
> +	if ((ret = git_configset_get_value(cs, key, &value)))
> +		return ret;
> +	*dest = git_parse_maybe_bool(value);
> +	if (*dest == -1)
> +		return -1;
> +	return 0;
>  }

Ditto.

>  int git_configset_get_pathname(struct config_set *cs, const char *key, const char **dest)
>  {
>  	const char *value;
> -	if (!git_configset_get_value(cs, key, &value))
> -		return git_config_pathname(dest, key, value);
> -	else
> -		return 1;
> +	int ret;
> +
> +	if ((ret = git_configset_get_value(cs, key, &value)))
> +		return ret;
> +	return git_config_pathname(dest, key, value);
>  }

Ditto.

> @@ -2775,9 +2782,11 @@ int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestam
>  	const char *expiry_string;
>  	intmax_t days;
>  	timestamp_t when;
> +	int ret;
>  
> -	if (git_config_get_string_tmp(key, &expiry_string))
> -		return 1; /* no such thing */
> +	if ((ret = git_config_get_string_tmp(key, &expiry_string)))
> +		/* no such thing, or git_config_parse_key() failure etc. */
> +		return ret;

This was returning -1 for an error (at the end of the function), as
well as 1 for "no such thing".  Now, this is a breaking change if
any callers wanted to tell between -1 and 1.

Luckily, I think its two callers discard the error return; they
initialize expiry to some reasonable default and rely on the fact
that the expiry is not updated when these configuration API calls
did not find anything interesting.

> @@ -2827,15 +2837,14 @@ int git_config_get_index_threads(int *dest)

You can easily find output in "git grep git_config_get_index_threads"
that all four callers only care if they get 0 or not, so this one
should be safe.


      reply	other threads:[~2023-02-23 22:58 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-23  3:12 What's cooking in git.git (Feb 2023, #04; Wed, 22) Junio C Hamano
2023-02-23  5:51 ` mc/credential-helper-www-authenticate (Re: What's cooking in git.git (Feb 2023, #04; Wed, 22)) Victoria Dye
2023-02-23  9:48   ` Jeff King
2023-02-27 17:19     ` Matthew John Cheetham
2023-02-23 21:10 ` ab/config-multi-and-nonbool (was " Glen Choo
2023-02-23 22:57   ` Junio C Hamano [this message]

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

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=xmqqa61456ru.fsf@gitster.g \
    --to=gitster@pobox.com \
    --cc=chooglen@google.com \
    --cc=git@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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).