Commit 40fd84cca68db24f325e460a40dabe805e7a5d35

Patrick Steinhardt 2018-08-09T10:46:26

smart_pkt: explicitly avoid integer overflows when parsing packets When parsing data, progress or error packets, we need to copy the contents of the rest of the current packet line into the flex-array of the parsed packet. To keep track of this array's length, we then assign the remaining length of the packet line to the structure. We do have a mismatch of types here, as the structure's `len` field is a signed integer, while the length that we are assigning has type `size_t`. On nearly all platforms, this shouldn't pose any problems at all. The line length can at most be 16^4, as the line's length is being encoded by exactly four hex digits. But on a platforms with 16 bit integers, this assignment could cause an overflow. While such platforms will probably only exist in the embedded ecosystem, we still want to avoid this potential overflow. Thus, we now simply change the structure's `len` member to be of type `size_t` to avoid any integer promotion.

diff --git a/src/transports/smart.h b/src/transports/smart.h
index 057d7e6..8983dee 100644
--- a/src/transports/smart.h
+++ b/src/transports/smart.h
@@ -90,7 +90,7 @@ typedef struct {
 
 typedef struct {
 	git_pkt_type type;
-	int len;
+	size_t len;
 	char data[GIT_FLEX_ARRAY];
 } git_pkt_data;
 
@@ -98,7 +98,7 @@ typedef git_pkt_data git_pkt_progress;
 
 typedef struct {
 	git_pkt_type type;
-	int len;
+	size_t len;
 	char error[GIT_FLEX_ARRAY];
 } git_pkt_err;
 
diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c
index 7c5a3f2..c6cc65e 100644
--- a/src/transports/smart_pkt.c
+++ b/src/transports/smart_pkt.c
@@ -118,9 +118,9 @@ static int err_pkt(git_pkt **out, const char *line, size_t len)
 	GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
 	pkt = git__malloc(alloclen);
 	GITERR_CHECK_ALLOC(pkt);
-
 	pkt->type = GIT_PKT_ERR;
-	pkt->len = (int)len;
+	pkt->len = len;
+
 	memcpy(pkt->error, line, len);
 	pkt->error[len] = '\0';
 
@@ -142,7 +142,7 @@ static int data_pkt(git_pkt **out, const char *line, size_t len)
 	GITERR_CHECK_ALLOC(pkt);
 
 	pkt->type = GIT_PKT_DATA;
-	pkt->len = (int) len;
+	pkt->len = len;
 	memcpy(pkt->data, line, len);
 
 	*out = (git_pkt *) pkt;
@@ -163,7 +163,7 @@ static int sideband_progress_pkt(git_pkt **out, const char *line, size_t len)
 	GITERR_CHECK_ALLOC(pkt);
 
 	pkt->type = GIT_PKT_PROGRESS;
-	pkt->len = (int) len;
+	pkt->len = len;
 	memcpy(pkt->data, line, len);
 
 	*out = (git_pkt *) pkt;