Re: [PATCH v2] apply.c: fix -p argument parsing
- From
Junio C Hamano <gitster@pobox.com>
- Date
- Mar 10, 2026, 03:31 UTC
- Message-ID
- <xmqqwlzkxsv5.fsf@gitster.g>
- In-Reply-To
- <20260310005408.2022216-1-mroik@delayed.space>
Mirko Faina <mroik@delayed.space> writes:
Show 13 quoted lines
> "git apply" has an option -p that takes an integer as its argument. > Unfortunately the function apply_option_parse_p() in charge of parsing > this argument uses atoi() to convert from string to integer, which > allows a non-digit after the number (e.g. "1q") to be silently ignored. > As a consequence, an argument that does not begin with a digit silently > becomes a zero. Despite this command working fine when a non-positive > argument is passed, it might be useful for the end user to know that > their input contains non-digits that might've been unintended. > > Replace atoi() with strtol_i() to catch malformed inputs. > > Signed-off-by: Mirko Faina <mroik@delayed.space> > ---
Show 5 quoted lines
> apply.c | 3 ++- > t/t4103-apply-binary.sh | 19 +++++++++++++++++++ > t/t4103/patch | 16 ++++++++++++++++ > 3 files changed, 37 insertions(+), 1 deletion(-) > create mode 100644 t/t4103/patch
Curious. It is true that we need to parse the p_value correctly even when we are applying a binary patch, but the problem is not limited to binary patches, is it?
Show 14 quoted lines
> diff --git a/apply.c b/apply.c
> index b6dd1066a0..61df3bdcd0 100644
> --- a/apply.c
> +++ b/apply.c
> @@ -4981,7 +4981,8 @@ static int apply_option_parse_p(const struct option *opt,
>
> BUG_ON_OPT_NEG(unset);
>
> - state->p_value = atoi(arg);
> + if (strtol_i(arg, 10, &state->p_value) < 0 || state->p_value < 0)
> + die("<num> has to be a non-negative integer");
> state->p_value_known = 1;
> return 0;
> }Sounds sensible.
I briefly wondered if it would have negative fallouts to change the type of .p_value member to "unsigned int" and use strtol_ui() to parse it, but the amount of work this part of the code needs to do does not change that much, so such a change is of dubious value. It looks like the above draws the line at the right place to stop.
Great execution.
Show 14 quoted lines
> diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh > index 8e302a5a57..d9dc884946 100755 > --- a/t/t4103-apply-binary.sh > +++ b/t/t4103-apply-binary.sh > @@ -53,6 +53,25 @@ test_expect_success 'setup' ' > ) > ' > > +test_expect_success 'git apply -p 1 patch' ' > + test_when_finished "rm -rf result t" && > + git apply -p 1 $TEST_DIRECTORY/t4103/patch && > + ls -l | sed -e "/[[:space:]]t$/!d" >result && > + test_line_count = 1 result > +'
Is this saying "in the directory there must be only a single file whose name is t?" Wouldn't it be more readable and direct to do something like
test_path_is_dir t
or is there something more subtle going on here?
Show 7 quoted lines
> +test_expect_success 'git apply -p malformed patch' ' > + test_must_fail git apply -p malformed $TEST_DIRECTORY/t4103/patch > +' > > +test_expect_success 'git apply -p 2q patch' ' > + test_must_fail git apply -p 2q $TEST_DIRECTORY/t4103/patch > +'
If this did not fail and patch gets applied with some p_value that happens to be used when we fail to parse the number, then ...
> +test_expect_success 'git apply -p -1 patch' ' > + test_must_fail git apply -p -1 $TEST_DIRECTORY/t4103/patch > +'
... it would not be clear why this step fails. Perhaps with that same "unable to parse" p_value was used and this tried to create the same file as the previous step already created, or we detected parse failure. We cannot tell.
It probably is a good idea to prepare for the worst by doing something silly like
test_when_finished "rm -f t/test/test test/test test" &&
at the beginning of each of these tests so that we would clean up whatever we could leave behind? I dunno.
Show 25 quoted lines
> test_expect_success 'stat binary diff -- should not fail.' \ > 'git checkout main && > git apply --stat --summary B.diff' > diff --git a/t/t4103/patch b/t/t4103/patch > new file mode 100644 > index 0000000000..c4511bb708 > --- /dev/null > +++ b/t/t4103/patch > @@ -0,0 +1,16 @@ > +From 90ad11d5b2d437e82d4d992f72fb44c2227798b5 Mon Sep 17 00:00:00 2001 > +From: Mroik <mroik@delayed.space> > +Date: Mon, 9 Mar 2026 23:25:00 +0100 > +Subject: [PATCH] Test > + > +--- > + t/test/test | 0 > + 1 file changed, 0 insertions(+), 0 deletions(-) > + create mode 100644 t/test/test > + > +diff --git a/t/test/test b/t/test/test > +new file mode 100644 > +index 0000000000..e69de29bb2 > +-- > +2.53.0.851.ga537e3e6e9 > +