Skip to contentSkip to conversation

Avoid segmentation fault in git range-diff when diff.noprefix=true

PATCH Superseded Johannes Schindelin via GitGitGadget 5 participants 11 messages Oct 2, 2019 – Oct 3, 2019

lore
Share & tools
lore
#0 lore raw

cover Avoid segmentation fault in git range-diff when diff.noprefix=true

This PR was inspired by this bug report:
https://public-inbox.org/git/[email protected]/T/#me576615d7a151cf2ed46186c482fbd88f9959914

Johannes Schindelin (1):
range-diff: internally force diff.noprefix=false

 range-diff.c          | 3 ++-
 t/t3206-range-diff.sh | 4 ++++
 2 files changed, 6 insertions(+), 1 deletion(-)

base-commit: bc12974a897308fd3254cf0cc90319078fe45eea
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-373%2Fdscho%2Frange-diff-requires-diff-prefix-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-373/dscho/range-diff-requires-diff-prefix-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/373

Signature · 1 line
gitgitgadget
#1 lore raw

PATCH 1/1 range-diff: internally force `diff.noprefix=false`

From: Johannes Schindelin <[email protected]>

When parsing the diffs, range-diff expects to see the prefixes a/ and b/ in the diff headers.

These prefixes can be forced off via the config setting diff.noprefix=true. As range-diff is not prepared for that situation, this will cause a segmentation fault.

Let's avoid that by forcing diff.noprefix=false just for that all to git log that generates the diffs that range-diff wants to parse.

---
 range-diff.c          | 3 ++-
 t/t3206-range-diff.sh | 4 ++++
 2 files changed, 6 insertions(+), 1 deletion(-)
range-diff.c +2 -1
index ba1e9a4265..8cc348b4cb 100644
@@ -50,7 +50,8 @@ static int read_patches(const char *range, struct string_list *list)
 	int offset, len;
 	size_t size;
 
-	argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
+	argv_array_pushl(&cp.args, "-c", "diff.noprefix=false",
+			"log", "--no-color", "-p", "--no-merges",
 			"--reverse", "--date-order", "--decorate=no",
 			/*
 			 * Choose indicators that are not used anywhere
t/t3206-range-diff.sh +4 -0
index 0120f769f1..64b66f2094 100755
@@ -461,4 +461,8 @@ test_expect_success 'format-patch --range-diff as commentary' '
 	grep "> 1: .* new message" 0001-*
 '
 
+test_expect_success 'range-diff overrides diff.noprefix internally' '
+	git -c diff.noprefix=true range-diff HEAD^...
+'
+
 test_done
Signature · 1 line
gitgitgadget
#2 lore raw

Re: [PATCH 1/1] range-diff: internally force `diff.noprefix=false`

Quoted 8 lines · Johannes Schindelin via GitGitGadget

When parsing the diffs, range-diff expects to see the prefixes a/ and b/ in the diff headers.

These prefixes can be forced off via the config setting diff.noprefix=true. As range-diff is not prepared for that situation, this will cause a segmentation fault.

Let's avoid that by forcing diff.noprefix=false just for that all to

s/all/call/

Quoted 3 lines

git log that generates the diffs that range-diff wants to parse.

s/Noticed/Reported/ perhaps?

Quoted 1 line
Tested-by on v1 1/1
#3 lore raw

Re: [PATCH 1/1] range-diff: internally force `diff.noprefix=false`

In reply to Johannes Schindelin via GitGitGadget
Quoted 9 lines · Johannes Schindelin via GitGitGadget

From: Johannes Schindelin <[email protected]>

When parsing the diffs, range-diff expects to see the prefixes a/ and b/ in the diff headers.

These prefixes can be forced off via the config setting diff.noprefix=true. As range-diff is not prepared for that situation, this will cause a segmentation fault.

Quoted 5 lines

Let's avoid that by forcing diff.noprefix=false just for that all to git log that generates the diffs that range-diff wants to parse.

Thanks

Michal

Quoted 34 lines
---
 range-diff.c          | 3 ++-
 t/t3206-range-diff.sh | 4 ++++
 2 files changed, 6 insertions(+), 1 deletion(-)
range-diff.c +2 -1
index ba1e9a4265..8cc348b4cb 100644
@@ -50,7 +50,8 @@ static int read_patches(const char *range, struct string_list *list)
 	int offset, len;
 	size_t size;
 
-	argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
+	argv_array_pushl(&cp.args, "-c", "diff.noprefix=false",
+			"log", "--no-color", "-p", "--no-merges",
 			"--reverse", "--date-order", "--decorate=no",
 			/*
 			 * Choose indicators that are not used anywhere
t/t3206-range-diff.sh +4 -0
index 0120f769f1..64b66f2094 100755
@@ -461,4 +461,8 @@ test_expect_success 'format-patch --range-diff as commentary' '
 	grep "> 1: .* new message" 0001-*
 '
 
+test_expect_success 'range-diff overrides diff.noprefix internally' '
+	git -c diff.noprefix=true range-diff HEAD^...
+'
+
 test_done
Signature · 1 line
gitgitgadget
#4 lore raw

Re: [PATCH 1/1] range-diff: internally force `diff.noprefix=false`

In reply to Johannes Schindelin via GitGitGadget

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 4 lines · writes:

From: Johannes Schindelin <[email protected]>

When parsing the diffs, range-diff expects to see the prefixes a/ and b/ in the diff headers.

If so, passing src/dst prefix as command line option is a much better solution, I think. diff.noprefix may not stay to be (or it may already not to be) the only thing how the prefix gets chosen.

Quoted 19 lines
range-diff.c +2 -1
-	argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
+	argv_array_pushl(&cp.args, "-c", "diff.noprefix=false",
+			"log", "--no-color", "-p", "--no-merges",
 			"--reverse", "--date-order", "--decorate=no",
 			/*
 			 * Choose indicators that are not used anywhere
t/t3206-range-diff.sh +4 -0
index 0120f769f1..64b66f2094 100755
@@ -461,4 +461,8 @@ test_expect_success 'format-patch --range-diff as commentary' '
 	grep "> 1: .* new message" 0001-*
 '
 
+test_expect_success 'range-diff overrides diff.noprefix internally' '
+	git -c diff.noprefix=true range-diff HEAD^...
+'
+
 test_done
#5 lore raw

Re: [PATCH 1/1] range-diff: internally force `diff.noprefix=false`

Hi Junio,

Quoted 11 lines · Junio C Hamano

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 4 lines · writes:

From: Johannes Schindelin <[email protected]>

When parsing the diffs, range-diff expects to see the prefixes a/ and b/ in the diff headers.

If so, passing src/dst prefix as command line option is a much better solution, I think. diff.noprefix may not stay to be (or it may already not to be) the only thing how the prefix gets chosen.

Good point.

While at it, I invert the logic in v2: instead of forcing a prefix, I now force no prefix (and reduce the strip level from 1 to 0 when parsing the diff header).

Thanks,
Dscho

Quoted 21 lines
Quoted 20 lines
range-diff.c +2 -1
-	argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
+	argv_array_pushl(&cp.args, "-c", "diff.noprefix=false",
+			"log", "--no-color", "-p", "--no-merges",
 			"--reverse", "--date-order", "--decorate=no",
 			/*
 			 * Choose indicators that are not used anywhere
t/t3206-range-diff.sh +4 -0
index 0120f769f1..64b66f2094 100755
@@ -461,4 +461,8 @@ test_expect_success 'format-patch --range-diff as commentary' '
 	grep "> 1: .* new message" 0001-*
 '
 
+test_expect_success 'range-diff overrides diff.noprefix internally' '
+	git -c diff.noprefix=true range-diff HEAD^...
+'
+
 test_done
#6 lore raw

Re: [PATCH 1/1] range-diff: internally force `diff.noprefix=false`

Quoted 3 lines · Johannes Schindelin

While at it, I invert the logic in v2: instead of forcing a prefix, I now force no prefix (and reduce the strip level from 1 to 0 when parsing the diff header).

Ah, that approach would also work and may be conceptually cleaner than requiring a/ and b/ prefix and forcing them.

#7 lore raw

Re: [PATCH 1/1] range-diff: internally force `diff.noprefix=false`

In reply to Junio C Hamano
Quoted 11 lines · Junio C Hamano

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 4 lines · writes:

From: Johannes Schindelin <[email protected]>

When parsing the diffs, range-diff expects to see the prefixes a/ and b/ in the diff headers.

If so, passing src/dst prefix as command line option is a much better solution, I think. diff.noprefix may not stay to be (or it may already not to be) the only thing how the prefix gets chosen.

That is, "--src-prefix=a/ --dst-prefix=b/", so that configuration variables yet to be invented for setting prefixes different from a/ and b/ can also be overridden, not just diff.noprefix (ancient Git used l/ and k/ as src and dst prefix, IIRC).

#8 lore raw

v2 cover Avoid segmentation fault in git range-diff when diff.noprefix=true

In reply to Johannes Schindelin via GitGitGadget

This PR was inspired by this bug report:
https://public-inbox.org/git/[email protected]/T/#me576615d7a151cf2ed46186c482fbd88f9959914

Changes since v1:

* Use a command-line option instead of a command-line config setting.
* Instead of forcing a prefix, force no prefix (and adjust the strip level).
* Fix typo "all" -> "call" in the commit message (and adjust it to reflect the other changes since v1, too).

Johannes Schindelin (1):
range-diff: internally force diff.noprefix=true

 range-diff.c          | 3 ++-
 t/t3206-range-diff.sh | 4 ++++
 2 files changed, 6 insertions(+), 1 deletion(-)

base-commit: bc12974a897308fd3254cf0cc90319078fe45eea
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-373%2Fdscho%2Frange-diff-requires-diff-prefix-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-373/dscho/range-diff-requires-diff-prefix-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/373

Range-diff vs v1:

1: 1f84f92846 ! 1: 9993a607be range-diff: internally force diff.noprefix=false
@@ -1,6 +1,6 @@
Author: Johannes Schindelin <[email protected]>

- range-diff: internally force diff.noprefix=false
+ range-diff: internally force diff.noprefix=true

When parsing the diffs, range-diff expects to see the prefixes a/ and b/ in the diff headers.
@@ -9,25 +9,33 @@
diff.noprefix=true. As range-diff is not prepared for that situation, this will cause a segmentation fault.

- Let's avoid that by forcing diff.noprefix=false just for that all to
- git log that generates the diffs that range-diff wants to parse.
+ Let's avoid that by passing the --no-prefix option to the git log
+ process that generates the diffs that range-diff wants to parse.
+ And of course expect the output to have no prefixes, then.

- Noticed-by: Michal Suchánek <[email protected]>
+ Reported-by: Michal Suchánek <[email protected]>

diff --git a/range-diff.c b/range-diff.c
--- a/range-diff.c
+++ b/range-diff.c
@@
- int offset, len;
- size_t size;

-- argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
-+ argv_array_pushl(&cp.args, "-c", "diff.noprefix=false",
-+ "log", "--no-color", "-p", "--no-merges",
+ argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
"--reverse", "--date-order", "--decorate=no",
++ "--no-prefix",
/*
* Choose indicators that are not used anywhere
+ * else in diffs, but still look reasonable
+@@
+ if (!util->diff_offset)
+ util->diff_offset = buf.len;
+ line[len - 1] = '\n';
+- len = parse_git_diff_header(&root, &linenr, 1, line,
++ len = parse_git_diff_header(&root, &linenr, 0, line,
+ len, size, &patch);
+ if (len < 0)
+ die(_("could not parse git header '%.*s'"), (int)len, line);

diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh --- a/t/t3206-range-diff.sh

Signature · 1 line
gitgitgadget
#9 lore raw

PATCH v2 1/1 range-diff: internally force `diff.noprefix=true`

From: Johannes Schindelin <[email protected]>

When parsing the diffs, range-diff expects to see the prefixes a/ and b/ in the diff headers.

These prefixes can be forced off via the config setting diff.noprefix=true. As range-diff is not prepared for that situation, this will cause a segmentation fault.

Let's avoid that by passing the --no-prefix option to the git log process that generates the diffs that range-diff wants to parse. And of course expect the output to have no prefixes, then.

---
 range-diff.c          | 3 ++-
 t/t3206-range-diff.sh | 4 ++++
 2 files changed, 6 insertions(+), 1 deletion(-)
range-diff.c +2 -1
index ba1e9a4265..f2fc1e02c2 100644
@@ -52,6 +52,7 @@ static int read_patches(const char *range, struct string_list *list)
 
 	argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
 			"--reverse", "--date-order", "--decorate=no",
+			"--no-prefix",
 			/*
 			 * Choose indicators that are not used anywhere
 			 * else in diffs, but still look reasonable
@@ -111,7 +112,7 @@ static int read_patches(const char *range, struct string_list *list)
 			if (!util->diff_offset)
 				util->diff_offset = buf.len;
 			line[len - 1] = '\n';
-			len = parse_git_diff_header(&root, &linenr, 1, line,
+			len = parse_git_diff_header(&root, &linenr, 0, line,
 						    len, size, &patch);
 			if (len < 0)
 				die(_("could not parse git header '%.*s'"), (int)len, line);
t/t3206-range-diff.sh +4 -0
index 0120f769f1..64b66f2094 100755
@@ -461,4 +461,8 @@ test_expect_success 'format-patch --range-diff as commentary' '
 	grep "> 1: .* new message" 0001-*
 '
 
+test_expect_success 'range-diff overrides diff.noprefix internally' '
+	git -c diff.noprefix=true range-diff HEAD^...
+'
+
 test_done
Signature · 1 line
gitgitgadget
#10 lore raw

Re: [PATCH v2 1/1] range-diff: internally force `diff.noprefix=true`

"Johannes Schindelin via GitGitGadget" <[email protected]>

Quoted 5 lines · writes:

From: Johannes Schindelin <[email protected]>

When parsing the diffs, range-diff expects to see the prefixes a/ and b/ in the diff headers.

Quoted 7 lines

These prefixes can be forced off via the config setting diff.noprefix=true. As range-diff is not prepared for that situation, this will cause a segmentation fault.

Let's avoid that by passing the --no-prefix option to the git log process that generates the diffs that range-diff wants to parse. And of course expect the output to have no prefixes, then.

Looks good. Thanks.