git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] gc: fix off-by-one in append_option
@ 2012-04-17 23:32 Jeff King
  2012-04-18 19:18 ` Jeff King
  0 siblings, 1 reply; 8+ messages in thread
From: Jeff King @ 2012-04-17 23:32 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

The append_option function appends a string to a
NULL-terminated array, taking care not to overflow the
array. However, it's comparison was over-cautious, and
checked that there was enough room for two options, not one
(plus the NULL-terminator, of course).  This could cause
very long command-lines (e.g., "git gc --aggressive" when
"--unpack-unreachable" is in use) to hit the limit.

Signed-off-by: Jeff King <peff@peff.net>
---
I noticed this when trying a "git gc --aggressive" with the current
"next". The culprit is my 7e52f56 (gc: do not explode objects which will
be immediately pruned) which adds two extra options to the repack
invocation.

This patch is enough to fix it, as the current limit is big enough when
the off-by-one error is removed.  The currentl limit is 10, which
appears to have been pulled out of thin air by 0d7566a (Add --aggressive
option to 'git gc', 2007-05-09) as "big enough".

Obviously this would be much nicer with argv_array. Unfortunately, I
don't think there is a way to have a nice initializer with argv_array.
The current code looks like this:

  static const char *argv_repack[MAX_ADD] = {"repack", "-d", "-l", NULL };

and in an ideal world you would have something like:

  static struct argv_array argv_repack = ARGV_ARRAY_INIT("repack", "-d", "-l");

Of course that would involve variadic macros, which we can't count on.
But even beyond that it's tough, because you are mixing static
initialization with a dynamic structure. You can hack around that by
copying the defaults during first push, but that's extra complexity, and
the syntax is still ugly.

What do you think of just:

  static struct argv_array argv_repack;
  [...]
  argv_init_from_string(&argv_repack, "repack -d -l");

I prefer static initialization when we can do it, but it just seems like
too much trouble in this case.

 builtin/gc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/gc.c b/builtin/gc.c
index 1bc2fe3..d80a961 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -74,7 +74,7 @@ static void append_option(const char **cmd, const char *opt, int max_length)
 	for (i = 0; cmd[i]; i++)
 		;
 
-	if (i + 2 >= max_length)
+	if (i + 1 >= max_length)
 		die(_("Too many options specified"));
 	cmd[i++] = opt;
 	cmd[i] = NULL;
-- 
1.7.9.6.8.g992e5

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-04-18 21:10 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-17 23:32 [PATCH] gc: fix off-by-one in append_option Jeff King
2012-04-18 19:18 ` Jeff King
2012-04-18 19:34   ` Junio C Hamano
2012-04-18 20:21     ` Jeff King
2012-04-18 21:07       ` Jeff King
2012-04-18 21:08         ` [PATCH 1/3] argv-array: refactor empty_argv initialization Jeff King
2012-04-18 21:10         ` [PATCH 2/3] argv-array: add a new "pushl" method Jeff King
2012-04-18 21:10         ` [PATCH 3/3] gc: use argv-array for sub-commands Jeff King

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).