Browse code

kwaj_read_headers(): fix handling of non-terminated strings

Stuart Caie authored on 2017/11/26 23:28:54
Showing 1 changed files
... ...
@@ -198,30 +198,36 @@ static int kwajd_read_headers(struct mspack_system *sys,
198 198
 
199 199
     /* filename and extension */
200 200
     if (hdr->headers & (MSKWAJ_HDR_HASFILENAME | MSKWAJ_HDR_HASFILEEXT)) {
201
-	off_t pos = sys->tell(fh);
202
-	char *fn = (char *) sys->alloc(sys, (size_t) 13);
203
-
201
+	int len;
204 202
 	/* allocate memory for maximum length filename */
205
-	if (! fn) return MSPACK_ERR_NOMEMORY;
206
-	hdr->filename = fn;
203
+	char *fn = (char *) sys->alloc(sys, (size_t) 13);
204
+	if (!(hdr->filename = fn)) return MSPACK_ERR_NOMEMORY;
207 205
 
208 206
 	/* copy filename if present */
209 207
 	if (hdr->headers & MSKWAJ_HDR_HASFILENAME) {
210
-	    if (sys->read(fh, &buf[0], 9) != 9) return MSPACK_ERR_READ;
211
-	    for (i = 0; i < 9; i++, fn++) if (!(*fn = buf[i])) break;
212
-	    pos += (i < 9) ? i+1 : 9;
213
-	    if (sys->seek(fh, pos, MSPACK_SYS_SEEK_START))
208
+	    /* read and copy up to 9 bytes of a null terminated string */
209
+	    if ((len = sys->read(fh, &buf[0], 9)) < 2) return MSPACK_ERR_READ;
210
+	    for (i = 0; i < len; i++) if (!(*fn++ = buf[i])) break;
211
+	    /* if string was 9 bytes with no null terminator, reject it */
212
+	    if (i == 9 && buf[8] != '\0') return MSPACK_ERR_DATAFORMAT;
213
+	    /* seek to byte after string ended in file */
214
+	    if (sys->seek(fh, (off_t)(i + 1 - len), MSPACK_SYS_SEEK_CUR))
214 215
 		return MSPACK_ERR_SEEK;
216
+	    fn--; /* remove the null terminator */
215 217
 	}
216 218
 
217 219
 	/* copy extension if present */
218 220
 	if (hdr->headers & MSKWAJ_HDR_HASFILEEXT) {
219 221
 	    *fn++ = '.';
220
-	    if (sys->read(fh, &buf[0], 4) != 4) return MSPACK_ERR_READ;
221
-	    for (i = 0; i < 4; i++, fn++) if (!(*fn = buf[i])) break;
222
-	    pos += (i < 4) ? i+1 : 4;
223
-	    if (sys->seek(fh, pos, MSPACK_SYS_SEEK_START))
222
+	    /* read and copy up to 4 bytes of a null terminated string */
223
+	    if ((len = sys->read(fh, &buf[0], 4)) < 2) return MSPACK_ERR_READ;
224
+	    for (i = 0; i < len; i++) if (!(*fn++ = buf[i])) break;
225
+	    /* if string was 4 bytes with no null terminator, reject it */
226
+	    if (i == 4 && buf[3] != '\0') return MSPACK_ERR_DATAFORMAT;
227
+	    /* seek to byte after string ended in file */
228
+	    if (sys->seek(fh, (off_t)(i + 1 - len), MSPACK_SYS_SEEK_CUR))
224 229
 		return MSPACK_ERR_SEEK;
230
+	    fn--; /* remove the null terminator */
225 231
 	}
226 232
 	*fn = '\0';
227 233
     }