git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: git@vger.kernel.org
Cc: Junio C Hamano <gitster@pobox.com>, Heiko Voigt <hvoigt@hvoigt.net>
Subject: [PATCH] config: do not ungetc EOF
Date: Thu, 5 Feb 2015 01:53:28 -0500	[thread overview]
Message-ID: <20150205065327.GA7807@peff.net> (raw)

When we are parsing a config value, if we see a carriage
return, we fgetc the next character to see if it is a
line feed (in which case we silently drop the CR). If it
isn't, we then ungetc the character, and take the literal
CR.

But we never check whether we in fact got a character at
all. If the config file ends in CR, we will get EOF here,
and try to ungetc EOF. This works OK for a real stdio
stream. The ungetc returns an error, and the next fgetc will
then return EOF again.

However, our custom buffer-based stream is not so fortunate.
It happily rewinds the position of the stream by one
character, ignoring the fact that we fed it EOF. The next
fgetc call returns the final CR again, over and over, and we
end up in an infinite loop.

Signed-off-by: Jeff King <peff@peff.net>
---
Looks like this weirdness has been there for a long time, but we only
added the `git config --blob` code in v1.8.4.

I also notice that config_buf_ungetc does not actually ungetc the
character we give it; it just rewinds one character in the stream. This
is fine, because we always feed the last-retrieved character. I dunno if
it is worth fixing (it also would have fixed this infinite loop, but for
the wrong reason; we would have stuck "-1" back into the stream, and
retrieved it on the next fgetc rather than the same '\r' over and over).

 config.c               | 3 ++-
 t/t1307-config-blob.sh | 9 +++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/config.c b/config.c
index 752e2e2..2c63099 100644
--- a/config.c
+++ b/config.c
@@ -235,7 +235,8 @@ static int get_next_char(void)
 		/* DOS like systems */
 		c = cf->do_fgetc(cf);
 		if (c != '\n') {
-			cf->do_ungetc(c, cf);
+			if (c != EOF)
+				cf->do_ungetc(c, cf);
 			c = '\r';
 		}
 	}
diff --git a/t/t1307-config-blob.sh b/t/t1307-config-blob.sh
index fdc257e..3c6791e 100755
--- a/t/t1307-config-blob.sh
+++ b/t/t1307-config-blob.sh
@@ -67,4 +67,13 @@ test_expect_success 'parse errors in blobs are properly attributed' '
 	grep "HEAD:config" err
 '
 
+test_expect_success 'can parse blob ending with CR' '
+	printf "[some]key = value\\r" >config &&
+	git add config &&
+	git commit -m CR &&
+	echo value >expect &&
+	git config --blob=HEAD:config some.key >actual &&
+	test_cmp expect actual
+'
+
 test_done
-- 
2.3.0.rc1.287.g761fd19

             reply	other threads:[~2015-02-05  6:53 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-05  6:53 Jeff King [this message]
2015-02-05 21:00 ` [PATCH] config: do not ungetc EOF Jeff King
2015-02-05 21:16   ` Junio C Hamano
2015-02-05 21:28     ` Jeff King
2015-02-08 21:22       ` Heiko Voigt
2015-02-08 21:13   ` Heiko Voigt

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=20150205065327.GA7807@peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=hvoigt@hvoigt.net \
    /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).