summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Jeff King <peff@peff.net>2015-02-05 16:00:24 -0500
committerLibravatar Junio C Hamano <gitster@pobox.com>2015-02-05 13:16:55 -0800
commit1d0655c15ebf7dfb460466d058daab790ed285b2 (patch)
treef3468288bbf3c6339022cac78a94c4d819d11661
parentconfig: do not ungetc EOF (diff)
downloadtgif-1d0655c15ebf7dfb460466d058daab790ed285b2.tar.xz
config_buf_ungetc: warn when pushing back a random character
Our config code simulates a stdio stream around a buffer, but our fake ungetc() does not behave quite like the real one. In particular, we only rewind the position by one character, but do _not_ actually put the character from the caller into position. It turns out that this does not matter, because we only ever push back the character we just read. In other words, such an assignment would be a noop. But because the function is called ungetc, and because it takes a character parameter, it is a mistake waiting to happen. Actually assigning the character into the buffer would be ideal, but our pointer is actually a "const" copy of the buffer. We do not know who the real owner of the buffer is in this code, and would not want to munge their contents. Instead, we can simply add an assertion that matches what the current caller does, and will let us know if new callers are added that violate the contract. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--config.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/config.c b/config.c
index 5eca17b242..788970c6bc 100644
--- a/config.c
+++ b/config.c
@@ -63,8 +63,12 @@ static int config_buf_fgetc(struct config_source *conf)
static int config_buf_ungetc(int c, struct config_source *conf)
{
- if (conf->u.buf.pos > 0)
- return conf->u.buf.buf[--conf->u.buf.pos];
+ if (conf->u.buf.pos > 0) {
+ conf->u.buf.pos--;
+ if (conf->u.buf.buf[conf->u.buf.pos] != c)
+ die("BUG: config_buf can only ungetc the same character");
+ return c;
+ }
return EOF;
}