comparison src/libpst.c @ 359:a3e674fade6c

From Jeffrey Morlan: pst_parse_block misreads Table Contexts (aka "type 2") with a multi-block Row Matrix ("ind2"). Rows are never split between blocks - every block except the last has padding at the end which should be ignored. I've only seen this affect the recipients table, but presumably it could affect attachments too. This was causing out-of-bounds memory ranges to be returned from pst_getBlockOffset and later access; patch fixes both the table reading issue and adds a missing bounds check to pst_getBlockOffset (so as not to risk a segfault if the PST is corrupted).
author Carl Byington <carl@five-ten-sg.com>
date Wed, 06 Jul 2016 10:20:12 -0700
parents fec7f4fca713
children 26c48ea9d896
comparison
equal deleted inserted replaced
358:6abc3054cba2 359:a3e674fade6c
1403 char* list_start; 1403 char* list_start;
1404 char* fr_ptr; 1404 char* fr_ptr;
1405 char* to_ptr; 1405 char* to_ptr;
1406 char* ind2_end = NULL; 1406 char* ind2_end = NULL;
1407 char* ind2_ptr = NULL; 1407 char* ind2_ptr = NULL;
1408 char* ind2_block_start = NULL;
1409 size_t ind2_max_block_size = pf->do_read64 ? 0x1FF0 : 0x1FF4;
1408 pst_x_attrib_ll *mapptr; 1410 pst_x_attrib_ll *mapptr;
1409 pst_block_hdr block_hdr; 1411 pst_block_hdr block_hdr;
1410 pst_table3_rec table3_rec; //for type 3 (0x0101) blocks 1412 pst_table3_rec table3_rec; //for type 3 (0x0101) blocks
1411 1413
1412 struct { 1414 struct {
1599 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7); 1601 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1600 DEBUG_RET(); 1602 DEBUG_RET();
1601 return NULL; 1603 return NULL;
1602 } 1604 }
1603 ind2_ptr = block_offset6.from; 1605 ind2_ptr = block_offset6.from;
1606 ind2_block_start = ind2_ptr;
1604 ind2_end = block_offset6.to; 1607 ind2_end = block_offset6.to;
1605 } 1608 }
1606 else { 1609 else {
1607 num_mapi_objects = 0; 1610 num_mapi_objects = 0;
1608 } 1611 }
1830 } 1833 }
1831 x++; 1834 x++;
1832 } 1835 }
1833 DEBUG_INFO(("increasing ind2_ptr by %i [%#x] bytes. Was %#x, Now %#x\n", rec_size, rec_size, ind2_ptr, ind2_ptr+rec_size)); 1836 DEBUG_INFO(("increasing ind2_ptr by %i [%#x] bytes. Was %#x, Now %#x\n", rec_size, rec_size, ind2_ptr, ind2_ptr+rec_size));
1834 ind2_ptr += rec_size; 1837 ind2_ptr += rec_size;
1838 // ind2 rows do not get split between blocks. See PST spec, 2.3.4.4 "Row Matrix".
1839 if (ind2_ptr + rec_size > ind2_block_start + ind2_max_block_size) {
1840 ind2_block_start += ind2_max_block_size;
1841 DEBUG_INFO(("advancing ind2_ptr to next block. Was %#x, Now %#x\n", ind2_ptr, ind2_block_start));
1842 ind2_ptr = ind2_block_start;
1843 }
1835 } 1844 }
1836 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7); 1845 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1837 DEBUG_RET(); 1846 DEBUG_RET();
1838 return mo_head; 1847 return mo_head;
1839 } 1848 }
3599 memcpy(&(p->from), &(buf[(i_offset+2)+of1]), sizeof(p->from)); 3608 memcpy(&(p->from), &(buf[(i_offset+2)+of1]), sizeof(p->from));
3600 memcpy(&(p->to), &(buf[(i_offset+2)+of1+sizeof(p->from)]), sizeof(p->to)); 3609 memcpy(&(p->to), &(buf[(i_offset+2)+of1+sizeof(p->from)]), sizeof(p->to));
3601 LE16_CPU(p->from); 3610 LE16_CPU(p->from);
3602 LE16_CPU(p->to); 3611 LE16_CPU(p->to);
3603 DEBUG_WARN(("get block offset finds from=%i(%#x), to=%i(%#x)\n", p->from, p->from, p->to, p->to)); 3612 DEBUG_WARN(("get block offset finds from=%i(%#x), to=%i(%#x)\n", p->from, p->from, p->to, p->to));
3604 if (p->from > p->to) { 3613 if (p->from > p->to || p->to > read_size) {
3605 DEBUG_WARN(("get block offset from > to\n")); 3614 DEBUG_WARN(("get block offset bad range\n"));
3606 DEBUG_RET(); 3615 DEBUG_RET();
3607 return 0; 3616 return 0;
3608 } 3617 }
3609 DEBUG_RET(); 3618 DEBUG_RET();
3610 return 1; 3619 return 1;