git-svn: trunk@998
Nigel Horne authored on 2004/10/15 02:45:55... | ... |
@@ -16,6 +16,9 @@ |
16 | 16 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 | 17 |
* |
18 | 18 |
* $Log: line.c,v $ |
19 |
+ * Revision 1.6 2004/10/14 17:45:55 nigelhorne |
|
20 |
+ * Try to reclaim some memory if it becomes low when decoding |
|
21 |
+ * |
|
19 | 22 |
* Revision 1.5 2004/09/30 08:58:56 nigelhorne |
20 | 23 |
* Remove empty lines |
21 | 24 |
* |
... | ... |
@@ -33,7 +36,7 @@ |
33 | 33 |
* |
34 | 34 |
*/ |
35 | 35 |
|
36 |
-static char const rcsid[] = "$Id: line.c,v 1.5 2004/09/30 08:58:56 nigelhorne Exp $"; |
|
36 |
+static char const rcsid[] = "$Id: line.c,v 1.6 2004/10/14 17:45:55 nigelhorne Exp $"; |
|
37 | 37 |
|
38 | 38 |
#if HAVE_CONFIG_H |
39 | 39 |
#include "clamav-config.h" |
... | ... |
@@ -142,4 +145,10 @@ lineGetData(const line_t *line) |
142 | 142 |
{ |
143 | 143 |
return line ? &line[1] : NULL; |
144 | 144 |
} |
145 |
+ |
|
146 |
+unsigned char |
|
147 |
+lineGetRefCount(const line_t *line) |
|
148 |
+{ |
|
149 |
+ return line[0]; |
|
150 |
+} |
|
145 | 151 |
#endif |
... | ... |
@@ -16,6 +16,9 @@ |
16 | 16 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 | 17 |
* |
18 | 18 |
* $Log: line.h,v $ |
19 |
+ * Revision 1.4 2004/10/14 17:45:55 nigelhorne |
|
20 |
+ * Try to reclaim some memory if it becomes low when decoding |
|
21 |
+ * |
|
19 | 22 |
* Revision 1.3 2004/08/21 11:57:57 nigelhorne |
20 | 23 |
* Use line.[ch] |
21 | 24 |
* |
... | ... |
@@ -45,5 +48,6 @@ line_t *lineCreate(const char *data); |
45 | 45 |
line_t *lineLink(line_t *line); |
46 | 46 |
line_t *lineUnlink(line_t *line); |
47 | 47 |
const char *lineGetData(const line_t *line); |
48 |
+unsigned char lineGetRefCount(const line_t *line); |
|
48 | 49 |
|
49 | 50 |
#endif |
... | ... |
@@ -17,6 +17,9 @@ |
17 | 17 |
* |
18 | 18 |
* Change History: |
19 | 19 |
* $Log: message.c,v $ |
20 |
+ * Revision 1.100 2004/10/14 17:45:55 nigelhorne |
|
21 |
+ * Try to reclaim some memory if it becomes low when decoding |
|
22 |
+ * |
|
20 | 23 |
* Revision 1.99 2004/10/12 10:40:48 nigelhorne |
21 | 24 |
* Remove shadow declaration of isblank |
22 | 25 |
* |
... | ... |
@@ -294,7 +297,7 @@ |
294 | 294 |
* uuencodebegin() no longer static |
295 | 295 |
* |
296 | 296 |
*/ |
297 |
-static char const rcsid[] = "$Id: message.c,v 1.99 2004/10/12 10:40:48 nigelhorne Exp $"; |
|
297 |
+static char const rcsid[] = "$Id: message.c,v 1.100 2004/10/14 17:45:55 nigelhorne Exp $"; |
|
298 | 298 |
|
299 | 299 |
#if HAVE_CONFIG_H |
300 | 300 |
#include "clamav-config.h" |
... | ... |
@@ -355,6 +358,7 @@ static unsigned char uudecode(char c); |
355 | 355 |
static const char *messageGetArgument(const message *m, int arg); |
356 | 356 |
static void *messageExport(message *m, const char *dir, void *(*create)(void), void (*destroy)(void *), void (*setFilename)(void *, const char *, const char *), void (*addData)(void *, const unsigned char *, size_t), void *(*exportText)(const text *, void *)); |
357 | 357 |
static int usefulArg(const char *arg); |
358 |
+static void messageDedup(message *m); |
|
358 | 359 |
|
359 | 360 |
/* |
360 | 361 |
* These maps are ordered in decreasing likelyhood of their appearance |
... | ... |
@@ -1035,14 +1039,26 @@ messageAddStr(message *m, const char *data) |
1035 | 1035 |
if(m->body_first == NULL) |
1036 | 1036 |
m->body_last = m->body_first = (text *)cli_malloc(sizeof(text)); |
1037 | 1037 |
else { |
1038 |
+ assert(m->body_last != NULL); |
|
1038 | 1039 |
m->body_last->t_next = (text *)cli_malloc(sizeof(text)); |
1040 |
+ if(m->body_last->t_next == NULL) { |
|
1041 |
+ messageDedup(m); |
|
1042 |
+ m->body_last->t_next = (text *)cli_malloc(sizeof(text)); |
|
1043 |
+ if(m->body_last->t_next == NULL) { |
|
1044 |
+ cli_errmsg("messageAddStr: out of memory\n"); |
|
1045 |
+ return -1; |
|
1046 |
+ } |
|
1047 |
+ } |
|
1048 |
+ |
|
1039 | 1049 |
if(data && m->body_last->t_line && (strcmp(data, lineGetData(m->body_last->t_line)) == 0)) |
1040 | 1050 |
repeat = m->body_last->t_line; |
1041 | 1051 |
m->body_last = m->body_last->t_next; |
1042 | 1052 |
} |
1043 | 1053 |
|
1044 |
- if(m->body_last == NULL) |
|
1054 |
+ if(m->body_last == NULL) { |
|
1055 |
+ cli_errmsg("messageAddStr: out of memory\n"); |
|
1045 | 1056 |
return -1; |
1057 |
+ } |
|
1046 | 1058 |
|
1047 | 1059 |
m->body_last->t_next = NULL; |
1048 | 1060 |
|
... | ... |
@@ -1052,15 +1068,14 @@ messageAddStr(message *m, const char *data) |
1052 | 1052 |
else |
1053 | 1053 |
m->body_last->t_line = lineCreate(data); |
1054 | 1054 |
|
1055 |
- if(m->body_last->t_line == NULL) { |
|
1056 |
- /* |
|
1057 |
- * TODO: Here we could go through all the message |
|
1058 |
- * looking for duplicate lines we can line. It'd be |
|
1059 |
- * very slow, but it could save enough memory to |
|
1060 |
- * continue... |
|
1061 |
- */ |
|
1062 |
- cli_errmsg("messageAddStr: out of memory\n"); |
|
1063 |
- return -1; |
|
1055 |
+ if((m->body_last->t_line == NULL) && (repeat == NULL)) { |
|
1056 |
+ messageDedup(m); |
|
1057 |
+ m->body_last->t_line = lineCreate(data); |
|
1058 |
+ |
|
1059 |
+ if(m->body_last->t_line == NULL) { |
|
1060 |
+ cli_errmsg("messageAddStr: out of memory\n"); |
|
1061 |
+ return -1; |
|
1062 |
+ } |
|
1064 | 1063 |
} |
1065 | 1064 |
/* cli_chomp(m->body_last->t_text); */ |
1066 | 1065 |
|
... | ... |
@@ -1638,7 +1653,7 @@ fileblob * |
1638 | 1638 |
messageToFileblob(message *m, const char *dir) |
1639 | 1639 |
{ |
1640 | 1640 |
cli_dbgmsg("messageToFileblob\n"); |
1641 |
- return messageExport(m, dir, fileblobCreate, fileblobDestroy, fileblobSetFilename, fileblobAddData, textToFileblob); |
|
1641 |
+ return messageExport(m, dir, (void *)fileblobCreate, (void *)fileblobDestroy, (void *)fileblobSetFilename, (void *)fileblobAddData, (void *)textToFileblob); |
|
1642 | 1642 |
} |
1643 | 1643 |
|
1644 | 1644 |
/* |
... | ... |
@@ -1648,7 +1663,7 @@ messageToFileblob(message *m, const char *dir) |
1648 | 1648 |
blob * |
1649 | 1649 |
messageToBlob(message *m) |
1650 | 1650 |
{ |
1651 |
- return messageExport(m, NULL, blobCreate, blobDestroy, blobSetFilename, blobAddData, textToBlob); |
|
1651 |
+ return messageExport(m, NULL, (void *)blobCreate, (void *)blobDestroy, (void *)blobSetFilename, (void *)blobAddData, (void *)textToBlob); |
|
1652 | 1652 |
} |
1653 | 1653 |
|
1654 | 1654 |
/* |
... | ... |
@@ -2351,3 +2366,72 @@ usefulArg(const char *arg) |
2351 | 2351 |
} |
2352 | 2352 |
return 1; |
2353 | 2353 |
} |
2354 |
+ |
|
2355 |
+/* |
|
2356 |
+ * We've run out of memory. Try to recover some by |
|
2357 |
+ * deduping the message |
|
2358 |
+ */ |
|
2359 |
+static void |
|
2360 |
+messageDedup(message *m) |
|
2361 |
+{ |
|
2362 |
+ const text *t1; |
|
2363 |
+ size_t saved = 0; |
|
2364 |
+ |
|
2365 |
+ t1 = m->dedupedThisFar ? m->dedupedThisFar : m->body_first; |
|
2366 |
+ |
|
2367 |
+ for(t1 = m->body_first; t1; t1 = t1->t_next) { |
|
2368 |
+ const char *d1; |
|
2369 |
+ text *t2; |
|
2370 |
+ line_t *l1; |
|
2371 |
+ unsigned int r1; |
|
2372 |
+ |
|
2373 |
+ if(saved >= 100*1000) |
|
2374 |
+ break; /* that's enough */ |
|
2375 |
+ l1 = t1->t_line; |
|
2376 |
+ if(l1 == NULL) |
|
2377 |
+ continue; |
|
2378 |
+ d1 = lineGetData(l1); |
|
2379 |
+ if(strlen(d1) < 8) |
|
2380 |
+ continue; /* wouldn't recover many bytes */ |
|
2381 |
+ r1 = (unsigned int)lineGetRefCount(l1); |
|
2382 |
+ if(r1 == 255) |
|
2383 |
+ continue; |
|
2384 |
+ /* |
|
2385 |
+ * We don't want to foul up any pointers |
|
2386 |
+ */ |
|
2387 |
+ if(t1 == m->encoding) |
|
2388 |
+ continue; |
|
2389 |
+ if(t1 == m->bounce) |
|
2390 |
+ continue; |
|
2391 |
+ if(t1 == m->uuencode) |
|
2392 |
+ continue; |
|
2393 |
+ if(t1 == m->binhex) |
|
2394 |
+ continue; |
|
2395 |
+ if(t1 == m->yenc) |
|
2396 |
+ continue; |
|
2397 |
+ |
|
2398 |
+ for(t2 = t1->t_next; t2; t2 = t2->t_next) { |
|
2399 |
+ const char *d2; |
|
2400 |
+ line_t *l2 = t2->t_line; |
|
2401 |
+ |
|
2402 |
+ if(l2 == NULL) |
|
2403 |
+ continue; |
|
2404 |
+ if((r1 + (unsigned int)lineGetRefCount(l2)) > 255) |
|
2405 |
+ continue; |
|
2406 |
+ d2 = lineGetData(l2); |
|
2407 |
+ if(d1 == d2) |
|
2408 |
+ /* already linked */ |
|
2409 |
+ continue; |
|
2410 |
+ if(strcmp(d1, d2) == 0) { |
|
2411 |
+ if(lineUnlink(l2) == NULL) |
|
2412 |
+ saved += strlen(d1); |
|
2413 |
+ t2->t_line = lineLink(l1); |
|
2414 |
+ if(t2->t_line == NULL) { |
|
2415 |
+ cli_errmsg("messageDedup: out of memory\n"); |
|
2416 |
+ return; |
|
2417 |
+ } |
|
2418 |
+ } |
|
2419 |
+ } |
|
2420 |
+ } |
|
2421 |
+ m->dedupedThisFar = t1; |
|
2422 |
+} |
... | ... |
@@ -16,6 +16,9 @@ |
16 | 16 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 | 17 |
* |
18 | 18 |
* $Log: message.h,v $ |
19 |
+ * Revision 1.20 2004/10/14 17:45:55 nigelhorne |
|
20 |
+ * Try to reclaim some memory if it becomes low when decoding |
|
21 |
+ * |
|
19 | 22 |
* Revision 1.19 2004/09/17 13:47:19 nigelhorne |
20 | 23 |
* Handle yEnc attachments |
21 | 24 |
* |
... | ... |
@@ -90,6 +93,7 @@ typedef struct message { |
90 | 90 |
text *uuencode; /* start of a uuencoded message */ |
91 | 91 |
text *yenc; /* start of a yEnc message */ |
92 | 92 |
text *encoding; /* is the non MIME message encoded? */ |
93 |
+ text *dedupedThisFar; |
|
93 | 94 |
} message; |
94 | 95 |
|
95 | 96 |
message *messageCreate(void); |