git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eric Sunshine <sunshine@sunshineco.com>
To: Hoyoung Lee <lhywkd22@gmail.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH v3 2/2] t/helper/test-delta: fix possible resource leak and ensure safe cleanup
Date: Wed, 23 Jul 2025 03:28:05 -0400	[thread overview]
Message-ID: <CAPig+cR-r=CeEaSTeWsX00MLCSRJUUVXMUWS6Ui-HQcR_qMGJA@mail.gmail.com> (raw)
In-Reply-To: <20250722174102.1876197-3-lhywkd22@gmail.com>

On Tue, Jul 22, 2025 at 1:41 PM Hoyoung Lee <lhywkd22@gmail.com> wrote:
> Initialize `fd` to -1 and unify all `open()`-related `close()` calls
> under a single cleanup label. This prevents undefined behavior when
> `fd` is used without initialization in error paths.

It's not clear what this means. As far as I can tell, the original
code never used an uninitialized `fd` in error paths.

> The cleanup logic now safely avoids calling `close()` on invalid
> descriptors and ensures consistent resource management.

Again, it's not clear what this means. Although your previous version
of this patch did add a call to close() with an invalid descriptor,
the original code did not do so. So, the above statement seems to be
misleading.

Those issues aside, the patch itself has problems, some minor, such as
making the code a bit confusing or misleading, and some major, such as
calling close() on an already closed descriptor.

Unfortunately, there are enough important context lines missing from
the patch itself that, instead of directly reviewing the patch
directly, I'm going to review the code following the application of
your patch...

>   int fd = -1;

This new initialization (-1) is useless because...

>   if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p"))) {
>     fprintf(stderr, "usage: %s\n", usage_str);
>     return 1;
>   }
>
>   fd = open(argv[2], O_RDONLY);

...the very first time `fd` is mentioned (aside from the declaration)
is here where it is unconditionally assigned a value. Thus, the -1
initialization is wasted (and potentially confusing for readers).

>   if (fd < 0 || fstat(fd, &st)) {
>     perror(argv[2]);
>     goto cleanup;
>   }

Okay, no problem here. The `if (fd >= 0) close(fd)` you added to the
"cleanup" action handles both the cases here when `fd` might be
negative after the open() call or a valid descriptor.

>   from_size = st.st_size;
>   from_buf = xmalloc(from_size);
>   if (read_in_full(fd, from_buf, from_size) < 0) {
>     perror(argv[2]);
>     goto cleanup;
>   }
>   close(fd);

Here `fd` is closed manually which is good because...

>   fd = open(argv[3], O_RDONLY);

...this code immediately assigns it a new value.

>   if (fd < 0 || fstat(fd, &st)) {
>     perror(argv[3]);
>     goto cleanup;
>   }

Okay for the same reason mentioned above.

>   data_size = st.st_size;
>   data_buf = xmalloc(data_size);
>   if (read_in_full(fd, data_buf, data_size) < 0) {
>     perror(argv[3]);
>     goto cleanup;
>   }
>   close(fd);

The descriptor is closed manually (again) because a subsequent open()
call is going to reuse the variable. However...

>   if (argv[1][1] == 'd')
>     out_buf = diff_delta(from_buf, from_size,
>              data_buf, data_size,
>              &out_size, 0);
>   else
>     out_buf = patch_delta(from_buf, from_size,
>               data_buf, data_size,
>               &out_size);
>   if (!out_buf) {
>     fprintf(stderr, "delta operation failed (returned NULL)\n");
>     goto cleanup;
>   }

...although `fd` was closed, it still holds the previously-open
non-negative file descriptor, which means that this `goto cleanup`...

>   fd = open (argv[4], O_WRONLY|O_CREAT|O_TRUNC, 0666);
>   if (fd < 0 || write_in_full(fd, out_buf, out_size) < 0) {
>     perror(argv[4]);
>     goto cleanup;
>   }
>
>   ret = 0;
> cleanup:
>   free(from_buf);
>   free(data_buf);
>   free(out_buf);
>
>   if (fd >= 0)
>     close(fd);

...will arrive here and the condition will evaluate to "true",
resulting in the already-closed descriptor being closed again.

>   return ret;

  reply	other threads:[~2025-07-23  7:28 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-22 17:41 [PATCH v3 0/2] fix resource leaks in test helpers Hoyoung Lee
2025-07-22 17:41 ` [PATCH v3 1/2] t/helper/test-truncate: close file descriptor after truncation Hoyoung Lee
2025-07-22 21:48   ` Junio C Hamano
2025-07-22 17:41 ` [PATCH v3 2/2] t/helper/test-delta: fix possible resource leak and ensure safe cleanup Hoyoung Lee
2025-07-23  7:28   ` Eric Sunshine [this message]
2025-07-23  7:55     ` Jeff King
2025-07-23  8:06       ` Jeff King
2025-07-23  8:17         ` Eric Sunshine
2025-07-23 23:59         ` Jeff King
2025-07-24  0:00           ` [PATCH 1/3] test-delta: handle errors with die() Jeff King
2025-07-24  0:02           ` [PATCH 2/3] test-delta: use strbufs to hold input files Jeff King
2025-07-24  0:03           ` [PATCH 3/3] test-delta: close output descriptor after use Jeff King
2025-07-23  8:11       ` [PATCH v3 2/2] t/helper/test-delta: fix possible resource leak and ensure safe cleanup Eric Sunshine
2025-07-23  8:46         ` Jeff King
2025-07-23 16:37           ` Eric Sunshine
2025-07-23 17:11         ` Junio C Hamano
2025-07-23 16:48       ` Junio C Hamano
2025-07-23 16:44     ` Junio C Hamano

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

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

  git send-email \
    --in-reply-to='CAPig+cR-r=CeEaSTeWsX00MLCSRJUUVXMUWS6Ui-HQcR_qMGJA@mail.gmail.com' \
    --to=sunshine@sunshineco.com \
    --cc=git@vger.kernel.org \
    --cc=lhywkd22@gmail.com \
    /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.
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 NNTP newsgroup(s).