tplink-safeloader: fix chunked support-list prints
authorSander Vanheule <sander@svanheule.net>
Thu, 26 May 2022 07:00:08 +0000 (09:00 +0200)
committerSander Vanheule <sander@svanheule.net>
Thu, 26 May 2022 07:10:46 +0000 (09:10 +0200)
When reading long support-list partitions, to print out as image info,
the string is read in chunks of 128 bytes. However, in cases where there
is more than one chunk, they are not properly terminated. This leads to
an out-of-bounds access by puts() printing the buffer chunks.

Ensure the read partial string is always NULL terminated, and print
chunk by chunk without extra line terminations. Terminate still with a
newline to maintain current behaviour.

Fixes: e1d76f4e8721 ("firmware-utils: tplink-safeloader: support displaying fw info")
Signed-off-by: Sander Vanheule <sander@svanheule.net>
src/tplink-safeloader.c

index c955bb4cac049b5c5b94226144091d1c4de1e6d8..d7de5b1b83aff7024b5c49ef954f94508444d070 100644 (file)
@@ -3788,18 +3788,21 @@ static int firmware_info(const char *input)
                char buf[128];
                size_t length;
                size_t bytes;
+               size_t max_length = sizeof(buf) - 1;
 
                if (fseek(fp, 0x1014 + e->base + sizeof(struct meta_header), SEEK_SET))
                        error(1, errno, "Can not seek in the firmware");
 
                printf("\n[Support list]\n");
                for (length = e->size - sizeof(struct meta_header); length; length -= bytes) {
-                       bytes = fread(buf, 1, length > sizeof(buf) ? sizeof(buf) : length, fp);
+                       bytes = fread(buf, 1, length > max_length ? max_length: length, fp);
                        if (bytes <= 0)
                                error(1, errno, "Can not read fwup-ptn data from the firmware");
 
-                       puts(buf);
+                       buf[bytes] = '\0';
+                       printf(buf);
                }
+        printf("\n");
        }
 
        e = find_partition(pointers, MAX_PARTITIONS, "partition-table", NULL);