Mercurial > libpst
annotate src/lzfu.c @ 41:183ae993b9ad
security fix for potential buffer overrun in lz decompress
author | carl |
---|---|
date | Tue, 02 Oct 2007 15:49:44 -0700 |
parents | ddfb25318812 |
children | f6db1f060a95 |
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 | |
12 #include "define.h" | |
13 #include "libpst.h" | |
14 #include <sys/types.h> | |
15 #include <string.h> | |
16 #include <stdio.h> | |
17 | |
18 #include "lzfu.h" | |
19 | |
36 | 20 #define LZFU_COMPRESSED 0x75465a4c |
21 #define LZFU_UNCOMPRESSED 0x414c454d | |
16 | 22 |
23 // initital dictionary | |
36 | 24 #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
|
25 "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
26 "t \\fdecor MS Sans SerifSymbolArialTimes Ne" \ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
27 "w RomanCourier{\\colortbl\\red0\\green0\\blue0" \ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
28 "\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
|
29 "\\tx" |
16 | 30 // initial length of dictionary |
31 #define LZFU_INITLENGTH 207 | |
32 | |
33 // header for compressed rtf | |
34 typedef struct _lzfuheader { | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
35 u_int32_t cbSize; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
36 u_int32_t cbRawSize; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
37 u_int32_t dwMagic; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
38 u_int32_t dwCRC; |
16 | 39 } lzfuheader; |
40 | |
41 | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
42 unsigned char* lzfu_decompress (unsigned char* rtfcomp, u_int32_t compsize, size_t *size) { |
36 | 43 // the dictionary buffer |
44 unsigned char dict[4096]; | |
45 // the dictionary pointer | |
46 unsigned int dict_length=0; | |
47 // the header of the lzfu block | |
48 lzfuheader lzfuhdr; | |
49 // container for the data blocks | |
50 unsigned char flags; | |
51 // temp value for determining the bits in the flag | |
52 unsigned char flag_mask; | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
53 u_int32_t i; |
36 | 54 unsigned char *out_buf; |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
55 u_int32_t out_ptr = 0; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
56 u_int32_t out_size; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
57 u_int32_t in_ptr; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
58 u_int32_t in_size; |
16 | 59 |
36 | 60 memcpy(dict, LZFU_INITDICT, LZFU_INITLENGTH); |
61 dict_length = LZFU_INITLENGTH; | |
62 memcpy(&lzfuhdr, rtfcomp, sizeof(lzfuhdr)); | |
37 | 63 LE32_CPU(lzfuhdr.cbSize); |
64 LE32_CPU(lzfuhdr.cbRawSize); | |
65 LE32_CPU(lzfuhdr.dwMagic); | |
66 LE32_CPU(lzfuhdr.dwCRC); | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
67 //printf("total size: %d\n", lzfuhdr.cbSize+4); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
68 //printf("raw size : %d\n", lzfuhdr.cbRawSize); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
69 //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
|
70 //printf("CRC : %#x\n", lzfuhdr.dwCRC); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
71 //printf("\n"); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
72 out_size = lzfuhdr.cbRawSize + 3; // two braces and a null terminator |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
73 out_buf = (unsigned char*)xmalloc(out_size); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
74 in_ptr = sizeof(lzfuhdr); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
75 in_size = (lzfuhdr.cbSize < compsize) ? lzfuhdr.cbSize : compsize; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
76 while (in_ptr < in_size) { |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
77 flags = rtfcomp[in_ptr++]; |
36 | 78 flag_mask = 1; |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
79 while (flag_mask) { |
36 | 80 if (flag_mask & flags) { |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
81 // two bytes available? |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
82 if (in_ptr+1 < in_size) { |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
83 // read 2 bytes from input |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
84 unsigned short int blkhdr, offset, length; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
85 memcpy(&blkhdr, rtfcomp+in_ptr, 2); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
86 LE16_CPU(blkhdr); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
87 in_ptr += 2; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
88 /* swap the upper and lower bytes of blkhdr */ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
89 blkhdr = (((blkhdr&0xFF00)>>8)+ |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
90 ((blkhdr&0x00FF)<<8)); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
91 /* 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
|
92 offset = (blkhdr&0xFFF0)>>4; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
93 /* 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
|
94 length = (blkhdr&0x000F)+2; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
95 // 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
|
96 for (i=0; i < length; i++) { |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
97 unsigned char c1; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
98 c1 = dict[(offset+i)%4096]; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
99 dict[dict_length]=c1; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
100 dict_length = (dict_length+1) % 4096; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
101 if (out_ptr < out_size) out_buf[out_ptr++] = c1; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
102 } |
36 | 103 } |
104 } else { | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
105 // one byte available? |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
106 if (in_ptr < in_size) { |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
107 // uncompressed chunk (single byte) |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
108 char c1 = rtfcomp[in_ptr++]; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
109 dict[dict_length] = c1; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
110 dict_length = (dict_length+1)%4096; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
111 if (out_ptr < out_size) out_buf[out_ptr++] = c1; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
112 } |
36 | 113 } |
114 flag_mask <<= 1; | |
115 } | |
16 | 116 } |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
117 // the compressed version doesn't appear to drop the closing |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
118 // braces onto the doc, so we do that here. |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
119 if (out_ptr < out_size) out_buf[out_ptr++] = '}'; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
120 if (out_ptr < out_size) out_buf[out_ptr++] = '}'; |
37 | 121 *size = out_ptr; |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
37
diff
changeset
|
122 if (out_ptr < out_size) out_buf[out_ptr++] = '\0'; |
36 | 123 return out_buf; |
16 | 124 } |