From: Ana Bobillo <[email protected]>

part_get_info_extended() makes up the UUID of a DOS partition as
"%08x-%02x" from the disk signature and the partition number, into a
buffer of 12 bytes. That is enough up to partition 255, but
MAX_EXT_PARTS lets the number reach 256, whose three digits make
sprintf() write the terminating NUL past the end of the buffer.

Size the buffer like the UUID it is copied into, and use snprintf().

Add a test with 256 partitions, which catches the overflow on sandbox
with CONFIG_ASAN.

Signed-off-by: Ana Bobillo <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
---
(no changes since v1)

 disk/part_dos.c |  6 ++++--
 test/dm/part.c  | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/disk/part_dos.c b/disk/part_dos.c
index bc40d9d2829..3029ee0c31a 100644
--- a/disk/part_dos.c
+++ b/disk/part_dos.c
@@ -325,9 +325,11 @@ static int part_get_info_extended(struct blk_desc *desc,
                                                 "0x%x", pt->sys_ind);
                                        info->bootable = get_bootable(pt);
                                        if (CONFIG_IS_ENABLED(PARTITION_UUIDS)) 
{
-                                               char str[12];
+                                               /* part_num may take three 
digits */
+                                               char str[UUID_STR_LEN + 1];
 
-                                               sprintf(str, "%08x-%02x", 
disksig, part_num);
+                                               snprintf(str, sizeof(str), 
"%08x-%02x",
+                                                        disksig, part_num);
                                                disk_partition_set_uuid(info, 
str);
                                        }
                                        info->sys_ind = pt->sys_ind;
diff --git a/test/dm/part.c b/test/dm/part.c
index 4938d962144..f8a0fa974c1 100644
--- a/test/dm/part.c
+++ b/test/dm/part.c
@@ -423,3 +423,49 @@ static int dm_test_part_dos_ext_empty(struct 
unit_test_state *uts)
        return 0;
 }
 DM_TEST(dm_test_part_dos_ext_empty, UTF_SCAN_PDATA | UTF_SCAN_FDT | 
UTF_CONSOLE);
+
+/*
+ * Partition numbers above 255 take three digits in the UUID made up for a
+ * DOS partition, from the disk signature and the partition number
+ */
+static int dm_test_part_dos_uuid(struct unit_test_state *uts)
+{
+       struct disk_partition info;
+       dos_partition_t pt[4];
+       struct blk_desc *desc;
+       int part;
+
+       if (!CONFIG_IS_ENABLED(PARTITION_UUIDS))
+               return -EAGAIN;
+
+       ut_asserteq(2, blk_get_device_by_str("mmc", "2", &desc));
+       ut_asserteq(512, desc->blksz);
+
+       /* an extended partition from sector 2 */
+       memset(pt, '\0', sizeof(pt));
+       dos_set_entry(&pt[0], DOS_PART_TYPE_EXTENDED, 2, 512);
+       ut_assertok(dos_write_table(desc, 0, pt));
+
+       /*
+        * holding logical partitions 5 to 256, each of one sector after its
+        * table, with the tables two sectors apart from sector 2 on
+        */
+       for (part = 5; part <= 256; part++) {
+               memset(pt, '\0', sizeof(pt));
+               dos_set_entry(&pt[0], 0x83, 1, 1);
+               if (part < 256)
+                       dos_set_entry(&pt[1], DOS_PART_TYPE_EXTENDED,
+                                     (part - 4) * 2, 2);
+               ut_assertok(dos_write_table(desc, 2 + (part - 5) * 2, pt));
+       }
+
+       ut_assertok(part_get_info_by_type(desc, 255, PART_TYPE_DOS, &info));
+       ut_asserteq(2 + 250 * 2 + 1, info.start);
+       ut_asserteq_str("00000000-ff", disk_partition_uuid(&info));
+       ut_assertok(part_get_info_by_type(desc, 256, PART_TYPE_DOS, &info));
+       ut_asserteq(2 + 251 * 2 + 1, info.start);
+       ut_asserteq_str("00000000-100", disk_partition_uuid(&info));
+
+       return 0;
+}
+DM_TEST(dm_test_part_dos_uuid, UTF_SCAN_PDATA | UTF_SCAN_FDT);

Reply via email to