Mercurial > libpst
annotate src/lzfu.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 | cf3df962f1e5 |
children | 5c0ce43c7532 |
rev | line source |
---|---|
16 | 1 /* |
36 | 2 This program is free software; you can redistribute it and/or modify |
3 it under the terms of the GNU General Public License as published by | |
4 the Free Software Foundation; either version 2 of the License, or | |
5 (at your option) any later version. | |
16 | 6 |
36 | 7 You should have received a copy of the GNU General Public License |
8 along with this program; if not, write to the Free Software Foundation, | |
9 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | |
16 | 10 */ |
11 | |
122
bdb38b434c0a
more changes from Fridrich Strba to avoid installing our config.h
Carl Byington <carl@five-ten-sg.com>
parents:
120
diff
changeset
|
12 #include "define.h" |
120
6395ced2b8b2
disable building pst2dii on cygwin
Carl Byington <carl@five-ten-sg.com>
parents:
85
diff
changeset
|
13 #include "lzfu.h" |
48 | 14 |
16 | 15 |
36 | 16 #define LZFU_COMPRESSED 0x75465a4c |
17 #define LZFU_UNCOMPRESSED 0x414c454d | |
16 | 18 |
19 // initital dictionary | |
36 | 20 #define LZFU_INITDICT "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \ |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
21 "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
22 "t \\fdecor MS Sans SerifSymbolArialTimes Ne" \ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
23 "w RomanCourier{\\colortbl\\red0\\green0\\blue0" \ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
24 "\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab" \ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
25 "\\tx" |
16 | 26 // initial length of dictionary |
27 #define LZFU_INITLENGTH 207 | |
28 | |
29 // header for compressed rtf | |
30 typedef struct _lzfuheader { | |
43 | 31 uint32_t cbSize; |
32 uint32_t cbRawSize; | |
33 uint32_t dwMagic; | |
34 uint32_t dwCRC; | |
16 | 35 } lzfuheader; |
36 | |
37 | |
172
6954d315aaa8
move version-info into main configure.in, and set it properly.
Carl Byington <carl@five-ten-sg.com>
parents:
130
diff
changeset
|
38 char* pst_lzfu_decompress(char* rtfcomp, uint32_t compsize, size_t *size) { |
79
56fa05fd5271
Patch from Robert Simpson for encryption type 2.
Carl Byington <carl@five-ten-sg.com>
parents:
78
diff
changeset
|
39 unsigned char dict[4096]; // the dictionary buffer |
56fa05fd5271
Patch from Robert Simpson for encryption type 2.
Carl Byington <carl@five-ten-sg.com>
parents:
78
diff
changeset
|
40 unsigned int dict_length = 0; // the dictionary pointer |
56fa05fd5271
Patch from Robert Simpson for encryption type 2.
Carl Byington <carl@five-ten-sg.com>
parents:
78
diff
changeset
|
41 lzfuheader lzfuhdr; // the header of the lzfu block |
56fa05fd5271
Patch from Robert Simpson for encryption type 2.
Carl Byington <carl@five-ten-sg.com>
parents:
78
diff
changeset
|
42 unsigned char flags; // 8 bits of flags (1=2byte block pointer into the dict, 0=1 byte literal) |
56fa05fd5271
Patch from Robert Simpson for encryption type 2.
Carl Byington <carl@five-ten-sg.com>
parents:
78
diff
changeset
|
43 unsigned char flag_mask; // look at one flag bit each time thru the loop |
43 | 44 uint32_t i; |
79
56fa05fd5271
Patch from Robert Simpson for encryption type 2.
Carl Byington <carl@five-ten-sg.com>
parents:
78
diff
changeset
|
45 char *out_buf; |
193 | 46 uint32_t out_ptr = 0; |
43 | 47 uint32_t out_size; |
48 uint32_t in_ptr; | |
49 uint32_t in_size; | |
16 | 50 |
36 | 51 memcpy(dict, LZFU_INITDICT, LZFU_INITLENGTH); |
79
56fa05fd5271
Patch from Robert Simpson for encryption type 2.
Carl Byington <carl@five-ten-sg.com>
parents:
78
diff
changeset
|
52 memset(dict + LZFU_INITLENGTH, 0, sizeof(dict) - LZFU_INITLENGTH); |
36 | 53 dict_length = LZFU_INITLENGTH; |
79
56fa05fd5271
Patch from Robert Simpson for encryption type 2.
Carl Byington <carl@five-ten-sg.com>
parents:
78
diff
changeset
|
54 |
36 | 55 memcpy(&lzfuhdr, rtfcomp, sizeof(lzfuhdr)); |
37 | 56 LE32_CPU(lzfuhdr.cbSize); |
57 LE32_CPU(lzfuhdr.cbRawSize); | |
58 LE32_CPU(lzfuhdr.dwMagic); | |
59 LE32_CPU(lzfuhdr.dwCRC); | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
60 //printf("total size: %d\n", lzfuhdr.cbSize+4); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
61 //printf("raw size : %d\n", lzfuhdr.cbRawSize); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
62 //printf("compressed: %s\n", (lzfuhdr.dwMagic == LZFU_COMPRESSED ? "yes" : "no")); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
63 //printf("CRC : %#x\n", lzfuhdr.dwCRC); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
64 //printf("\n"); |
78
535075b4d261
Patch from Joachim Metz for debian packaging, and fix for incorrect length on lz decompression.
Carl Byington <carl@five-ten-sg.com>
parents:
73
diff
changeset
|
65 out_size = lzfuhdr.cbRawSize; |
172
6954d315aaa8
move version-info into main configure.in, and set it properly.
Carl Byington <carl@five-ten-sg.com>
parents:
130
diff
changeset
|
66 out_buf = (char*)pst_malloc(out_size); |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
67 in_ptr = sizeof(lzfuhdr); |
78
535075b4d261
Patch from Joachim Metz for debian packaging, and fix for incorrect length on lz decompression.
Carl Byington <carl@five-ten-sg.com>
parents:
73
diff
changeset
|
68 // Make sure to correct lzfuhdr.cbSize with 4 bytes before comparing |
535075b4d261
Patch from Joachim Metz for debian packaging, and fix for incorrect length on lz decompression.
Carl Byington <carl@five-ten-sg.com>
parents:
73
diff
changeset
|
69 // to compsize |
535075b4d261
Patch from Joachim Metz for debian packaging, and fix for incorrect length on lz decompression.
Carl Byington <carl@five-ten-sg.com>
parents:
73
diff
changeset
|
70 in_size = (lzfuhdr.cbSize + 4 < compsize) ? lzfuhdr.cbSize + 4 : compsize; |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
71 while (in_ptr < in_size) { |
73
3cb02cb1e6cd
Patch from Robert Simpson to fix doubly-linked list in the cache_ptr code, and allow arrays of unicode strings (without converting them).
Carl Byington <carl@five-ten-sg.com>
parents:
48
diff
changeset
|
72 flags = (unsigned char)(rtfcomp[in_ptr++]); |
36 | 73 flag_mask = 1; |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
74 while (flag_mask) { |
36 | 75 if (flag_mask & flags) { |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
76 // two bytes available? |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
77 if (in_ptr+1 < in_size) { |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
78 // read 2 bytes from input |
130
e35fd42bac05
more cleanup of include files
Carl Byington <carl@five-ten-sg.com>
parents:
129
diff
changeset
|
79 uint16_t blkhdr, offset, length; |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
80 memcpy(&blkhdr, rtfcomp+in_ptr, 2); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
81 LE16_CPU(blkhdr); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
82 in_ptr += 2; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
83 /* swap the upper and lower bytes of blkhdr */ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
84 blkhdr = (((blkhdr&0xFF00)>>8)+ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
85 ((blkhdr&0x00FF)<<8)); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
86 /* the offset is the first 12 bits of the 16 bit value */ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
87 offset = (blkhdr&0xFFF0)>>4; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
88 /* the length of the dict entry are the last 4 bits */ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
89 length = (blkhdr&0x000F)+2; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
90 // add the value we are about to print to the dictionary |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
91 for (i=0; i < length; i++) { |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
92 unsigned char c1; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
93 c1 = dict[(offset+i)%4096]; |
79
56fa05fd5271
Patch from Robert Simpson for encryption type 2.
Carl Byington <carl@five-ten-sg.com>
parents:
78
diff
changeset
|
94 dict[dict_length] = c1; |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
95 dict_length = (dict_length+1) % 4096; |
73
3cb02cb1e6cd
Patch from Robert Simpson to fix doubly-linked list in the cache_ptr code, and allow arrays of unicode strings (without converting them).
Carl Byington <carl@five-ten-sg.com>
parents:
48
diff
changeset
|
96 if (out_ptr < out_size) out_buf[out_ptr++] = (char)c1; |
78
535075b4d261
Patch from Joachim Metz for debian packaging, and fix for incorrect length on lz decompression.
Carl Byington <carl@five-ten-sg.com>
parents:
73
diff
changeset
|
97 // required for dictionary wrap around |
535075b4d261
Patch from Joachim Metz for debian packaging, and fix for incorrect length on lz decompression.
Carl Byington <carl@five-ten-sg.com>
parents:
73
diff
changeset
|
98 // otherwise 0 byte values are referenced incorrectly |
535075b4d261
Patch from Joachim Metz for debian packaging, and fix for incorrect length on lz decompression.
Carl Byington <carl@five-ten-sg.com>
parents:
73
diff
changeset
|
99 dict[dict_length] = 0; |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
100 } |
36 | 101 } |
102 } else { | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
103 // one byte available? |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
104 if (in_ptr < in_size) { |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
105 // uncompressed chunk (single byte) |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
106 char c1 = rtfcomp[in_ptr++]; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
107 dict[dict_length] = c1; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
108 dict_length = (dict_length+1)%4096; |
73
3cb02cb1e6cd
Patch from Robert Simpson to fix doubly-linked list in the cache_ptr code, and allow arrays of unicode strings (without converting them).
Carl Byington <carl@five-ten-sg.com>
parents:
48
diff
changeset
|
109 if (out_ptr < out_size) out_buf[out_ptr++] = (char)c1; |
78
535075b4d261
Patch from Joachim Metz for debian packaging, and fix for incorrect length on lz decompression.
Carl Byington <carl@five-ten-sg.com>
parents:
73
diff
changeset
|
110 // required for dictionary wrap around |
535075b4d261
Patch from Joachim Metz for debian packaging, and fix for incorrect length on lz decompression.
Carl Byington <carl@five-ten-sg.com>
parents:
73
diff
changeset
|
111 // otherwise 0 byte values are referenced incorrect |
535075b4d261
Patch from Joachim Metz for debian packaging, and fix for incorrect length on lz decompression.
Carl Byington <carl@five-ten-sg.com>
parents:
73
diff
changeset
|
112 dict[dict_length] = 0; |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
113 } |
36 | 114 } |
115 flag_mask <<= 1; | |
116 } | |
16 | 117 } |
85
582e927756d3
Patch from Robert Simpson for file handle leak in error case.
Carl Byington <carl@five-ten-sg.com>
parents:
79
diff
changeset
|
118 *size = out_ptr; |
36 | 119 return out_buf; |
16 | 120 } |