summaryrefslogtreecommitdiffstats
path: root/src/parti386.c
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2015-04-16 08:25:30 +0200
committerChristophe Grenier <grenier@cgsecurity.org>2015-04-16 08:43:48 +0200
commit4195e27fc0acbf99d77c90d79f687158623903f2 (patch)
tree98a8bf09e3c56337380f28decaa904b4658bbf17 /src/parti386.c
parentdd664527743fa4e5570e0a3e38e186370e7b23e2 (diff)
PC/Intel partition table parsing: fix an endless loop found by afl-fuzz
Diffstat (limited to 'src/parti386.c')
-rw-r--r--src/parti386.c237
1 files changed, 125 insertions, 112 deletions
diff --git a/src/parti386.c b/src/parti386.c
index c9fb231..5a8c15a 100644
--- a/src/parti386.c
+++ b/src/parti386.c
@@ -466,144 +466,157 @@ static void test_MBR_data(list_part_t *list_part)
screen_buffer_add(msg_ONLY1MUSTBOOT);
}
-static list_part_t *get_ext_data_i386(disk_t *disk_car, list_part_t *list_part, const int verbose, const int saveheader)
+static partition_t *get_ext_partition_i386(const list_part_t *list_part)
{
- list_part_t *element;
- partition_t *partition_main_ext=NULL;
- for(element=list_part;element!=NULL;element=element->next)
+ const list_part_t *element;
+ for(element=list_part; element!=NULL; element=element->next)
{
if(element->part->status==STATUS_EXT)
- partition_main_ext=element->part;
+ return element->part;
}
- if(partition_main_ext!=NULL)
+ return NULL;
+}
+
+static list_part_t *get_ext_data_i386(disk_t *disk_car, list_part_t *list_part, const int verbose, const int saveheader)
+{
+ partition_t *partition_main_ext;
+ partition_t *partition_ext;
+ partition_t *partition_next_ext;
+ unsigned int order=5;
+ unsigned int nbr_part=0;
+ if((partition_main_ext=get_ext_partition_i386(list_part))==NULL)
+ return list_part;
+ for(partition_ext=partition_main_ext;
+ partition_ext!=NULL && nbr_part<32;
+ partition_ext=partition_next_ext)
{
- partition_t *partition_ext=partition_main_ext;
- partition_t *partition_next_ext=NULL;
- unsigned int order=5;
- do
+ unsigned char buffer[DEFAULT_SECTOR_SIZE];
+ int nb_hidden=0, nb_mb=0, nb_part=0, nb_ext=0, nb_boot=0;
+ unsigned int i;
+ partition_next_ext=NULL;
+ if(partition_ext->part_offset==0)
+ return list_part;
+ if(disk_car->pread(disk_car, &buffer, sizeof(buffer), partition_ext->part_offset) != sizeof(buffer))
+ return list_part;
+ if((buffer[0x1FE]!=(unsigned char)0x55)||(buffer[0x1FF]!=(unsigned char)0xAA))
{
- unsigned char buffer[DEFAULT_SECTOR_SIZE];
- int nb_hidden=0, nb_mb=0, nb_part=0, nb_ext=0, nb_boot=0;
- unsigned int i;
- if(disk_car->pread(disk_car, &buffer, sizeof(buffer), partition_ext->part_offset) != sizeof(buffer))
- return list_part;
- if((buffer[0x1FE]!=(unsigned char)0x55)||(buffer[0x1FF]!=(unsigned char)0xAA))
- {
- screen_buffer_add("\ntest_logical: " msg_TBL_NMARK);
- return list_part;
- }
- for(i=0;i<4;i++)
+ screen_buffer_add("\ntest_logical: " msg_TBL_NMARK);
+ return list_part;
+ }
+ for(i=0;i<4;i++)
+ {
+ const struct partition_dos *p=pt_offset(buffer,i);
+ if(p->boot_ind==(unsigned char)0x80)
+ nb_boot++;
+ switch(p->sys_ind)
{
- const struct partition_dos *p=pt_offset(buffer,i);
- if(p->boot_ind==(unsigned char)0x80)
- nb_boot++;
- switch(p->sys_ind)
- {
- case P_16FATBDH:
- case P_16FATH:
- case P_NTFSH:
- nb_hidden++;
- break;
- case P_OS2MB:
- nb_mb++;
- break;
- case P_EXTENDX:
- case P_EXTENDED:
- case P_LINUXEXTENDX:
- nb_ext++;
- break;
- case P_NO_OS:
- break;
- default:
- nb_part++;
- }
+ case P_16FATBDH:
+ case P_16FATH:
+ case P_NTFSH:
+ nb_hidden++;
+ break;
+ case P_OS2MB:
+ nb_mb++;
+ break;
+ case P_EXTENDX:
+ case P_EXTENDED:
+ case P_LINUXEXTENDX:
+ nb_ext++;
+ break;
+ case P_NO_OS:
+ break;
+ default:
+ nb_part++;
}
- if(nb_hidden>0)
- screen_buffer_add("Partition must not be hidden\n");
- if(nb_mb>0)
- screen_buffer_add("Multiboot must be a primary partition, not a logical\n");
- if(nb_ext>1)
- screen_buffer_add("A logical partition must not have more than one link to another logical partition\n");
- if(nb_part>1)
- screen_buffer_add("A logical partition must contain only one partition\n");
- if(nb_boot>0)
- screen_buffer_add("Logical partition must not be bootable\n");
- partition_next_ext=NULL;
- for(i=0;i<4;i++)
+ }
+ if(nb_hidden>0)
+ screen_buffer_add("Partition must not be hidden\n");
+ if(nb_mb>0)
+ screen_buffer_add("Multiboot must be a primary partition, not a logical\n");
+ if(nb_ext>1)
+ screen_buffer_add("A logical partition must not have more than one link to another logical partition\n");
+ if(nb_part>1)
+ screen_buffer_add("A logical partition must contain only one partition\n");
+ if(nb_boot>0)
+ screen_buffer_add("Logical partition must not be bootable\n");
+ for(i=0;i<4;i++)
+ {
+ const struct partition_dos *p=pt_offset(buffer,i);
+ if(p->sys_ind!=0)
{
- const struct partition_dos *p=pt_offset(buffer,i);
- if(p->sys_ind!=0)
+ int insert_error=0;
+ partition_t *new_partition=partition_new(&arch_i386);
+ new_partition->order=order;
+ if(verbose>1)
+ log_dos_entry(p);
+ if(is_extended(p->sys_ind))
{
- int insert_error=0;
- partition_t *new_partition=partition_new(&arch_i386);
- new_partition->order=order;
- if(verbose>1)
- log_dos_entry(p);
- if(is_extended(p->sys_ind))
+ i386_entry2partition(disk_car, partition_main_ext->part_offset, new_partition, p, STATUS_EXT_IN_EXT,order,verbose,saveheader);
+ aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,new_partition);
+ if(new_partition->errcode!=BAD_NOERR)
{
- i386_entry2partition(disk_car, partition_main_ext->part_offset, new_partition, p, STATUS_EXT_IN_EXT,order,verbose,saveheader);
- aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,new_partition);
- if(new_partition->errcode!=BAD_NOERR)
- {
- screen_buffer_add("%s\n",errmsg_i386_entry2partition(new_partition->errcode));
+ screen_buffer_add("%s\n",errmsg_i386_entry2partition(new_partition->errcode));
+ }
+ {
+ if((new_partition->part_offset<=partition_main_ext->part_offset) ||
+ (new_partition->part_offset+new_partition->part_size-1 > partition_main_ext->part_offset+partition_main_ext->part_size-1))
+ { /* Must be IN partition_main_ext */
+ screen_buffer_add("Must be in extended partition\n");
+ aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition_main_ext);
+ aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,new_partition);
}
+ else
{
- if((new_partition->part_offset<=partition_main_ext->part_offset) ||
- (new_partition->part_offset+new_partition->part_size-1 > partition_main_ext->part_offset+partition_main_ext->part_size-1))
- { /* Must be IN partition_main_ext */
- screen_buffer_add("Must be in extended partition\n");
- aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition_main_ext);
- aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,new_partition);
- }
- else
+ list_part_t *element;
+ for(element=list_part;element!=NULL;element=element->next)
{
- for(element=list_part;element!=NULL;element=element->next)
+ partition_t *partition=element->part;
+ if(partition->status==STATUS_EXT_IN_EXT)
{
- partition_t *partition=element->part;
- if(partition->status==STATUS_EXT_IN_EXT)
- {
- if(((partition->part_offset>=new_partition->part_offset) && (partition->part_offset<=new_partition->part_offset+new_partition->part_size-1)) ||
- ((partition->part_offset+partition->part_size-1>=new_partition->part_offset) && (partition->part_offset+partition->part_size-1<=new_partition->part_offset+partition->part_size-1)))
- { /* New Partition start or end mustn't been in partition */
- screen_buffer_add( "Logical partition must be in its own extended partition\n");
- aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition);
- aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,new_partition);
- }
+ if(((partition->part_offset>=new_partition->part_offset) && (partition->part_offset<=new_partition->part_offset+new_partition->part_size-1)) ||
+ ((partition->part_offset+partition->part_size-1>=new_partition->part_offset) && (partition->part_offset+partition->part_size-1<=new_partition->part_offset+partition->part_size-1)))
+ { /* New Partition start or end mustn't been in partition */
+ screen_buffer_add( "Logical partition must be in its own extended partition\n");
+ aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition);
+ aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,new_partition);
}
}
}
}
}
- else
+ }
+ else
+ {
+ i386_entry2partition(disk_car,partition_ext->part_offset, new_partition, p, STATUS_LOG,order,verbose,saveheader);
+ order++;
+ if(verbose>1)
+ log_dos_entry(p);
+ aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,new_partition);
+ if(new_partition->errcode!=BAD_NOERR)
{
- i386_entry2partition(disk_car,partition_ext->part_offset, new_partition, p, STATUS_LOG,order,verbose,saveheader);
- order++;
- if(verbose>1)
- log_dos_entry(p);
- aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,new_partition);
- if(new_partition->errcode!=BAD_NOERR)
- {
- screen_buffer_add("%s\n",errmsg_i386_entry2partition(new_partition->errcode));
- }
- {
- if((new_partition->part_offset<=partition_main_ext->part_offset) ||
- (new_partition->part_offset+new_partition->part_size-1 > partition_main_ext->part_offset+partition_main_ext->part_size-1))
- { /* Must be IN partition_main_ext */
- screen_buffer_add( msg_SAME_SPACE);
- aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition_main_ext);
- aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,new_partition);
- }
+ screen_buffer_add("%s\n",errmsg_i386_entry2partition(new_partition->errcode));
+ }
+ {
+ if((new_partition->part_offset<=partition_main_ext->part_offset) ||
+ (new_partition->part_offset+new_partition->part_size-1 > partition_main_ext->part_offset+partition_main_ext->part_size-1))
+ { /* Must be IN partition_main_ext */
+ screen_buffer_add( msg_SAME_SPACE);
+ aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition_main_ext);
+ aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,new_partition);
}
}
- list_part=insert_new_partition(list_part, new_partition, 0, &insert_error);
- if(insert_error>0)
- free(new_partition);
- else if(is_extended(p->sys_ind))
+ }
+ list_part=insert_new_partition(list_part, new_partition, 0, &insert_error);
+ if(insert_error>0)
+ free(new_partition);
+ else
+ {
+ nbr_part++;
+ if(is_extended(p->sys_ind))
partition_next_ext=new_partition;
}
}
- partition_ext=partition_next_ext;
- } while ((partition_ext!=NULL) && (order<30));
+ }
}
return list_part;
}