Browse code

use mmap() when available

git-svn: trunk@1786

Tomasz Kojm authored on 2005/12/16 04:53:52
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Thu Dec 15 20:51:27 CET 2005 (tk)
2
+---------------------------------
3
+  * libclamav/sis.c: use mmap() when available
4
+
1 5
 Thu Dec 15 02:52:01 CET 2005 (tk)
2 6
 ---------------------------------
3 7
   * libclamav/sis.[ch]: new files
... ...
@@ -29,6 +29,14 @@
29 29
 #include <unistd.h>
30 30
 #include <time.h>
31 31
 
32
+#if HAVE_MMAP
33
+#if HAVE_SYS_MMAN_H
34
+#include <sys/mman.h>
35
+#else /* HAVE_SYS_MMAN_H */
36
+#undef HAVE_MMAP
37
+#endif
38
+#endif
39
+
32 40
 #include "cltypes.h"
33 41
 #include "clamav.h"
34 42
 #include "others.h"
... ...
@@ -69,17 +77,46 @@ int cli_scansis(int desc, const char **virname, long int *scanned, const struct
69 69
 	struct sis_file_hdr6 file_hdr6;
70 70
 	uint8_t release = 0;
71 71
 	uint16_t opts, nlangs, *langrecs;
72
-	char *langs;
72
+	char *mfile = NULL, *langs;
73
+	struct stat sb;
73 74
 	int i;
74 75
 
75 76
 
76
-    if(read(desc, &file_hdr, sizeof(struct sis_file_hdr)) != sizeof(struct sis_file_hdr)) {
77
-	cli_dbgmsg("SIS: Can't read file header\n"); /* Not a SIS file? */
77
+    if(fstat(desc, &sb) == -1) {
78
+	cli_errmsg("SIS: fstat() failed\n");
79
+	return CL_EIO;
80
+    }
81
+
82
+    if(sb.st_size < sizeof(struct sis_file_hdr)) {
83
+	cli_dbgmsg("SIS: Broken or not a SIS file (too small)\n");
78 84
 	return CL_CLEAN;
79 85
     }
80 86
 
87
+#if HAVE_MMAP
88
+    if(sb.st_size < 33554432) {
89
+	mfile = (char *) mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, desc, 0);
90
+	if(mfile == MAP_FAILED) {
91
+	    mfile = NULL;
92
+	} else {
93
+	    cli_dbgmsg("SIS: mmap'ed file\n");
94
+	    memcpy(&file_hdr, mfile, sizeof(struct sis_file_hdr));
95
+	}
96
+    }
97
+#endif
98
+
99
+    if(!mfile) {
100
+	if(read(desc, &file_hdr, sizeof(struct sis_file_hdr)) != sizeof(struct sis_file_hdr)) {
101
+	    cli_dbgmsg("SIS: Can't read file header\n"); /* Not a SIS file? */
102
+	    return CL_CLEAN;
103
+	}
104
+    }
105
+
81 106
     if(EC32(file_hdr.uid3) != 0x10000419) {
82 107
 	cli_dbgmsg("SIS: Not a SIS file\n");
108
+#if HAVE_MMAP
109
+	if(mfile)
110
+	    munmap(mfile, sb.st_size);
111
+#endif
83 112
 	return CL_CLEAN;
84 113
     }
85 114
 
... ...
@@ -104,17 +141,32 @@ int cli_scansis(int desc, const char **virname, long int *scanned, const struct
104 104
     cli_dbgmsg("SIS: Offset of languages records: %d\n", EC32(file_hdr.plangs));
105 105
 
106 106
     if(nlangs && nlangs < 100) {
107
-	if(lseek(desc, EC32(file_hdr.plangs), SEEK_SET) < 0) {
108
-	    cli_errmsg("SIS: No language records\n");
107
+
108
+	if(EC32(file_hdr.plangs) + nlangs * 2 >= sb.st_size) {
109
+	    cli_errmsg("SIS: Broken file structure (language records)\n");
110
+#if HAVE_MMAP
111
+	    if(mfile)
112
+		munmap(mfile, sb.st_size);
113
+#endif
109 114
 	    return CL_EFORMAT;
110 115
 	}
111 116
 
112 117
 	langrecs = (uint16_t *) cli_malloc(nlangs * 2);
113 118
 
114
-	if(read(desc, langrecs, nlangs * 2) != nlangs * 2) {
115
-	    cli_errmsg("SIS: Can't read language records\n");
116
-	    free(langrecs);
117
-	    return CL_EFORMAT;
119
+	if(!mfile) {
120
+	    if(lseek(desc, EC32(file_hdr.plangs), SEEK_SET) < 0) {
121
+		cli_errmsg("SIS: No language records\n");
122
+		free(langrecs);
123
+		return CL_EFORMAT;
124
+	    }
125
+
126
+	    if(read(desc, langrecs, nlangs * 2) != nlangs * 2) {
127
+		cli_errmsg("SIS: Can't read language records\n");
128
+		free(langrecs);
129
+		return CL_EFORMAT;
130
+	    }
131
+	} else {
132
+	    memcpy(langrecs, mfile + EC32(file_hdr.plangs), nlangs * 2);
118 133
 	}
119 134
 
120 135
 	langs = (char *) cli_calloc(nlangs * 3 + 1, sizeof(char));
... ...
@@ -184,16 +236,33 @@ int cli_scansis(int desc, const char **virname, long int *scanned, const struct
184 184
 
185 185
     if(release == 6) {
186 186
 
187
-	lseek(desc, sizeof(struct sis_file_hdr), SEEK_SET);
188
-
189
-	if(read(desc, &file_hdr6, sizeof(struct sis_file_hdr6)) != sizeof(struct sis_file_hdr6)) {
190
-	    cli_dbgmsg("SIS: Can't read additional data of EPOC 6 file header\n"); /* Not a SIS file? */
187
+	if(sizeof(struct sis_file_hdr) + sizeof(struct sis_file_hdr6) >= sb.st_size) {
188
+	    cli_errmsg("SIS: Broken file structure (language records)\n");
189
+#if HAVE_MMAP
190
+	    if(mfile)
191
+		munmap(mfile, sb.st_size);
192
+#endif
191 193
 	    return CL_EFORMAT;
192 194
 	}
193 195
 
196
+
197
+	if(!mfile) {
198
+	    lseek(desc, sizeof(struct sis_file_hdr), SEEK_SET);
199
+
200
+	    if(read(desc, &file_hdr6, sizeof(struct sis_file_hdr6)) != sizeof(struct sis_file_hdr6)) {
201
+		cli_dbgmsg("SIS: Can't read additional data of EPOC 6 file header\n"); /* Not a SIS file? */
202
+		return CL_EFORMAT;
203
+	    }
204
+	} else {
205
+	    memcpy(&file_hdr6, mfile + sizeof(struct sis_file_hdr), sizeof(struct sis_file_hdr6));
206
+	}
194 207
 	cli_dbgmsg("SIS: Maximum space required: %d\n", EC32(file_hdr6.maxispace));
195 208
     }
196 209
 
210
+#if HAVE_MMAP
211
+    if(mfile)
212
+	munmap(mfile, sb.st_size);
213
+#endif
197 214
 
198 215
     return CL_CLEAN;
199 216
 }