Subject: [PATCH] squash! reftable: reading/writing blocks

From: Carlo Marcelo Arenas Belón <[email-masked]>
Date: Thu, 30 Sep 2021 05:23:52 -0700

Avoid a possible infinite loop in platforms where size_t > long
by using instead the required type and checking for overflow
before doubling.

Increase slightly the initial buffer based on the zlib(1)
recommendation to reduce the likelihood of this code triggering,
and add some error checking to the memory allocation.

[1] https://refspecs.linuxbase.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/zlib-compress2-1.html

Signed-off-by: Carlo Marcelo Arenas Belón <[email-masked]>
---
 reftable/block.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/reftable/block.c b/reftable/block.c
index 11387b260a..4029df18ac 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -132,7 +132,7 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)
 
 int block_writer_finish(struct block_writer *w)
 {
-	int i = 0;
+	int i;
 	for (i = 0; i < w->restart_len; i++) {
 		put_be24(w->buf + w->next, w->restarts[i]);
 		w->next += 3;
@@ -144,23 +144,24 @@ int block_writer_finish(struct block_writer *w)
 
 	if (block_writer_type(w) == BLOCK_TYPE_LOG) {
 		int block_header_skip = 4 + w->header_off;
-		uint8_t *compressed = NULL;
-		int zresult = 0;
+		uint8_t *compressed;
 		uLongf src_len = w->next - block_header_skip;
-		size_t dest_cap = src_len;
+		uLongf dest_cap = src_len * 1.001 + 12;
 
 		compressed = reftable_malloc(dest_cap);
 		while (1) {
+			int zresult;
 			uLongf out_dest_len = dest_cap;
 
 			zresult = compress2(compressed, &out_dest_len,
 					    w->buf + block_header_skip, src_len,
 					    9);
-			if (zresult == Z_BUF_ERROR) {
+			if (zresult == Z_BUF_ERROR && dest_cap < LONG_MAX) {
 				dest_cap *= 2;
 				compressed =
 					reftable_realloc(compressed, dest_cap);
-				continue;
+				if (compressed)
+					continue;
 			}
 
 			if (Z_OK != zresult) {
-- 
2.33.0.955.gee03ddbf0e