--- a/libparted/labels/dos.c
+++ b/libparted/labels/dos.c
@@ -310,9 +310,11 @@
  */
 #define MAX_CHS_CYLINDER	1021
 #define MAX_TOTAL_PART		64
+#define DOS_MAX_TABLES		(MAX_TOTAL_PART + 1)
 
 typedef struct _DosRawPartition		DosRawPartition;
 typedef struct _DosRawTable		DosRawTable;
+typedef struct _DosTableParseState	DosTableParseState;
 
 /* note: lots of bit-bashing here, thus, you shouldn't look inside it.
  * Use chs_to_sector() and sector_to_chs() instead.
@@ -340,6 +342,11 @@
 	DosRawPartition		partitions [DOS_N_PRI_PARTITIONS];
 	uint16_t		magic;
 } __attribute__((packed));
+
+struct _DosTableParseState {
+	PedSector		sectors [DOS_MAX_TABLES];
+	int			count;
+};
 
 /* OrigState is information we want to preserve about the partition for
  * dealing with CHS issues
@@ -1112,7 +1119,20 @@
 }
 
 static int
-read_table (PedDisk* disk, PedSector sector, int is_extended_table)
+table_sector_seen (const DosTableParseState* state, PedSector sector)
+{
+	int i;
+
+	for (i = 0; i < state->count; i++)
+		if (state->sectors [i] == sector)
+			return 1;
+
+	return 0;
+}
+
+static int
+read_table (PedDisk* disk, PedSector sector, int is_extended_table,
+            DosTableParseState* state)
 {
 	int			i;
 	DosRawTable*		table;
@@ -1123,7 +1143,33 @@
 
 	PED_ASSERT (disk != NULL);
 	PED_ASSERT (disk->dev != NULL);
+	PED_ASSERT (state != NULL);
 
+	if (table_sector_seen (state, sector)) {
+		if (ped_exception_throw (
+			PED_EXCEPTION_ERROR,
+			PED_EXCEPTION_IGNORE_CANCEL,
+			_("Invalid partition table - recursive "
+			  "partition table on %s."),
+			disk->dev->path)
+				!= PED_EXCEPTION_IGNORE)
+			return 0;
+		return 1;
+	}
+
+	if (state->count >= DOS_MAX_TABLES) {
+		if (ped_exception_throw (
+			PED_EXCEPTION_ERROR,
+			PED_EXCEPTION_IGNORE_CANCEL,
+			_("Invalid partition table - too many "
+			  "extended partition tables on %s."),
+			disk->dev->path)
+				!= PED_EXCEPTION_IGNORE)
+			return 0;
+		return 1;
+	}
+	state->sectors [state->count++] = sector;
+
 	void *label = NULL;
 	if (!ptt_read_sector (disk->dev, sector, &label))
 		goto error;
@@ -1199,7 +1245,7 @@
 
 		/* non-nested extended partition */
 		if (part->type == PED_PARTITION_EXTENDED) {
-			if (!read_table (disk, part->geom.start, 1))
+			if (!read_table (disk, part->geom.start, 1, state))
 				goto error;
 		}
 	}
@@ -1222,7 +1268,7 @@
 				 */
 				continue;
 			}
-			if (!read_table (disk, part_start, 1))
+			if (!read_table (disk, part_start, 1, state))
 				goto error;
 		}
 	}
@@ -1240,11 +1286,14 @@
 static int
 msdos_read (PedDisk* disk)
 {
+	DosTableParseState	state;
+
 	PED_ASSERT (disk != NULL);
 	PED_ASSERT (disk->dev != NULL);
 
 	ped_disk_delete_all (disk);
-	if (!read_table (disk, 0, 0))
+	state.count = 0;
+	if (!read_table (disk, 0, 0, &state))
 		return 0;
 
 #ifndef DISCOVER_ONLY
