... | ... |
@@ -185,7 +185,7 @@ am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \ |
185 | 185 |
libclamav_la-ishield.lo libclamav_la-bytecode_api.lo \ |
186 | 186 |
libclamav_la-bytecode_api_decl.lo libclamav_la-cache.lo \ |
187 | 187 |
libclamav_la-bytecode_detect.lo libclamav_la-events.lo \ |
188 |
- libclamav_la-dmg.lo libclamav_la-xar.lo \ |
|
188 |
+ libclamav_la-adc.lo libclamav_la-dmg.lo libclamav_la-xar.lo \ |
|
189 | 189 |
libclamav_la-sf_base64decode.lo libclamav_la-hfsplus.lo \ |
190 | 190 |
libclamav_la-swf.lo libclamav_la-jpeg.lo libclamav_la-png.lo \ |
191 | 191 |
libclamav_la-iso9660.lo libclamav_la-arc4.lo \ |
... | ... |
@@ -711,11 +711,11 @@ libclamav_la_SOURCES = clamav.h matcher-ac.c matcher-ac.h matcher-bm.c \ |
711 | 711 |
bcfeatures.h bytecode_api.c bytecode_api_decl.c bytecode_api.h \ |
712 | 712 |
bytecode_api_impl.h bytecode_hooks.h cache.c cache.h \ |
713 | 713 |
bytecode_detect.c bytecode_detect.h builtin_bytecodes.h \ |
714 |
- events.c events.h dmg.c dmg.h xar.c xar.h sf_base64decode.c \ |
|
715 |
- sf_base64decode.h hfsplus.c hfsplus.h swf.c swf.h jpeg.c \ |
|
716 |
- jpeg.h png.c png.h iso9660.c iso9660.h arc4.c arc4.h \ |
|
717 |
- rijndael.c rijndael.h crtmgr.c crtmgr.h asn1.c asn1.h bignum.h \ |
|
718 |
- bignum_fast.h tomsfastmath/addsub/fp_add.c \ |
|
714 |
+ events.c events.h adc.c adc.h dmg.c dmg.h xar.c xar.h \ |
|
715 |
+ sf_base64decode.c sf_base64decode.h hfsplus.c hfsplus.h swf.c \ |
|
716 |
+ swf.h jpeg.c jpeg.h png.c png.h iso9660.c iso9660.h arc4.c \ |
|
717 |
+ arc4.h rijndael.c rijndael.h crtmgr.c crtmgr.h asn1.c asn1.h \ |
|
718 |
+ bignum.h bignum_fast.h tomsfastmath/addsub/fp_add.c \ |
|
719 | 719 |
tomsfastmath/addsub/fp_add_d.c tomsfastmath/addsub/fp_addmod.c \ |
720 | 720 |
tomsfastmath/addsub/fp_cmp.c tomsfastmath/addsub/fp_cmp_d.c \ |
721 | 721 |
tomsfastmath/addsub/fp_cmp_mag.c tomsfastmath/addsub/fp_sub.c \ |
... | ... |
@@ -916,6 +916,7 @@ distclean-compile: |
916 | 916 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-LzmaDec.Plo@am__quote@ |
917 | 917 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-Ppmd7.Plo@am__quote@ |
918 | 918 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-Ppmd7Dec.Plo@am__quote@ |
919 |
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-adc.Plo@am__quote@ |
|
919 | 920 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-arc4.Plo@am__quote@ |
920 | 921 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-asn1.Plo@am__quote@ |
921 | 922 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-aspack.Plo@am__quote@ |
... | ... |
@@ -1848,6 +1849,13 @@ libclamav_la-events.lo: events.c |
1848 | 1848 |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
1849 | 1849 |
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-events.lo `test -f 'events.c' || echo '$(srcdir)/'`events.c |
1850 | 1850 |
|
1851 |
+libclamav_la-adc.lo: adc.c |
|
1852 |
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-adc.lo -MD -MP -MF $(DEPDIR)/libclamav_la-adc.Tpo -c -o libclamav_la-adc.lo `test -f 'adc.c' || echo '$(srcdir)/'`adc.c |
|
1853 |
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-adc.Tpo $(DEPDIR)/libclamav_la-adc.Plo |
|
1854 |
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adc.c' object='libclamav_la-adc.lo' libtool=yes @AMDEPBACKSLASH@ |
|
1855 |
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
1856 |
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-adc.lo `test -f 'adc.c' || echo '$(srcdir)/'`adc.c |
|
1857 |
+ |
|
1851 | 1858 |
libclamav_la-dmg.lo: dmg.c |
1852 | 1859 |
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-dmg.lo -MD -MP -MF $(DEPDIR)/libclamav_la-dmg.Tpo -c -o libclamav_la-dmg.lo `test -f 'dmg.c' || echo '$(srcdir)/'`dmg.c |
1853 | 1860 |
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-dmg.Tpo $(DEPDIR)/libclamav_la-dmg.Plo |
1854 | 1861 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,291 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2013 Sourcefire, Inc. |
|
2 |
+ * |
|
3 |
+ * Authors: David Raynor <draynor@sourcefire.com> |
|
4 |
+ * |
|
5 |
+ * This program is free software; you can redistribute it and/or modify |
|
6 |
+ * it under the terms of the GNU General Public License version 2 as |
|
7 |
+ * published by the Free Software Foundation. |
|
8 |
+ * |
|
9 |
+ * This program is distributed in the hope that it will be useful, |
|
10 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
+ * GNU General Public License for more details. |
|
13 |
+ * |
|
14 |
+ * You should have received a copy of the GNU General Public License |
|
15 |
+ * along with this program; if not, write to the Free Software |
|
16 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
17 |
+ * MA 02110-1301, USA. |
|
18 |
+ */ |
|
19 |
+ |
|
20 |
+#if HAVE_CONFIG_H |
|
21 |
+#include "clamav-config.h" |
|
22 |
+#endif |
|
23 |
+ |
|
24 |
+#include <stdio.h> |
|
25 |
+#include <errno.h> |
|
26 |
+#if HAVE_STRING_H |
|
27 |
+#include <string.h> |
|
28 |
+#endif |
|
29 |
+ |
|
30 |
+#include "cltypes.h" |
|
31 |
+#include "others.h" |
|
32 |
+#include "adc.h" |
|
33 |
+ |
|
34 |
+/* #define DEBUG_ADC */ |
|
35 |
+ |
|
36 |
+#ifdef DEBUG_ADC |
|
37 |
+# define adc_dbgmsg(...) cli_dbgmsg( __VA_ARGS__ ) |
|
38 |
+#else |
|
39 |
+# define adc_dbgmsg(...) ; |
|
40 |
+#endif |
|
41 |
+ |
|
42 |
+/* Initialize values and collect buffer |
|
43 |
+ * NOTE: buffer size must be larger than largest lookback offset */ |
|
44 |
+int adc_decompressInit(adc_stream *strm) |
|
45 |
+{ |
|
46 |
+ if (strm == NULL) { |
|
47 |
+ return ADC_IO_ERROR; |
|
48 |
+ } |
|
49 |
+ if (strm->state != ADC_STATE_UNINIT) { |
|
50 |
+ return ADC_DATA_ERROR; |
|
51 |
+ } |
|
52 |
+ |
|
53 |
+ /* Have to buffer maximum backward lookup */ |
|
54 |
+ strm->buffer = calloc(ADC_BUFF_SIZE, 1); |
|
55 |
+ if (strm->buffer == NULL) { |
|
56 |
+ return ADC_MEM_ERROR; |
|
57 |
+ } |
|
58 |
+ strm->buffered = 0; |
|
59 |
+ strm->state = ADC_STATE_GETTYPE; |
|
60 |
+ strm->length = 0; |
|
61 |
+ strm->offset = 0; |
|
62 |
+ strm->curr = strm->buffer; |
|
63 |
+ |
|
64 |
+ return ADC_OK; |
|
65 |
+} |
|
66 |
+ |
|
67 |
+/* Decompress routine |
|
68 |
+ * NOTE: Reaching end of input buffer does not mean end of output. |
|
69 |
+ * It may fill the output buffer but have more to output. |
|
70 |
+ * It will only return ADC_STREAM_END if output buffer is not full. |
|
71 |
+ * It will return ADC_DATA_ERROR if it ends in the middle of a phrase |
|
72 |
+ * (i.e. in the middle of a lookback code or data run) |
|
73 |
+ */ |
|
74 |
+int adc_decompress(adc_stream *strm) |
|
75 |
+{ |
|
76 |
+ uint8_t bData; |
|
77 |
+ uint8_t didNothing = 1; |
|
78 |
+ |
|
79 |
+ /* first, the error returns based on strm */ |
|
80 |
+ if ((strm == NULL) || (strm->next_in == NULL) || (strm->next_out == NULL)) { |
|
81 |
+ return ADC_IO_ERROR; |
|
82 |
+ } |
|
83 |
+ if (strm->state == ADC_STATE_UNINIT) { |
|
84 |
+ return ADC_DATA_ERROR; |
|
85 |
+ } |
|
86 |
+ |
|
87 |
+ cli_dbgmsg("adc_decompress: avail_in %lu avail_out %lu state %u\n", strm->avail_in, strm->avail_out, strm->state); |
|
88 |
+ |
|
89 |
+ while (strm->avail_out) { |
|
90 |
+ /* Exit if needs more in bytes and none available */ |
|
91 |
+ int needsInput; |
|
92 |
+ switch (strm->state) { |
|
93 |
+ case ADC_STATE_SHORTLOOK: |
|
94 |
+ case ADC_STATE_LONGLOOK: |
|
95 |
+ needsInput = 0; |
|
96 |
+ break; |
|
97 |
+ default: |
|
98 |
+ needsInput = 1; |
|
99 |
+ break; |
|
100 |
+ } |
|
101 |
+ if (needsInput && (strm->avail_in == 0)) { |
|
102 |
+ break; |
|
103 |
+ } |
|
104 |
+ else { |
|
105 |
+ didNothing = 0; |
|
106 |
+ } |
|
107 |
+ |
|
108 |
+ /* Find or execute statecode */ |
|
109 |
+ switch (strm->state) { |
|
110 |
+ case ADC_STATE_GETTYPE: { |
|
111 |
+ /* Grab action code */ |
|
112 |
+ bData = *(uint8_t *)(strm->next_in); |
|
113 |
+ strm->next_in++; |
|
114 |
+ strm->avail_in--; |
|
115 |
+ if (bData & 0x80) { |
|
116 |
+ strm->state = ADC_STATE_RAWDATA; |
|
117 |
+ strm->offset = 0; |
|
118 |
+ strm->length = (bData & 0x7F) + 1; |
|
119 |
+ } |
|
120 |
+ else if (bData & 0x40) { |
|
121 |
+ strm->state = ADC_STATE_LONGOP2; |
|
122 |
+ strm->offset = 0; |
|
123 |
+ strm->length = (bData & 0x3F) + 4; |
|
124 |
+ } |
|
125 |
+ else { |
|
126 |
+ strm->state = ADC_STATE_SHORTOP; |
|
127 |
+ strm->offset = (bData & 0x3) * 0x100; |
|
128 |
+ strm->length = ((bData & 0x3C) >> 2) + 3; |
|
129 |
+ } |
|
130 |
+ adc_dbgmsg("adc_decompress: GETTYPE bData %x state %u offset %u length %u\n", |
|
131 |
+ bData, strm->state, strm->offset, strm->length); |
|
132 |
+ break; |
|
133 |
+ } |
|
134 |
+ case ADC_STATE_LONGOP2: { |
|
135 |
+ /* Grab first offset byte */ |
|
136 |
+ bData = *(uint8_t *)(strm->next_in); |
|
137 |
+ strm->next_in++; |
|
138 |
+ strm->avail_in--; |
|
139 |
+ strm->offset = bData * 0x100; |
|
140 |
+ strm->state = ADC_STATE_LONGOP1; |
|
141 |
+ adc_dbgmsg("adc_decompress: LONGOP2 bData %x state %u offset %u length %u\n", |
|
142 |
+ bData, strm->state, strm->offset, strm->length); |
|
143 |
+ break; |
|
144 |
+ } |
|
145 |
+ case ADC_STATE_LONGOP1: { |
|
146 |
+ /* Grab second offset byte */ |
|
147 |
+ bData = *(uint8_t *)(strm->next_in); |
|
148 |
+ strm->next_in++; |
|
149 |
+ strm->avail_in--; |
|
150 |
+ strm->offset += bData + 1; |
|
151 |
+ strm->state = ADC_STATE_LONGLOOK; |
|
152 |
+ adc_dbgmsg("adc_decompress: LONGOP1 bData %x state %u offset %u length %u\n", |
|
153 |
+ bData, strm->state, strm->offset, strm->length); |
|
154 |
+ break; |
|
155 |
+ } |
|
156 |
+ case ADC_STATE_SHORTOP: { |
|
157 |
+ /* Grab offset byte */ |
|
158 |
+ bData = *(uint8_t *)(strm->next_in); |
|
159 |
+ strm->next_in++; |
|
160 |
+ strm->avail_in--; |
|
161 |
+ strm->offset += bData + 1; |
|
162 |
+ strm->state = ADC_STATE_SHORTLOOK; |
|
163 |
+ adc_dbgmsg("adc_decompress: SHORTOP bData %x state %u offset %u length %u\n", |
|
164 |
+ bData, strm->state, strm->offset, strm->length); |
|
165 |
+ break; |
|
166 |
+ } |
|
167 |
+ |
|
168 |
+ case ADC_STATE_RAWDATA: { |
|
169 |
+ /* Grab data */ |
|
170 |
+ adc_dbgmsg("adc_decompress: RAWDATA offset %u length %u\n", strm->offset, strm->length); |
|
171 |
+ while ((strm->avail_in > 0) && (strm->avail_out > 0) && (strm->length > 0)) { |
|
172 |
+ bData = *(uint8_t *)(strm->next_in); |
|
173 |
+ strm->next_in++; |
|
174 |
+ strm->avail_in--; |
|
175 |
+ /* store to output */ |
|
176 |
+ *(uint8_t *)(strm->next_out) = bData; |
|
177 |
+ strm->next_out++; |
|
178 |
+ strm->avail_out--; |
|
179 |
+ /* store to buffer */ |
|
180 |
+ if (strm->curr >= (strm->buffer + ADC_BUFF_SIZE)) { |
|
181 |
+ strm->curr = strm->buffer; |
|
182 |
+ } |
|
183 |
+ *(uint8_t *)strm->curr = bData; |
|
184 |
+ strm->curr++; |
|
185 |
+ if (strm->buffered < ADC_BUFF_SIZE) { |
|
186 |
+ strm->buffered++; |
|
187 |
+ } |
|
188 |
+ strm->length--; |
|
189 |
+ } |
|
190 |
+ if (strm->length == 0) { |
|
191 |
+ /* adc_dbgmsg("adc_decompress: RAWDATADONE buffered %u avail_in %u avail_out %u \n", |
|
192 |
+ strm->buffered, strm->avail_in, strm->avail_out); */ |
|
193 |
+ strm->state = ADC_STATE_GETTYPE; |
|
194 |
+ } |
|
195 |
+ break; |
|
196 |
+ } |
|
197 |
+ |
|
198 |
+ case ADC_STATE_SHORTLOOK: |
|
199 |
+ case ADC_STATE_LONGLOOK: { |
|
200 |
+ /* Copy data */ |
|
201 |
+ adc_dbgmsg("adc_decompress: LOOKBACK offset %u length %u avail_in %u avail_out %u\n", |
|
202 |
+ strm->offset, strm->length, strm->avail_in, strm->avail_out); |
|
203 |
+ while ((strm->avail_out > 0) && (strm->length > 0)) { |
|
204 |
+ /* state validation first */ |
|
205 |
+ if (strm->offset > 0x10000) { |
|
206 |
+ cli_dbgmsg("adc_decompress: bad LOOKBACK offset %u\n", strm->offset); |
|
207 |
+ return ADC_DATA_ERROR; |
|
208 |
+ } |
|
209 |
+ else if ((strm->state == ADC_STATE_SHORTLOOK) && (strm->offset > 0x400)) { |
|
210 |
+ cli_dbgmsg("adc_decompress: bad LOOKBACK offset %u\n", strm->offset); |
|
211 |
+ return ADC_DATA_ERROR; |
|
212 |
+ } |
|
213 |
+ if (strm->offset > strm->buffered) { |
|
214 |
+ cli_dbgmsg("adc_decompress: too large LOOKBACK offset %u\n", strm->offset); |
|
215 |
+ return ADC_DATA_ERROR; |
|
216 |
+ } |
|
217 |
+ /* retrieve byte */ |
|
218 |
+ if (strm->curr >= (strm->buffer + ADC_BUFF_SIZE)) { |
|
219 |
+ strm->curr = strm->buffer; |
|
220 |
+ } |
|
221 |
+ if (strm->curr > (strm->buffer + strm->offset)) { |
|
222 |
+ bData = *(uint8_t *)(strm->curr - strm->offset); |
|
223 |
+ } |
|
224 |
+ else { |
|
225 |
+ bData = *(uint8_t *)(strm->curr + ADC_BUFF_SIZE - strm->offset); |
|
226 |
+ } |
|
227 |
+ /* store to output */ |
|
228 |
+ *(uint8_t *)(strm->next_out) = bData; |
|
229 |
+ strm->next_out++; |
|
230 |
+ strm->avail_out--; |
|
231 |
+ /* store to buffer */ |
|
232 |
+ *(uint8_t *)strm->curr = bData; |
|
233 |
+ strm->curr++; |
|
234 |
+ if (strm->buffered < ADC_BUFF_SIZE) { |
|
235 |
+ strm->buffered++; |
|
236 |
+ } |
|
237 |
+ strm->length--; |
|
238 |
+ } |
|
239 |
+ if (strm->length == 0) { |
|
240 |
+ strm->state = ADC_STATE_GETTYPE; |
|
241 |
+ /* adc_dbgmsg("adc_decompress: LOOKBACKDONE buffered %u avail_in %u avail_out %u \n", |
|
242 |
+ strm->buffered, strm->avail_in, strm->avail_out); */ |
|
243 |
+ } |
|
244 |
+ break; |
|
245 |
+ } |
|
246 |
+ |
|
247 |
+ default: { |
|
248 |
+ /* bad state */ |
|
249 |
+ cli_errmsg("adc_decompress: invalid state %u\n", strm->state); |
|
250 |
+ return ADC_DATA_ERROR; |
|
251 |
+ } |
|
252 |
+ } /* end switch */ |
|
253 |
+ } /* end while */ |
|
254 |
+ |
|
255 |
+ /* There really isn't a terminator, just end of data */ |
|
256 |
+ if (didNothing && strm->avail_out) { |
|
257 |
+ if (strm->state == ADC_STATE_GETTYPE) { |
|
258 |
+ /* Nothing left to do */ |
|
259 |
+ return ADC_STREAM_END; |
|
260 |
+ } |
|
261 |
+ else { |
|
262 |
+ /* Ended mid phrase */ |
|
263 |
+ cli_dbgmsg("adc_decompress: stream ended mid-phrase, state %u\n", strm->state); |
|
264 |
+ return ADC_DATA_ERROR; |
|
265 |
+ } |
|
266 |
+ } |
|
267 |
+ return ADC_OK; |
|
268 |
+} |
|
269 |
+ |
|
270 |
+/* Cleanup routine, frees buffer */ |
|
271 |
+int adc_decompressEnd(adc_stream *strm) |
|
272 |
+{ |
|
273 |
+ if (strm == NULL) { |
|
274 |
+ return ADC_IO_ERROR; |
|
275 |
+ } |
|
276 |
+ if (strm->state == ADC_STATE_UNINIT) { |
|
277 |
+ return ADC_DATA_ERROR; |
|
278 |
+ } |
|
279 |
+ |
|
280 |
+ if (strm->buffer != NULL) { |
|
281 |
+ free(strm->buffer); |
|
282 |
+ } |
|
283 |
+ strm->buffered = 0; |
|
284 |
+ strm->state = ADC_STATE_UNINIT; |
|
285 |
+ strm->length = 0; |
|
286 |
+ strm->offset = 0; |
|
287 |
+ |
|
288 |
+ return ADC_OK; |
|
289 |
+} |
|
290 |
+ |
0 | 291 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,55 @@ |
0 |
+ |
|
1 |
+ |
|
2 |
+#ifndef CLAM_ADC_H |
|
3 |
+#define CLAM_ADC_H |
|
4 |
+ |
|
5 |
+struct adc_stream { |
|
6 |
+ void *next_in; |
|
7 |
+ size_t avail_in; |
|
8 |
+ size_t total_in; |
|
9 |
+ |
|
10 |
+ void *next_out; |
|
11 |
+ size_t avail_out; |
|
12 |
+ size_t total_out; |
|
13 |
+ |
|
14 |
+ /* internals */ |
|
15 |
+ uint8_t *buffer; |
|
16 |
+ uint8_t *curr; |
|
17 |
+ |
|
18 |
+ uint32_t buffered; |
|
19 |
+ uint16_t state; |
|
20 |
+ uint16_t length; |
|
21 |
+ uint32_t offset; |
|
22 |
+}; |
|
23 |
+typedef struct adc_stream adc_stream; |
|
24 |
+ |
|
25 |
+#define ADC_BUFF_SIZE 65536 |
|
26 |
+ |
|
27 |
+#define ADC_MEM_ERROR -1 |
|
28 |
+#define ADC_DATA_ERROR -2 |
|
29 |
+#define ADC_IO_ERROR -3 |
|
30 |
+#define ADC_OK 0 |
|
31 |
+#define ADC_STREAM_END 1 |
|
32 |
+ |
|
33 |
+enum adc_state { |
|
34 |
+ ADC_STATE_UNINIT = 0, |
|
35 |
+ ADC_STATE_GETTYPE = 1, |
|
36 |
+ ADC_STATE_RAWDATA = 2, |
|
37 |
+ ADC_STATE_SHORTOP = 3, |
|
38 |
+ ADC_STATE_LONGOP2 = 4, |
|
39 |
+ ADC_STATE_LONGOP1 = 5, |
|
40 |
+ ADC_STATE_SHORTLOOK = 6, |
|
41 |
+ ADC_STATE_LONGLOOK = 7 |
|
42 |
+}; |
|
43 |
+ |
|
44 |
+/* Compression phrases |
|
45 |
+ * store phrase - 1 byte header + data, first byte 0x80-0xFF, max length 0x80 (7 bits + 1), no offset |
|
46 |
+ * short phrase - 2 byte header + data, first byte 0x00-0x3F, max length 0x12 (4 bits + 3), max offset 0x3FF (10 bits) |
|
47 |
+ * long phrase - 3 byte header + data, first byte 0x40-0x7F, max length 0x43 (6 bits + 4), max offset 0xFFFF (16 bits) |
|
48 |
+ */ |
|
49 |
+ |
|
50 |
+int adc_decompressInit(adc_stream *strm); |
|
51 |
+int adc_decompress(adc_stream *strm); |
|
52 |
+int adc_decompressEnd(adc_stream *strm); |
|
53 |
+ |
|
54 |
+#endif |
... | ... |
@@ -54,9 +54,10 @@ |
54 | 54 |
#include "dmg.h" |
55 | 55 |
#include "scanners.h" |
56 | 56 |
#include "sf_base64decode.h" |
57 |
+#include "adc.h" |
|
57 | 58 |
|
58 |
-// #define DEBUG_DMG_PARSE |
|
59 |
-// #define DEBUG_DMG_BZIP |
|
59 |
+/* #define DEBUG_DMG_PARSE */ |
|
60 |
+/* #define DEBUG_DMG_BZIP */ |
|
60 | 61 |
|
61 | 62 |
#ifdef DEBUG_DMG_PARSE |
62 | 63 |
# define dmg_parsemsg(...) cli_dbgmsg( __VA_ARGS__) |
... | ... |
@@ -710,10 +711,84 @@ static int dmg_stripe_store(cli_ctx *ctx, int fd, uint32_t index, struct dmg_mis |
710 | 710 |
/* Stripe handling: ADC block (type 0x80000004) */ |
711 | 711 |
static int dmg_stripe_adc(cli_ctx *ctx, int fd, uint32_t index, struct dmg_mish_with_stripes *mish_set) |
712 | 712 |
{ |
713 |
- /* Temporary stub */ |
|
714 |
- cli_dbgmsg("dmg_stripe_adc: stripe " STDu32 "\n", index); |
|
715 |
- /* Return as format error to prevent scan for now */ |
|
716 |
- return CL_EFORMAT; |
|
713 |
+ int ret = CL_CLEAN, adcret; |
|
714 |
+ adc_stream strm; |
|
715 |
+ size_t off = mish_set->stripes[index].dataOffset; |
|
716 |
+ size_t len = mish_set->stripes[index].dataLength; |
|
717 |
+ uint64_t size_so_far = 0; |
|
718 |
+ uint64_t expected_len = mish_set->stripes[index].sectorCount * DMG_SECTOR_SIZE; |
|
719 |
+ uint8_t obuf[BUFSIZ]; |
|
720 |
+ |
|
721 |
+ cli_dbgmsg("dmg_stripe_adc: stripe " STDu32 " initial len " STDu64 " expected len " STDu64 "\n", |
|
722 |
+ index, len, expected_len); |
|
723 |
+ if (len == 0) |
|
724 |
+ return CL_CLEAN; |
|
725 |
+ |
|
726 |
+ memset(&strm, 0, sizeof(strm)); |
|
727 |
+ strm.next_in = (void*)fmap_need_off_once(*ctx->fmap, off, len); |
|
728 |
+ if (!strm.next_in) { |
|
729 |
+ cli_warnmsg("dmg_stripe_adc: fmap need failed on stripe " STDu32 "\n", index); |
|
730 |
+ return CL_EMAP; |
|
731 |
+ } |
|
732 |
+ strm.avail_in = len; |
|
733 |
+ strm.next_out = obuf; |
|
734 |
+ strm.avail_out = sizeof(obuf); |
|
735 |
+ |
|
736 |
+ adcret = adc_decompressInit(&strm); |
|
737 |
+ if(adcret != ADC_OK) { |
|
738 |
+ cli_warnmsg("dmg_stripe_adc: adc_decompressInit failed\n"); |
|
739 |
+ return CL_EMEM; |
|
740 |
+ } |
|
741 |
+ |
|
742 |
+ while(adcret == ADC_OK) { |
|
743 |
+ int written; |
|
744 |
+ if (size_so_far > expected_len) { |
|
745 |
+ cli_warnmsg("dmg_stripe_adc: expected size exceeded!\n"); |
|
746 |
+ adc_decompressEnd(&strm); |
|
747 |
+ return CL_EFORMAT; |
|
748 |
+ } |
|
749 |
+ adcret = adc_decompress(&strm); |
|
750 |
+ switch(adcret) { |
|
751 |
+ case ADC_OK: |
|
752 |
+ if(strm.avail_out == 0) { |
|
753 |
+ if ((written=cli_writen(fd, obuf, sizeof(obuf)))!=sizeof(obuf)) { |
|
754 |
+ cli_errmsg("dmg_stripe_adc: failed write to output file\n"); |
|
755 |
+ adc_decompressEnd(&strm); |
|
756 |
+ return CL_EWRITE; |
|
757 |
+ } |
|
758 |
+ size_so_far += written; |
|
759 |
+ strm.next_out = obuf; |
|
760 |
+ strm.avail_out = sizeof(obuf); |
|
761 |
+ } |
|
762 |
+ continue; |
|
763 |
+ case ADC_STREAM_END: |
|
764 |
+ default: |
|
765 |
+ written = sizeof(obuf) - strm.avail_out; |
|
766 |
+ if (written) { |
|
767 |
+ if ((cli_writen(fd, obuf, written))!=written) { |
|
768 |
+ cli_errmsg("dmg_stripe_adc: failed write to output file\n"); |
|
769 |
+ adc_decompressEnd(&strm); |
|
770 |
+ return CL_EWRITE; |
|
771 |
+ } |
|
772 |
+ size_so_far += written; |
|
773 |
+ strm.next_out = obuf; |
|
774 |
+ strm.avail_out = sizeof(obuf); |
|
775 |
+ } |
|
776 |
+ if (adcret == Z_STREAM_END) |
|
777 |
+ break; |
|
778 |
+ cli_dbgmsg("dmg_stripe_adc: after writing " STDu64 " bytes, " |
|
779 |
+ "got error %d decompressing stripe " STDu32 "\n", |
|
780 |
+ size_so_far, adcret, index); |
|
781 |
+ adc_decompressEnd(&strm); |
|
782 |
+ return CL_EFORMAT; |
|
783 |
+ } |
|
784 |
+ break; |
|
785 |
+ } |
|
786 |
+ |
|
787 |
+ adc_decompressEnd(&strm); |
|
788 |
+ cli_dbgmsg("dmg_stripe_adc: stripe " STDu32 " actual len " STDu64 " expected len " STDu64 "\n", |
|
789 |
+ index, size_so_far, expected_len); |
|
790 |
+ return CL_CLEAN; |
|
717 | 791 |
} |
718 | 792 |
|
719 | 793 |
/* Stripe handling: deflate block (type 0x80000005) */ |