Browse code

More tidy ups

git-svn: trunk@3352

Nigel Horne authored on 2007/11/02 03:32:17
Showing 2 changed files
... ...
@@ -1,3 +1,8 @@
1
+Thu Nov  1 17:42:12 GMT 2007 (njh)
2
+----------------------------------
3
+  * libclamav/vba_extract.c:	More tidy ups. Fixed memory leak on error
4
+			return
5
+
1 6
 Thu Nov  1 16:14:50 CET 2007 (acab)
2 7
   * libclamav/autoit: add support for type10(int64) and some misc fixes
3 8
 
... ...
@@ -105,7 +105,7 @@ static uint32_t vba_endian_convert_32(uint32_t value, int is_mac)
105 105
 }
106 106
 
107 107
 #define NUM_VBA_VERSIONS 14
108
-static const vba_version_t vba_version[] = {
108
+static const vba_version_t vba_version[NUM_VBA_VERSIONS] = {
109 109
 	{ { 0x5e, 0x00, 0x00, 0x01 }, "Office 97",              5, FALSE},
110 110
 	{ { 0x5f, 0x00, 0x00, 0x01 }, "Office 97 SR1",          5, FALSE },
111 111
 	{ { 0x65, 0x00, 0x00, 0x01 }, "Office 2000 alpha?",     6, FALSE },
... ...
@@ -160,8 +160,10 @@ get_unicode_name(const char *name, int size, int is_mac)
160 160
 				newname[j++] = (char)('a'+((x&0xF)));
161 161
 				newname[j++] = (char)('a'+((x>>4)&0xF));
162 162
 				newname[j++] = (char)('a'+((x>>8)&0xF));
163
+#if	0
163 164
 				newname[j++] = (char)('a'+((x>>16)&0xF));	/* FIXME: x>>16 MUST == 0 */
164 165
 				newname[j++] = (char)('a'+((x>>24)&0xF));	/* FIXME: x>>24 MUST == 0 */
166
+#endif
165 167
 			}
166 168
                         newname[j++] = '_';
167 169
                 }
... ...
@@ -199,7 +201,8 @@ static void vba56_test_middle(int fd)
199 199
 	return;
200 200
 }
201 201
 
202
-static int vba_read_project_strings(int fd, int is_mac)
202
+static int
203
+vba_read_project_strings(int fd, int is_mac)
203 204
 {
204 205
 	for (;;) {
205 206
 		uint32_t offset;
... ...
@@ -215,7 +218,6 @@ static int vba_read_project_strings(int fd, int is_mac)
215 215
 			lseek(fd, -2, SEEK_CUR);
216 216
 			break;
217 217
 		}
218
-		cli_dbgmsg ("length: %d, ", length);
219 218
 		buff = (unsigned char *) cli_malloc(length);
220 219
 		if (!buff) {
221 220
 			cli_errmsg("cli_malloc failed\n");
... ...
@@ -230,46 +232,35 @@ static int vba_read_project_strings(int fd, int is_mac)
230 230
 			break;
231 231
 		}
232 232
 		name = get_unicode_name((const char *)buff, length, is_mac);
233
-		if (name) {
234
-			cli_dbgmsg("name: %s\n", name);
235
-		} else {
236
-			cli_dbgmsg("name: [null]\n");
237
-		}
233
+		if (name)
234
+			cli_dbgmsg("length: %d, name: %s\n", length, name);
235
+		else
236
+			cli_dbgmsg("length: %d, name: [null]\n", length);
238 237
 		free(buff);
239 238
 
240 239
 		/* Ignore twelve bytes from entries of type 'G'.
241 240
 		   Type 'C' entries come in pairs, the second also
242 241
 		   having a 12 byte trailer */
243 242
 		/* TODO: Need to check if types H(same as G) and D(same as C) exist */
244
-		if (name && (!strncmp ("*\\G", name, 3) || !strncmp ("*\\H", name, 3)
245
-				|| !strncmp("*\\C", name, 3) || !strncmp("*\\D", name, 3))) {
246
-			char namebuff[10];
247
-
248
-			if (cli_readn(fd, &length, 2) != 2) {
249
-				return FALSE;
250
-			}
251
-			length = vba_endian_convert_16(length, is_mac);
252
-			if ((length != 0) && (length != 65535)) {
253
-				lseek(fd, -2, SEEK_CUR);
254
-				free(name);
255
-				continue;
256
-			}
257
-			if (cli_readn(fd, namebuff, sizeof(namebuff)) != sizeof(namebuff)) {
258
-				cli_errmsg("failed to read namebuff\n");
259
-				free(name);
260
-				close(fd);
261
-				return FALSE;
262
-			}
263
-		} else {
243
+		if((name == NULL) || (memcmp("*\\", name, 2) != 0) ||
244
+		   (strchr("GCHD", name[2]) == NULL)) {
264 245
 			/* Unknown type - probably ran out of strings - rewind */
265 246
 			lseek(fd, -(length+2), SEEK_CUR);
266
-			if (name) {
247
+			if(name)
267 248
 				free(name);
268
-			}
269 249
 			break;
270 250
 		}
271 251
 		free(name);
272
-		offset = lseek(fd, 0, SEEK_CUR);
252
+
253
+		if (cli_readn(fd, &length, 2) != 2)
254
+			return FALSE;
255
+
256
+		length = vba_endian_convert_16(length, is_mac);
257
+		if ((length != 0) && (length != 65535)) {
258
+			lseek(fd, -2, SEEK_CUR);
259
+			continue;
260
+		}
261
+		offset = lseek(fd, 10, SEEK_CUR);
273 262
 		cli_dbgmsg("offset: %u\n", offset);
274 263
 		vba56_test_middle(fd);
275 264
 	}
... ...
@@ -337,14 +328,6 @@ vba_project_t *vba56_dir_read(const char *dir)
337 337
 		is_mac = vba_version[i].is_mac;
338 338
 	}
339 339
 
340
-#if	0
341
-	if((vba_endian_convert_16(v56h.ooff, is_mac) != 0xFF00)) {
342
-		cli_warnmsg("Expected 0xFF00, got 0x%x\n", v56h.ooff);
343
-		close(fd);
344
-		return NULL;
345
-	}
346
-#endif
347
-
348 340
 	if (!vba_read_project_strings(fd, is_mac)) {
349 341
 		close(fd);
350 342
 		return NULL;
... ...
@@ -447,17 +430,16 @@ vba_project_t *vba56_dir_read(const char *dir)
447 447
 			break;
448 448
 		}
449 449
 		vba_project->name[i] = get_unicode_name((const char *)buff, length, is_mac);
450
+		free(buff);
450 451
 		if (!vba_project->name[i]) {
451 452
 			offset = lseek(fd, 0, SEEK_CUR);
452 453
 			vba_project->name[i] = (char *) cli_malloc(18);
453 454
 			if(vba_project->name[i] == NULL) {
454
-				free(buff);
455 455
 				break;
456 456
 			}
457 457
 			snprintf(vba_project->name[i], 18, "clamav-%.10d", (int)offset);
458 458
 		}
459 459
 		cli_dbgmsg("project name: %s, ", vba_project->name[i]);
460
-		free(buff);
461 460
 
462 461
 		/* some kind of string identifier ?? */
463 462
 		if (cli_readn(fd, &length, 2) != 2) {
... ...
@@ -785,6 +767,7 @@ static int ppt_unlzw(const char *dir, int fd, uint32_t length)
785 785
 
786 786
 	if (cli_readn(fd, inbuff, stream.avail_in) != (int64_t)stream.avail_in) {
787 787
 		close(ofd);
788
+		unlink(fullname);
788 789
 		return FALSE;
789 790
 	}
790 791
 	length -= stream.avail_in;
... ...
@@ -888,16 +871,12 @@ static char *ppt_stream_iter(int fd)
888 888
 
889 889
 char *ppt_vba_read(const char *dir)
890 890
 {
891
-	char *fullname, *out_dir;
891
+	char *out_dir;
892 892
 	int fd;
893
+	char fullname[NAME_MAX + 1];
893 894
 
894
-	fullname = (char *) cli_malloc(strlen(dir) + 21);
895
-	if (!fullname) {
896
-		return NULL;
897
-	}
898
-	sprintf(fullname, "%s/PowerPoint Document", dir);
895
+	snprintf(fullname, sizeof(fullname) - 1, "%s/PowerPoint Document", dir);
899 896
 	fd = open(fullname, O_RDONLY|O_BINARY);
900
-	free(fullname);
901 897
 	if (fd == -1) {
902 898
 		cli_dbgmsg("Open PowerPoint Document failed\n");
903 899
 		return NULL;
... ...
@@ -917,7 +896,6 @@ typedef struct mso_fib_tag {
917 917
 	char ununsed[sizeof(uint16_t) + sizeof(uint16_t) +
918 918
 		sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint16_t) +
919 919
 		sizeof(uint16_t)];
920
-	/* block of 268 bytes - ignore */
921 920
 	uint32_t macro_offset;
922 921
 	uint32_t macro_len;
923 922
 } mso_fib_t;
... ...
@@ -970,11 +948,6 @@ typedef struct menu_entry_tag {
970 970
 	uint16_t pos;
971 971
 } menu_entry_t;
972 972
 
973
-typedef struct menu_info_tag {
974
-	uint16_t count;
975
-	struct menu_entry_tag *menu_entry;
976
-} menu_info_t;
977
-
978 973
 typedef struct mac_token_tag {
979 974
 	unsigned char token;
980 975
 	unsigned char *str;
... ...
@@ -1149,74 +1122,22 @@ static int wm_read_oxo3(int fd)
1149 1149
 	return TRUE;
1150 1150
 }
1151 1151
 
1152
-static menu_info_t *wm_read_menu_info(int fd)
1152
+static int
1153
+wm_skip_menu_info(int fd)
1153 1154
 {
1154
-	int i;
1155
-	menu_info_t *menu_info;
1156
-	menu_entry_t *menu_entry;
1157
-
1158
-	menu_info = (menu_info_t *) cli_malloc(sizeof(menu_info_t));
1159
-	if (!menu_info) {
1160
-		return NULL;
1161
-	}
1155
+	uint16_t count;
1162 1156
 
1163
-	if (cli_readn(fd, &menu_info->count, 2) != 2) {
1157
+	if (cli_readn(fd, &count, sizeof(uint16_t)) != sizeof(uint16_t)) {
1164 1158
 		cli_dbgmsg("read menu_info failed\n");
1165
-		free(menu_info);
1166
-		return NULL;
1167
-	}
1168
-	menu_info->count = vba_endian_convert_16(menu_info->count, FALSE);
1169
-	cli_dbgmsg("menu_info count: %d\n", menu_info->count);
1170
-
1171
-	menu_info->menu_entry =
1172
-		(menu_entry_t *) cli_malloc(sizeof(menu_entry_t) * menu_info->count);
1173
-	if (!menu_info->menu_entry) {
1174
-		free(menu_info);
1175
-		return NULL;
1176
-	}
1177
-
1178
-	for (i=0 ; i < menu_info->count ; i++) {
1179
-		menu_entry = &menu_info->menu_entry[i];
1180
-		if (cli_readn(fd, &menu_entry->context, 2) != 2) {
1181
-			goto abort;
1182
-		}
1183
-		if (cli_readn(fd, &menu_entry->menu, 2) != 2) {
1184
-			goto abort;
1185
-		}
1186
-		if (cli_readn(fd, &menu_entry->extname_i, 2) != 2) {
1187
-			goto abort;
1188
-		}
1189
-		if (cli_readn(fd, &menu_entry->unknown, 2) != 2) {
1190
-			goto abort;
1191
-		}
1192
-		if (cli_readn(fd, &menu_entry->intname_i, 2) != 2) {
1193
-			goto abort;
1194
-		}
1195
-		if (cli_readn(fd, &menu_entry->pos, 2) != 2) {
1196
-			goto abort;
1197
-		}
1198
-		menu_entry->context = vba_endian_convert_16(menu_entry->context, FALSE);
1199
-		menu_entry->menu = vba_endian_convert_16(menu_entry->menu, FALSE);
1200
-		menu_entry->extname_i = vba_endian_convert_16(menu_entry->extname_i, FALSE);
1201
-		menu_entry->intname_i = vba_endian_convert_16(menu_entry->intname_i, FALSE);
1202
-		menu_entry->pos = vba_endian_convert_16(menu_entry->pos, FALSE);
1203
-		cli_dbgmsg("menu entry: %d.%d\n", menu_entry->menu, menu_entry->pos);
1159
+		return FALSE;
1204 1160
 	}
1205
-	return menu_info;
1206
-
1207
-abort:
1208
-	cli_dbgmsg("read menu_entry failed\n");
1209
-	free(menu_info->menu_entry);
1210
-	free(menu_info);
1211
-	return NULL;
1212
-}
1161
+	count = vba_endian_convert_16(count, FALSE);
1162
+	cli_dbgmsg("menu_info count: %d\n", count);
1213 1163
 
1214
-static void wm_free_menu_info(menu_info_t *menu_info)
1215
-{
1216
-	if (menu_info) {
1217
-		free(menu_info->menu_entry);
1218
-		free(menu_info);
1219
-	}
1164
+	if(count)
1165
+		if(lseek(fd, count * 12, SEEK_CUR) == -1)
1166
+			return FALSE;
1167
+	return TRUE;
1220 1168
 }
1221 1169
 
1222 1170
 static macro_extnames_t *wm_read_macro_extnames(int fd)
... ...
@@ -1420,20 +1341,13 @@ vba_project_t *wm_dir_read(const char *dir)
1420 1420
 	int fd, done=FALSE, i;
1421 1421
 	mso_fib_t fib;
1422 1422
 	off_t end_offset;
1423
-	unsigned char start_id, info_id;
1423
+	unsigned char info_id;
1424 1424
 	macro_info_t *macro_info=NULL;
1425
-	macro_extnames_t *macro_extnames=NULL;
1426
-	macro_intnames_t *macro_intnames=NULL;
1427 1425
 	vba_project_t *vba_project=NULL;
1428
-	char *fullname;
1426
+	char fullname[NAME_MAX + 1];
1429 1427
 
1430
-	fullname = (char *) cli_malloc(strlen(dir) + 14);
1431
-	if (!fullname) {
1432
-		return NULL;
1433
-	}
1434
-	sprintf(fullname, "%s/WordDocument", dir);
1428
+	snprintf(fullname, sizeof(fullname) - 1, "%s/WordDocument", dir);
1435 1429
 	fd = open(fullname, O_RDONLY|O_BINARY);
1436
-	free(fullname);
1437 1430
 	if (fd == -1) {
1438 1431
 		cli_dbgmsg("Open WordDocument failed\n");
1439 1432
 		return NULL;
... ...
@@ -1443,9 +1357,16 @@ vba_project_t *wm_dir_read(const char *dir)
1443 1443
 		close(fd);
1444 1444
 		return NULL;
1445 1445
 	}
1446
+	if(fib.macro_len == 0) {
1447
+		cli_dbgmsg("No macros detected\n");
1448
+		/* Must be clean */
1449
+		close(fd);
1450
+		return NULL;
1451
+	}
1446 1452
 	wm_print_fib(&fib);
1447 1453
 
1448
-	if (lseek(fd, fib.macro_offset, SEEK_SET) != (int64_t)fib.macro_offset) {
1454
+	/* Go one past the start to ignore start_id */
1455
+	if (lseek(fd, fib.macro_offset + 1, SEEK_SET) != (off_t)(fib.macro_offset + 1)) {
1449 1456
 		cli_dbgmsg("lseek macro_offset failed\n");
1450 1457
 		close(fd);
1451 1458
 		return NULL;
... ...
@@ -1453,15 +1374,9 @@ vba_project_t *wm_dir_read(const char *dir)
1453 1453
 
1454 1454
 	end_offset = fib.macro_offset + fib.macro_len;
1455 1455
 
1456
-	if (cli_readn(fd, &start_id, 1) != 1) {
1457
-		cli_dbgmsg("read start_id failed\n");
1458
-		close(fd);
1459
-		return NULL;
1460
-	}
1461
-	cli_dbgmsg("start_id: %d\n", start_id);
1462
-
1463 1456
 	while ((lseek(fd, 0, SEEK_CUR) < end_offset) && !done) {
1464
-		menu_info_t *menu_info;
1457
+		macro_intnames_t *macro_intnames;
1458
+		macro_extnames_t *macro_extnames;
1465 1459
 
1466 1460
 		if (cli_readn(fd, &info_id, 1) != 1) {
1467 1461
 			cli_dbgmsg("read macro_info failed\n");
... ...
@@ -1476,42 +1391,40 @@ vba_project_t *wm_dir_read(const char *dir)
1476 1476
 				}
1477 1477
 				break;
1478 1478
 			case 0x03:
1479
-				if (!wm_read_oxo3(fd)) {
1479
+				if(!wm_read_oxo3(fd))
1480 1480
 					done = TRUE;
1481
-				}
1482 1481
 				break;
1483 1482
 			case 0x05:
1484
-				menu_info = wm_read_menu_info(fd);
1485
-				if(menu_info)
1486
-					wm_free_menu_info(menu_info);
1487
-				else
1483
+				if(!wm_skip_menu_info(fd))
1488 1484
 					done = TRUE;
1489 1485
 				break;
1490 1486
 			case 0x10:
1491 1487
 				macro_extnames = wm_read_macro_extnames(fd);
1492
-				if (macro_extnames == NULL) {
1488
+				if(macro_extnames)
1489
+					wm_free_extnames(macro_extnames);
1490
+				else
1493 1491
 					done = TRUE;
1494
-				}
1495 1492
 				break;
1496 1493
 			case 0x11:
1497 1494
 				macro_intnames = wm_read_macro_intnames(fd);
1498
-				if (macro_intnames == NULL) {
1495
+				if(macro_intnames)
1496
+					wm_free_intnames(macro_intnames);
1497
+				else
1499 1498
 					done = TRUE;
1500
-				}
1501 1499
 				break;
1502 1500
 			case 0x12:
1503 1501
 				/* No sure about these, always seems to
1504 1502
 				come after the macros though, so finish
1505 1503
 				*/
1506
-				done = 1;
1504
+				done = TRUE;
1507 1505
 				break;
1508 1506
 			case 0x40:
1509 1507
 				/* end marker */
1510
-				done = 1;
1508
+				done = TRUE;
1511 1509
 				break;
1512 1510
 			default:
1513 1511
 				cli_dbgmsg("\nunknown type: 0x%x\n", info_id);
1514
-				done = 1;
1512
+				done = TRUE;
1515 1513
 		}
1516 1514
 	}
1517 1515
 
... ...
@@ -1568,15 +1481,8 @@ vba_project_t *wm_dir_read(const char *dir)
1568 1568
 	}
1569 1569
 	/* Fall through */
1570 1570
 abort:
1571
-	if (macro_info) {
1571
+	if (macro_info)
1572 1572
 		wm_free_macro_info(macro_info);
1573
-	}
1574
-	if (macro_extnames) {
1575
-		wm_free_extnames(macro_extnames);
1576
-	}
1577
-	if (macro_intnames) {
1578
-		wm_free_intnames(macro_intnames);
1579
-	}
1580 1573
 	close(fd);
1581 1574
 	return vba_project;
1582 1575
 }