threads / patch / 2899

patchoff-by-one bugs found by valgrind

Subject: [PATCH] off-by-one bugs found by valgrind

## tl;dr

4 messages between Dec 21, 2005 and Dec 21, 2005. Diffs are folded; open one to read it.

replies: 3people: 3as markdown or json

Pavel Roskin· Dec 21, 2005, 20:35 UTC · lore

Insufficient memory is allocated in index-pack.c to hold the *.idx name. One more byte should be allocated to hold the terminating 0.

quote_c_style_counted() in quote.c uses a dangerous construct, when a variable is incremented once and used twice in the same expression. Convert this construct to a more traditional form of the for loop.

Signed-off-by: Pavel Roskin <proski@gnu.org>
Show changes to 2 files +5 −3

index-pack.c, quote.c

diff --git a/index-pack.c b/index-pack.c
index 785fe71..d4ce3af 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -440,7 +440,7 @@ int main(int argc, char **argv)
 		if (len < 5 || strcmp(pack_name + len - 5, ".pack"))
 			die("packfile name '%s' does not end with '.pack'",
 			    pack_name);
-		index_name_buf = xmalloc(len - 1);
+		index_name_buf = xmalloc(len);
 		memcpy(index_name_buf, pack_name, len - 5);
 		strcpy(index_name_buf + len - 5, ".idx");
 		index_name = index_name_buf;
diff --git a/quote.c b/quote.c
index 76eb144..00297b5 100644
--- a/quote.c
+++ b/quote.c
@@ -126,8 +126,10 @@ static int quote_c_style_counted(const c
 
 	if (!no_dq)
 		EMIT('"');
-	for (sp = name; (ch = *sp++) && (sp - name) <= namelen; ) {
-
+	for (sp = name; sp < name + namelen; sp++) {
+		ch = *sp;
+		if (!ch)
+			break;
 		if ((ch < ' ') || (ch == '"') || (ch == '\\') ||
 		    (ch == 0177)) {
 			needquote = 1;
-- 
Regards,
Pavel Roskin
Junio C Hamano· Dec 21, 2005, 20:59 UTC · re: Pavel Roskin · lore

Re: [PATCH] off-by-one bugs found by valgrind

Pavel Roskin <proski@gnu.org> writes:
> Insufficient memory is allocated in index-pack.c to hold the *.idx name.
> One more byte should be allocated to hold the terminating 0.
Thanks.
> quote_c_style_counted() in quote.c uses a dangerous construct, when a
> variable is incremented once and used twice in the same expression.
Sorry, I do not follow you.  Isn't && a sequence point?
> -	for (sp = name; (ch = *sp++) && (sp - name) <= namelen; ) {
> -
> +	for (sp = name; sp < name + namelen; sp++) {
H. Peter Anvin· Dec 21, 2005, 21:17 UTC · re: Junio C Hamano · lore

Re: [PATCH] off-by-one bugs found by valgrind

Junio C Hamano wrote:
Show 14 quoted lines
> Pavel Roskin <proski@gnu.org> writes:
> 
> 
>>Insufficient memory is allocated in index-pack.c to hold the *.idx name.
>>One more byte should be allocated to hold the terminating 0.
> 
> Thanks.
> 
> 
>>quote_c_style_counted() in quote.c uses a dangerous construct, when a
>>variable is incremented once and used twice in the same expression.
> 
> Sorry, I do not follow you.  Isn't && a sequence point?
> 

&& is a sequence point. The code is techically fine, but it's harder than necessary to read.

	-hpa
Pavel Roskin· Dec 21, 2005, 21:47 UTC · re: H. Peter Anvin · lore

Re: [PATCH] off-by-one bugs found by valgrind

On Wed, 2005-12-21 at 13:17 -0800, H. Peter Anvin wrote:
> >>quote_c_style_counted() in quote.c uses a dangerous construct, when a
> >>variable is incremented once and used twice in the same expression.
> > 
> > Sorry, I do not follow you.  Isn't && a sequence point?
The patch is right, but my comment was wrong, sorry.

The actual problem detected by valgrind is that sp is dereferenced before it's checked for the upper boundary. So, if e.g. namelen is 6, the code reads name[6] into ch and then leaves the loop.

> && is a sequence point.  The code is techically fine, but it's harder 
> than necessary to read.
That alone should be a good reason to apply this patch.
-- 
Regards,
Pavel Roskin

← back to recent threads