"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Omar Polo <op@omarpolo.com>
Subject:
Re: got patch vs git diff with renames
To:
Omar Polo <op@omarpolo.com>
Cc:
Stefan Sperling <stsp@stsp.name>, gameoftrees@openbsd.org
Date:
Fri, 13 May 2022 13:06:19 +0200

Download raw body.

Thread
Omar Polo <op@omarpolo.com> wrote:
> Stefan Sperling <stsp@stsp.name> wrote:
> > On Fri, Apr 29, 2022 at 11:08:41AM +0200, Omar Polo wrote:
> > > [...]
> > > P.S.: i forgot that we supported the rename with an empty hunk "@@ -0,0
> > > +0,0 @@".  Since git doesn't seem to handle it, and neither patch(1), I
> > > intend to remove the support for it, but again, in a follow-up commit :)
> > 
> > Agreed. If nobody else uses such empty hunks as a rename marker, then we
> > shouldn't rely on this either.
> 
> here's the diff for it.
> 
> I'm still undecided if checking for empty hunks in patch.c too as a
> safety net is a good idea given that got-read-patch now fails for those.
> 
> The rationale would be that if got-read-patch somehow misses that case,
> we end up with a NULL h->lines that causes a segfault in patch_file.
> Maybe we can just assume the libexec helper sends good data?  I'm
> probably too paranoic.

*ping*

-----------------------------------------------
commit 88043ce8225a269051f48c557de2b4ae33060bc8 (emptyhunks)
from: Omar Polo <op@omarpolo.com>
date: Fri May 13 11:05:24 2022 UTC
 
 got patch: fail when reading empty hunks
 
diff 44ad2c77dcb79fc8620bd95c1bc7cb6e4fda25fb d83b9d4ef9fc401e23d73d0337cb506e6269fd47
blob - 9a66825918efbd6b934add0ed0636e397fb31edd
blob + d7d7afe8b98daec948e859725cc2686ec675b8f5
--- lib/patch.c
+++ lib/patch.c
@@ -215,9 +215,12 @@ recv_patch(struct imsgbuf *ibuf, int *done, struct got
 
 		switch (imsg.hdr.type) {
 		case GOT_IMSG_PATCH_DONE:
+			if (h != NULL && h->len == 0)
+				err = got_error(GOT_ERR_PATCH_MALFORMED);
 			goto done;
 		case GOT_IMSG_PATCH_HUNK:
-			if (h != NULL && (h->old_nonl || h->new_nonl)) {
+			if (h != NULL &&
+			    (h->len == 0 || h->old_nonl || h->new_nonl)) {
 				err = got_error(GOT_ERR_PATCH_MALFORMED);
 				goto done;
 			}
@@ -470,9 +473,6 @@ patch_file(struct got_patch *p, const char *path, FILE
 
 	copypos = 0;
 	STAILQ_FOREACH(h, &p->head, entries) {
-		if (h->lines == NULL)
-			break;
-
 	tryagain:
 		err = locate_hunk(orig, h, &pos, &lineno);
 		if (err != NULL && err->code == GOT_ERR_HUNK_FAILED)
blob - 074b5cb8fcd2962ea86e2b829b0b0817f69b8835
blob + 96d97895737dd64fc733a5a4dcbcc4b195ffe58e
--- libexec/got-read-patch/got-read-patch.c
+++ libexec/got-read-patch/got-read-patch.c
@@ -267,7 +267,8 @@ parse_hdr(char *s, int *done, struct got_imsg_patch_hu
 	if (hdr->oldfrom >= LONG_MAX - hdr->oldlines ||
 	    hdr->newfrom >= LONG_MAX - hdr->newlines ||
 	    /* not so sure about this one */
-	    hdr->oldlines >= LONG_MAX - hdr->newlines - 1)
+	    hdr->oldlines >= LONG_MAX - hdr->newlines - 1 ||
+	    (hdr->oldlines == 0 && hdr->newlines == 0))
 		return got_error(GOT_ERR_PATCH_MALFORMED);
 
 	if (hdr->oldlines == 0) {
blob - b30e9e02052c205e40d442f72d8988369b6eea06
blob + 155c33f0173f68f8c1375feaf38ffc73113b0b7e
--- regress/cmdline/patch.sh
+++ regress/cmdline/patch.sh
@@ -537,6 +537,40 @@ EOF
 		return 1
 	fi
 
+	# empty hunk
+	cat <<EOF > $testroot/wt/patch
+diff --git a/alpha b/iota
+--- a/alpha
++++ b/iota
+@@ -0,0 +0,0 @@
+EOF
+
+	(cd $testroot/wt && got patch patch) \
+		 > $testroot/stdout \
+		2> $testroot/stderr
+	ret=$?
+	if [ $ret -eq 0 ]; then
+		echo "got managed to apply an invalid patch"
+		test_done $testroot 1
+		return 1
+	fi
+
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done $testroot $ret
+		return 1
+	fi
+
+	cmp -s $testroot/stderr.expected $testroot/stderr
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		diff -u $testroot/stderr.expected $testroot/stderr
+		test_done $testroot $ret
+		return 1
+	fi
+
 	test_done $testroot $ret
 }