# [PATCH] server-info: avoid calling fclose(3) twice in update_info_file()

2 messages from 2017-04-16 to 2017-04-17. Participants: René Scharfe, Jeff King.
Thread: https://gitlist.dev/t/45713

## René Scharfe, 2017-04-16 16:55

Subject: [PATCH] server-info: avoid calling fclose(3) twice in update_info_file()
Message-ID: <137d732f-7a23-8a8a-9f2b-7f16bb361c5a@web.de>
URL: https://gitlist.dev/e/137d732f-7a23-8a8a-9f2b-7f16bb361c5a%40web.de

```
If an error occurs when or after closing the stream we call fclose(3)
again in the error handler.  The second call can exhibit undefined
behavior, so make sure to call fclose(3) at most once.  Also avoid
calling close(2) after fd has been successfully associated with the
stream, as fclose(3) has become responsible for doing that beyond
this point.

Found with Cppcheck.

Signed-off-by: Rene Scharfe <l.s.r@web.de>
---
 server-info.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/server-info.c b/server-info.c
index 7bc4e75d22..f6c1a3dfb0 100644
--- a/server-info.c
+++ b/server-info.c
@@ -14,19 +14,21 @@ static int update_info_file(char *path, int (*generate)(FILE *))
 	char *tmp = mkpathdup("%s_XXXXXX", path);
 	int ret = -1;
 	int fd = -1;
-	FILE *fp = NULL;
+	FILE *fp = NULL, *to_close;
 
 	safe_create_leading_directories(path);
 	fd = git_mkstemp_mode(tmp, 0666);
 	if (fd < 0)
 		goto out;
-	fp = fdopen(fd, "w");
+	to_close = fp = fdopen(fd, "w");
 	if (!fp)
 		goto out;
+	fd = -1;
 	ret = generate(fp);
 	if (ret)
 		goto out;
-	if (fclose(fp))
+	fp = NULL;
+	if (fclose(to_close))
 		goto out;
 	if (adjust_shared_perm(tmp) < 0)
 		goto out;
-- 
2.12.2


```

## Jeff King, 2017-04-17 01:37

Subject: Re: [PATCH] server-info: avoid calling fclose(3) twice in update_info_file()
Message-ID: <20170417013733.ga362sz67n7vbt32@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20170417013733.ga362sz67n7vbt32%40sigill.intra.peff.net
In-Reply-To: <137d732f-7a23-8a8a-9f2b-7f16bb361c5a@web.de>

```
On Sun, Apr 16, 2017 at 06:55:58PM +0200, René Scharfe wrote:

> If an error occurs when or after closing the stream we call fclose(3)
> again in the error handler.  The second call can exhibit undefined
> behavior, so make sure to call fclose(3) at most once.

Yikes. Good catch.

> Also avoid
> calling close(2) after fd has been successfully associated with the
> stream, as fclose(3) has become responsible for doing that beyond
> this point.

Yeah, the "else if" in the error-code was supposed to handle that, but
it comes back when you fix the double-fclose by setting fp to NULL.

So the whole thing looks good to me. Thanks for cleaning up my mess.

-Peff

```
