diff mbox series

[v2] config.c: NULL check when reading protected config

Message ID pull.1299.v2.git.git.1658874067077.gitgitgadget@gmail.com (mailing list archive)
State Accepted
Commit 776f184893d2861a729aa4b91d69931036e03e4b
Headers show
Series [v2] config.c: NULL check when reading protected config | expand

Commit Message

Glen Choo July 26, 2022, 10:21 p.m. UTC
From: Glen Choo <chooglen@google.com>

In read_protected_config(), check whether each file name is NULL before
attempting to read it, and add a BUG() call to
git_config_from_file_with_options() to make this error easier to catch
in the future.

The NULL checks mirror what do_git_config_sequence() does (which
read_protected_config() is modeled after). Without these NULL checks,
multiple tests fail with "make SANITIZE=address", e.g. in the final test
of t4010, xdg_config is NULL causing us to call fopen(NULL).

Reported-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Glen Choo <chooglen@google.com>
---
    config.c: NULL check when reading protected config
    
    This fixes the SANITIZE=address failure on master, That was introduced
    by gc/bare-repo-discovery. Thanks again to Ævar for the original report
    [1] and for proposing a way to catch this in CI [2].
    
    Changes in v2:
    
     * Fix typo
     * Add BUG() to git_config_from_file_with_options()
    
    [1]
    https://lore.kernel.org/git/220725.861qu9oxl4.gmgdl@evledraar.gmail.com
    [2]
    https://lore.kernel.org/git/patch-1.1-e48b6853dd5-20220726T110716Z-avarab@gmail.com

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1299%2Fchooglen%2Fconfig%2Ffix-sanitize-address-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1299/chooglen/config/fix-sanitize-address-v2
Pull-Request: https://github.com/git/git/pull/1299

Range-diff vs v1:

 1:  17b4a489c69 ! 1:  ba51078418a config.c: NULL check when reading protected config
     @@ Commit message
          config.c: NULL check when reading protected config
      
          In read_protected_config(), check whether each file name is NULL before
     -    attempting to read it. This mirrors do_git_config_sequence() (which
     -    read_protected_config() is modelled after).
     +    attempting to read it, and add a BUG() call to
     +    git_config_from_file_with_options() to make this error easier to catch
     +    in the future.
      
     -    Without these NULL checks,
     -
     -     make SANITIZE=address test T=t0410*.sh
     -
     -    fails because xdg_config is NULL, causing us to call fopen(NULL).
     +    The NULL checks mirror what do_git_config_sequence() does (which
     +    read_protected_config() is modeled after). Without these NULL checks,
     +    multiple tests fail with "make SANITIZE=address", e.g. in the final test
     +    of t4010, xdg_config is NULL causing us to call fopen(NULL).
      
          Reported-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
          Signed-off-by: Glen Choo <chooglen@google.com>
      
       ## config.c ##
     +@@ config.c: int git_config_from_file_with_options(config_fn_t fn, const char *filename,
     + 	int ret = -1;
     + 	FILE *f;
     + 
     ++	if (!filename)
     ++		BUG("filename cannot be NULL");
     + 	f = fopen_or_warn(filename, "r");
     + 	if (f) {
     + 		ret = do_config_from_file(fn, CONFIG_ORIGIN_FILE, filename,
      @@ config.c: static void read_protected_config(void)
       	system_config = git_system_config();
       	git_global_config(&user_config, &xdg_config);


 config.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)


base-commit: 6a475b71f8c4ce708d69fdc9317aefbde3769e25

Comments

Ævar Arnfjörð Bjarmason July 27, 2022, 9:12 a.m. UTC | #1
On Tue, Jul 26 2022, Glen Choo via GitGitGadget wrote:

> From: Glen Choo <chooglen@google.com>

> +	if (!filename)
> +		BUG("filename cannot be NULL");

Looks good, but as an aside I wonder if we wouldn't get better code
analysis with "nonnull" for this sort of thing, but we can leave this
for now:
https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes
Junio C Hamano July 27, 2022, 3 p.m. UTC | #2
"Glen Choo via GitGitGadget" <gitgitgadget@gmail.com> writes:

> diff --git a/config.c b/config.c
> index 015bec360f5..e8ebef77d5c 100644
> --- a/config.c
> +++ b/config.c
> @@ -2645,9 +2647,12 @@ static void read_protected_config(void)
>  	system_config = git_system_config();
>  	git_global_config(&user_config, &xdg_config);
>  
> -	git_configset_add_file(&protected_config, system_config);
> -	git_configset_add_file(&protected_config, xdg_config);
> -	git_configset_add_file(&protected_config, user_config);
> +	if (system_config)
> +		git_configset_add_file(&protected_config, system_config);
> +	if (xdg_config)
> +		git_configset_add_file(&protected_config, xdg_config);
> +	if (user_config)
> +		git_configset_add_file(&protected_config, user_config);
>  	git_configset_add_parameters(&protected_config);

This does make it similar to the way how the primary "config
sequence" reader calls git_config_from_file(), so I do prefer the
patch as posted as a short-term "oops, we merged a buggy code that
segfaults and here is a fix" patch.

It however makes me wonder if it is simpler to allow passing NULL to
git_config_from_file_with_options() and make it silently turn into a
no-op.  I.e. instead of ...

> @@ -1979,6 +1979,8 @@ int git_config_from_file_with_options(config_fn_t fn, const char *filename,
>  	int ret = -1;
>  	FILE *f;
>  
> +	if (!filename)
> +		BUG("filename cannot be NULL");

... we could do

	if (!filename)
		return 0; /* successful no-op */

Even if there are codepaths that feed arbitrary pathnames given by
the end user, they wouldn't be passing NULL (they may pass an empty
string, or a filename that causes fopen() to fail), would they?

But that is something we should leave to a follow-up series, not
"oops, we need to fix it now" fix.

Thanks, will queue.

>  	f = fopen_or_warn(filename, "r");
>  	if (f) {
>  		ret = do_config_from_file(fn, CONFIG_ORIGIN_FILE, filename,
Glen Choo July 27, 2022, 4:52 p.m. UTC | #3
Junio C Hamano <gitster@pobox.com> writes:

> It however makes me wonder if it is simpler to allow passing NULL to
> git_config_from_file_with_options() and make it silently turn into a
> no-op.  I.e. instead of ...
>
>> @@ -1979,6 +1979,8 @@ int git_config_from_file_with_options(config_fn_t fn, const char *filename,
>>  	int ret = -1;
>>  	FILE *f;
>>  
>> +	if (!filename)
>> +		BUG("filename cannot be NULL");
>
> ... we could do
>
> 	if (!filename)
> 		return 0; /* successful no-op */
>
> Even if there are codepaths that feed arbitrary pathnames given by
> the end user, they wouldn't be passing NULL (they may pass an empty
> string, or a filename that causes fopen() to fail), would they?

Yeah, that's worth considering. I'm not sure how I feel about it yet,
but hopefully I find some time to dig around and form an opinion.

>
> But that is something we should leave to a follow-up series, not
> "oops, we need to fix it now" fix.
>
> Thanks, will queue.

Thanks :)

>
>>  	f = fopen_or_warn(filename, "r");
>>  	if (f) {
>>  		ret = do_config_from_file(fn, CONFIG_ORIGIN_FILE, filename,
Glen Choo July 27, 2022, 5:07 p.m. UTC | #4
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> On Tue, Jul 26 2022, Glen Choo via GitGitGadget wrote:
>
>> From: Glen Choo <chooglen@google.com>
>
>> +	if (!filename)
>> +		BUG("filename cannot be NULL");
>
> Looks good, but as an aside I wonder if we wouldn't get better code
> analysis with "nonnull" for this sort of thing, but we can leave this
> for now:
> https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes

Interesting. I wonder how good the analysis is vs the cost, e.g. it's
useful if it detects _maybe_ NULL variables, but it might be too
expensive if it requires us to mark all of our variables as non-NULL.
diff mbox series

Patch

diff --git a/config.c b/config.c
index 015bec360f5..e8ebef77d5c 100644
--- a/config.c
+++ b/config.c
@@ -1979,6 +1979,8 @@  int git_config_from_file_with_options(config_fn_t fn, const char *filename,
 	int ret = -1;
 	FILE *f;
 
+	if (!filename)
+		BUG("filename cannot be NULL");
 	f = fopen_or_warn(filename, "r");
 	if (f) {
 		ret = do_config_from_file(fn, CONFIG_ORIGIN_FILE, filename,
@@ -2645,9 +2647,12 @@  static void read_protected_config(void)
 	system_config = git_system_config();
 	git_global_config(&user_config, &xdg_config);
 
-	git_configset_add_file(&protected_config, system_config);
-	git_configset_add_file(&protected_config, xdg_config);
-	git_configset_add_file(&protected_config, user_config);
+	if (system_config)
+		git_configset_add_file(&protected_config, system_config);
+	if (xdg_config)
+		git_configset_add_file(&protected_config, xdg_config);
+	if (user_config)
+		git_configset_add_file(&protected_config, user_config);
 	git_configset_add_parameters(&protected_config);
 
 	free(system_config);