Re: [PATCH] diff: avoid stack-buffer-read-overrun for very long name

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jim Meyering <jim@xxxxxxxxxxxx> writes:

> Marcus Karlsson wrote:
> ...
>> Are there any guarantees that len1 and len2 does not exceed PATH_MAX?
>> Because if there aren't any then that function looks like it could need
>> even more improvements.
>
> Hi Marcus,
>
> You're right to ask.
> I've just confirmed that there is such a guarantee.

In any case, I think this is an old part of the codebase that has not
been updated to take advantage of newer API, partly because not many
people cared, and partly because there wasn't any serious bug there,
that can use some facelifting.  Wouldn't it make more sense to use
strbuf here, perhaps like this (not even compile tested), on top of your
patch?

 diff-no-index.c |   40 +++++++++++++++++-----------------------
 1 file changed, 17 insertions(+), 23 deletions(-)

diff --git a/diff-no-index.c b/diff-no-index.c
index 5cd3ff5..b44473e 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -52,7 +52,7 @@ static int get_mode(const char *path, int *mode)
 }
 
 static int queue_diff(struct diff_options *o,
-		const char *name1, const char *name2)
+		      const char *name1, const char *name2)
 {
 	int mode1 = 0, mode2 = 0;
 
@@ -63,10 +63,11 @@ static int queue_diff(struct diff_options *o,
 		return error("file/directory conflict: %s, %s", name1, name2);
 
 	if (S_ISDIR(mode1) || S_ISDIR(mode2)) {
-		char buffer1[PATH_MAX], buffer2[PATH_MAX];
+		struct strbuf buffer1 = STRBUF_INIT;
+		struct strbuf buffer2 = STRBUF_INIT;
 		struct string_list p1 = STRING_LIST_INIT_DUP;
 		struct string_list p2 = STRING_LIST_INIT_DUP;
-		int len1 = 0, len2 = 0, i1, i2, ret = 0;
+		int i1, i2, ret = 0;
 
 		if (name1 && read_directory(name1, &p1))
 			return -1;
@@ -76,19 +77,15 @@ static int queue_diff(struct diff_options *o,
 		}
 
 		if (name1) {
-			len1 = strlen(name1);
-			if (len1 > 0 && name1[len1 - 1] == '/')
-				len1--;
-			memcpy(buffer1, name1, len1);
-			buffer1[len1++] = '/';
+			strbuf_addstr(&buffer1, name1);
+			if (buffer1.len && buffer1.buf[buffer1.len - 1] != '/')
+				strbuf_addch(&buffer1, '/');
 		}
 
 		if (name2) {
-			len2 = strlen(name2);
-			if (len2 > 0 && name2[len2 - 1] == '/')
-				len2--;
-			memcpy(buffer2, name2, len2);
-			buffer2[len2++] = '/';
+			strbuf_addstr(&buffer2, name2);
+			if (buffer2.len && buffer2.buf[buffer2.len - 1] != '/')
+				strbuf_addch(&buffer2, '/');
 		}
 
 		for (i1 = i2 = 0; !ret && (i1 < p1.nr || i2 < p2.nr); ) {
@@ -100,31 +97,28 @@ static int queue_diff(struct diff_options *o,
 			else if (i2 == p2.nr)
 				comp = -1;
 			else
-				comp = strcmp(p1.items[i1].string,
-					p2.items[i2].string);
+				comp = strcmp(p1.items[i1].string, p2.items[i2].string);
 
 			if (comp > 0)
 				n1 = NULL;
 			else {
-				n1 = buffer1;
-				strncpy(buffer1 + len1, p1.items[i1++].string,
-						PATH_MAX - len1);
-				buffer1[PATH_MAX-1] = 0;
+				strbuf_addstr(&buffer1, p1.items[i1++].string);
+				n1 = buffer1.buf;
 			}
 
 			if (comp < 0)
 				n2 = NULL;
 			else {
-				n2 = buffer2;
-				strncpy(buffer2 + len2, p2.items[i2++].string,
-						PATH_MAX - len2);
-				buffer2[PATH_MAX-1] = 0;
+				strbuf_addstr(&buffer2, p2.items[i2++].string);
+				n2 = buffer2.buf;
 			}
 
 			ret = queue_diff(o, n1, n2);
 		}
 		string_list_clear(&p1, 0);
 		string_list_clear(&p2, 0);
+		strbuf_reset(&buffer1);
+		strbuf_reset(&buffer2);
 
 		return ret;
 	} else {
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]