Browse code

bb#11306 - fixes for LZMA decompression in flash files

Kevin Lin authored on 2015/05/02 04:23:07
Showing 1 changed files
... ...
@@ -125,7 +125,9 @@ static int scanzws(cli_ctx *ctx, struct swf_file_hdr *hdr)
125 125
 	struct CLI_LZMA lz;
126 126
 	unsigned char inbuff[FILEBUFF], outbuff[FILEBUFF];
127 127
 	fmap_t *map = *ctx->fmap;
128
+	/* strip off header */
128 129
 	off_t offset = 8;
130
+	uint32_t d_insize;
129 131
 	size_t outsize = 8;
130 132
 	int ret, lret, count;
131 133
 	char *tmpname;
... ...
@@ -148,11 +150,52 @@ static int scanzws(cli_ctx *ctx, struct swf_file_hdr *hdr)
148 148
 	return CL_EWRITE;
149 149
     }
150 150
 
151
-    lz.avail_in = 0;
151
+    /* read 4 bytes (for compressed 32-bit filesize) [not used for LZMA] */
152
+    if (fmap_readn(map, &d_insize, offset, sizeof(d_insize)) != sizeof(d_insize)) {
153
+	cli_errmsg("scanzws: Error reading SWF file\n");
154
+        close(fd);
155
+        if (cli_unlink(tmpname)) {
156
+            free(tmpname);
157
+            return CL_EUNLINK;
158
+        }
159
+        free(tmpname);
160
+        return CL_EREAD;
161
+    }
162
+    offset += sizeof(d_insize);
163
+
164
+    /* check if declared input size matches actual output size */
165
+    /* map->len = header (8 bytes) + d_insize (4 bytes) + flags (5 bytes) + compressed stream */
166
+    if (d_insize != (map->len - 17)) {
167
+        cli_warnmsg("SWF: declared input length != compressed stream size, %u != %llu\n",
168
+                    d_insize, (long long unsigned)(map->len - 17));
169
+    } else {
170
+        cli_dbgmsg("SWF: declared input length == compressed stream size, %u == %llu\n",
171
+                   d_insize, (long long unsigned)(map->len - 17));
172
+    }
173
+
174
+    /* first buffer required for initializing LZMA */
175
+    ret = fmap_readn(map, inbuff, offset, FILEBUFF);
176
+    if (ret < 0) {
177
+	cli_errmsg("scanzws: Error reading SWF file\n");
178
+	close(fd);
179
+	if (cli_unlink(tmpname)) {
180
+	    free(tmpname);
181
+	    return CL_EUNLINK;
182
+	}
183
+	free(tmpname);
184
+	return CL_EUNPACK;
185
+    }
186
+    if (!ret)
187
+	return CL_EFORMAT; /* likely truncated */
188
+    offset += ret;
189
+
190
+    memset(&lz, 0, sizeof(lz));
152 191
     lz.next_in = inbuff;
153 192
     lz.next_out = outbuff;
193
+    lz.avail_in = ret;
194
+    lz.avail_out = FILEBUFF;
154 195
 
155
-    lret = cli_LzmaInit(&lz, 0);
196
+    lret = cli_LzmaInit(&lz, hdr->filesize);
156 197
     if (lret != LZMA_RESULT_OK) {
157 198
 	cli_errmsg("scanzws: LzmaInit() failed\n");
158 199
 	close(fd);
... ...
@@ -164,9 +207,10 @@ static int scanzws(cli_ctx *ctx, struct swf_file_hdr *hdr)
164 164
 	return CL_EUNPACK;
165 165
     }
166 166
 
167
-    do {
167
+    while (lret == LZMA_RESULT_OK) {
168 168
 	if (lz.avail_in == 0) {
169 169
 	    lz.next_in = inbuff;
170
+
170 171
 	    ret = fmap_readn(map, inbuff, offset, FILEBUFF);
171 172
 	    if (ret < 0) {
172 173
 		cli_errmsg("scanzws: Error reading SWF file\n");
... ...
@@ -204,11 +248,11 @@ static int scanzws(cli_ctx *ctx, struct swf_file_hdr *hdr)
204 204
 	}
205 205
 	lz.next_out = outbuff;
206 206
 	lz.avail_out = FILEBUFF;
207
-    } while(lret == LZMA_RESULT_OK);
207
+    }
208 208
 
209 209
     cli_LzmaShutdown(&lz);
210 210
 
211
-    if (lret != LZMA_STREAM_END || lret != LZMA_RESULT_OK) {
211
+    if (lret != LZMA_STREAM_END && lret != LZMA_RESULT_OK) {
212 212
 	/* outsize starts at 8, therefore, if its still 8, nothing was decompressed */
213 213
 	if (outsize == 8) {
214 214
 	    cli_infomsg(ctx, "scanzws: Error decompressing SWF file. No data decompressed.\n");
... ...
@@ -222,9 +266,17 @@ static int scanzws(cli_ctx *ctx, struct swf_file_hdr *hdr)
222 222
 	}
223 223
 	cli_infomsg(ctx, "scanzws: Error decompressing SWF file. Scanning what was decompressed.\n");
224 224
     }
225
-
226 225
     cli_dbgmsg("SWF: Decompressed[LZMA] to %s, size %d\n", tmpname, outsize);
227 226
 
227
+    /* check if declared output size matches actual output size */
228
+    if (hdr->filesize != outsize) {
229
+        cli_warnmsg("SWF: declared output length != inflated stream size, %u != %llu\n",
230
+                    hdr->filesize, (long long unsigned)outsize);
231
+    } else {
232
+        cli_dbgmsg("SWF: declared output length == inflated stream size, %u == %llu\n",
233
+                   hdr->filesize, (long long unsigned)outsize);
234
+    }
235
+
228 236
     ret = cli_magic_scandesc(fd, ctx);
229 237
 
230 238
     close(fd);
... ...
@@ -347,6 +399,15 @@ static int scancws(cli_ctx *ctx, struct swf_file_hdr *hdr)
347 347
     }
348 348
     cli_dbgmsg("SWF: Decompressed[zlib] to %s, size %d\n", tmpname, outsize);
349 349
 
350
+    /* check if declared output size matches actual output size */
351
+    if (hdr->filesize != outsize) {
352
+        cli_warnmsg("SWF: declared output length != inflated stream size, %u != %llu\n",
353
+                    hdr->filesize, (long long unsigned)outsize);
354
+    } else {
355
+        cli_dbgmsg("SWF: declared output length == inflated stream size, %u == %llu\n",
356
+                   hdr->filesize, (long long unsigned)outsize);
357
+    }
358
+
350 359
     ret = cli_magic_scandesc(fd, ctx);
351 360
 
352 361
     close(fd);