From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jeff King Subject: [PATCH] config: do not ungetc EOF Date: Thu, 5 Feb 2015 01:53:28 -0500 Message-ID: <20150205065327.GA7807@peff.net> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Cc: Junio C Hamano , Heiko Voigt To: git@vger.kernel.org X-From: git-owner@vger.kernel.org Thu Feb 05 07:53:39 2015 Return-path: Envelope-to: gcvg-git-2@plane.gmane.org Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1YJGJk-000859-1g for gcvg-git-2@plane.gmane.org; Thu, 05 Feb 2015 07:53:36 +0100 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754743AbbBEGxb (ORCPT ); Thu, 5 Feb 2015 01:53:31 -0500 Received: from cloud.peff.net ([50.56.180.127]:45303 "HELO cloud.peff.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1751080AbbBEGxb (ORCPT ); Thu, 5 Feb 2015 01:53:31 -0500 Received: (qmail 7015 invoked by uid 102); 5 Feb 2015 06:53:31 -0000 Received: from Unknown (HELO peff.net) (10.0.1.1) by cloud.peff.net (qpsmtpd/0.84) with SMTP; Thu, 05 Feb 2015 00:53:31 -0600 Received: (qmail 28329 invoked by uid 107); 5 Feb 2015 06:53:30 -0000 Received: from sigill.intra.peff.net (HELO sigill.intra.peff.net) (10.0.0.7) by peff.net (qpsmtpd/0.84) with SMTP; Thu, 05 Feb 2015 01:53:30 -0500 Received: by sigill.intra.peff.net (sSMTP sendmail emulation); Thu, 05 Feb 2015 01:53:28 -0500 Content-Disposition: inline Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Archived-At: 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 --- 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