From 77c24f1dc58373453e80e77f5d44e65691bc8906 Mon Sep 17 00:00:00 2001 From: phcoder Date: Tue, 15 Sep 2009 10:36:29 +0000 Subject: [PATCH] 2009-09-15 Vladimir Serbinenko * partmap/pc.c (pc_partition_map_iterate): Detect and break loops. --- ChangeLog | 4 ++++ partmap/msdos.c | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2d1733ac3..be7715f25 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-09-15 Vladimir Serbinenko + + * partmap/pc.c (pc_partition_map_iterate): Detect and break loops. + 2009-09-14 Colin Watson * commands/test.c (get_fileinfo): Return immediately if diff --git a/partmap/msdos.c b/partmap/msdos.c index d0fc18efe..a5d55b64d 100644 --- a/partmap/msdos.c +++ b/partmap/msdos.c @@ -97,6 +97,8 @@ pc_partition_map_iterate (grub_disk_t disk, struct grub_msdos_partition_mbr mbr; struct grub_msdos_partition_disk_label label; struct grub_disk raw; + int labeln = 0; + grub_disk_addr_t lastaddr; /* Enforce raw disk access. */ raw = *disk; @@ -117,6 +119,18 @@ pc_partition_map_iterate (grub_disk_t disk, if (grub_disk_read (&raw, p.offset, 0, sizeof (mbr), &mbr)) goto finish; + /* This is our loop-detection algorithm. It works the following way: + It saves last position which was a power of two. Then it compares the + saved value with a current one. This way it's guaranteed that the loop + will be broken by at most third walk. + */ + if (labeln && lastaddr == p.offset) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "loop detected"); + + labeln++; + if ((labeln & (labeln - 1)) == 0) + lastaddr = p.offset; + /* Check if it is valid. */ if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");