Increase robustness of LZW decoding to avoid buffer overflow on arbitrary manipulated input streams in combination with uninitalised memory.diff -r1.1.1.1 -r1.2 xsrc/xfree/xc/extras/freetype2/src/lzw/zopen.c
(joerg)
--- xsrc/xfree/xc/extras/freetype2/src/lzw/Attic/zopen.c 2005/03/18 13:07:34 1.1.1.1
+++ xsrc/xfree/xc/extras/freetype2/src/lzw/Attic/zopen.c 2011/08/16 18:17:19 1.2
@@ -1,15 +1,15 @@ | @@ -1,15 +1,15 @@ | |||
1 | /* $XFree86: xc/extras/freetype2/src/lzw/zopen.c,v 1.2 2004/12/16 22:15:48 tsi Exp $ */ | 1 | /* $XFree86: xc/extras/freetype2/src/lzw/zopen.c,v 1.2 2004/12/16 22:15:48 tsi Exp $ */ | |
2 | /* $NetBSD: zopen.c,v 1.1.1.1 2005/03/18 13:07:34 tron Exp $ */ | 2 | /* $NetBSD: zopen.c,v 1.2 2011/08/16 18:17:19 joerg Exp $ */ | |
3 | 3 | |||
4 | /*- | 4 | /*- | |
5 | * Copyright (c) 1985, 1986, 1992, 1993 | 5 | * Copyright (c) 1985, 1986, 1992, 1993 | |
6 | * The Regents of the University of California. All rights reserved. | 6 | * The Regents of the University of California. All rights reserved. | |
7 | * | 7 | * | |
8 | * This code is derived from software contributed to Berkeley by | 8 | * This code is derived from software contributed to Berkeley by | |
9 | * Diomidis Spinellis and James A. Woods, derived from original | 9 | * Diomidis Spinellis and James A. Woods, derived from original | |
10 | * work by Spencer Thomas and Joseph Orost. | 10 | * work by Spencer Thomas and Joseph Orost. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
15 | * 1. Redistributions of source code must retain the above copyright | 15 | * 1. Redistributions of source code must retain the above copyright | |
@@ -37,27 +37,27 @@ | @@ -37,27 +37,27 @@ | |||
37 | /*- | 37 | /*- | |
38 | * | 38 | * | |
39 | * Copyright (c) 2004 | 39 | * Copyright (c) 2004 | |
40 | * Albert Chin-A-Young. | 40 | * Albert Chin-A-Young. | |
41 | * | 41 | * | |
42 | * Modified to work with FreeType's PCF driver. | 42 | * Modified to work with FreeType's PCF driver. | |
43 | * | 43 | * | |
44 | */ | 44 | */ | |
45 | 45 | |||
46 | #if defined(LIBC_SCCS) && !defined(lint) | 46 | #if defined(LIBC_SCCS) && !defined(lint) | |
47 | #if 0 | 47 | #if 0 | |
48 | static char sccsid[] = "@(#)zopen.c 8.1 (Berkeley) 6/27/93"; | 48 | static char sccsid[] = "@(#)zopen.c 8.1 (Berkeley) 6/27/93"; | |
49 | #else | 49 | #else | |
50 | static char rcsid[] = "$NetBSD: zopen.c,v 1.1.1.1 2005/03/18 13:07:34 tron Exp $"; | 50 | static char rcsid[] = "$NetBSD: zopen.c,v 1.2 2011/08/16 18:17:19 joerg Exp $"; | |
51 | #endif | 51 | #endif | |
52 | #endif /* LIBC_SCCS and not lint */ | 52 | #endif /* LIBC_SCCS and not lint */ | |
53 | 53 | |||
54 | /*- | 54 | /*- | |
55 | * fcompress.c - File compression ala IEEE Computer, June 1984. | 55 | * fcompress.c - File compression ala IEEE Computer, June 1984. | |
56 | * | 56 | * | |
57 | * Compress authors: | 57 | * Compress authors: | |
58 | * Spencer W. Thomas (decvax!utah-cs!thomas) | 58 | * Spencer W. Thomas (decvax!utah-cs!thomas) | |
59 | * Jim McKie (decvax!mcvax!jim) | 59 | * Jim McKie (decvax!mcvax!jim) | |
60 | * Steve Davies (decvax!vax135!petsd!peora!srd) | 60 | * Steve Davies (decvax!vax135!petsd!peora!srd) | |
61 | * Ken Turkowski (decvax!decwrl!turtlevax!ken) | 61 | * Ken Turkowski (decvax!decwrl!turtlevax!ken) | |
62 | * James A. Woods (decvax!ihnp4!ames!jaw) | 62 | * James A. Woods (decvax!ihnp4!ames!jaw) | |
63 | * Joe Orost (decvax!vax135!petsd!joe) | 63 | * Joe Orost (decvax!vax135!petsd!joe) | |
@@ -204,87 +204,83 @@ zread(s_zstate_t *zs) | @@ -204,87 +204,83 @@ zread(s_zstate_t *zs) | |||
204 | goto middle; | 204 | goto middle; | |
205 | case S_EOF: | 205 | case S_EOF: | |
206 | goto eof; | 206 | goto eof; | |
207 | } | 207 | } | |
208 | 208 | |||
209 | maxbits = *(zs->next_in); /* Set -b from file. */ | 209 | maxbits = *(zs->next_in); /* Set -b from file. */ | |
210 | zs->avail_in--; | 210 | zs->avail_in--; | |
211 | zs->next_in++; | 211 | zs->next_in++; | |
212 | zs->total_in++; | 212 | zs->total_in++; | |
213 | in_count--; | 213 | in_count--; | |
214 | block_compress = maxbits & BLOCK_MASK; | 214 | block_compress = maxbits & BLOCK_MASK; | |
215 | maxbits &= BIT_MASK; | 215 | maxbits &= BIT_MASK; | |
216 | maxmaxcode = 1L << maxbits; | 216 | maxmaxcode = 1L << maxbits; | |
217 | if (maxbits > BITS) { | 217 | if (maxbits > BITS || maxbits < 12) { | |
218 | return -1; | 218 | return -1; | |
219 | } | 219 | } | |
220 | /* As above, initialize the first 256 entries in the table. */ | 220 | /* As above, initialize the first 256 entries in the table. */ | |
221 | maxcode = MAXCODE(n_bits = INIT_BITS); | 221 | maxcode = MAXCODE(n_bits = INIT_BITS); | |
222 | for (code = 255; code >= 0; code--) { | 222 | for (code = 255; code >= 0; code--) { | |
223 | tab_prefixof(code) = 0; | 223 | tab_prefixof(code) = 0; | |
224 | tab_suffixof(code) = (char_type) code; | 224 | tab_suffixof(code) = (char_type) code; | |
225 | } | 225 | } | |
226 | free_ent = block_compress ? FIRST : 256; | 226 | free_ent = block_compress ? FIRST : 256; | |
227 | 227 | oldcode = -1; | ||
228 | finchar = oldcode = getcode(zs); | |||
229 | if (oldcode == -1) /* EOF already? */ | |||
230 | return 0; /* Get out of here */ | |||
231 | ||||
232 | /* First code must be 8 bits = char. */ | |||
233 | *(zs->next_out)++ = (unsigned char)finchar; | |||
234 | zs->total_out++; | |||
235 | count--; | |||
236 | stackp = de_stack; | 228 | stackp = de_stack; | |
237 | 229 | |||
238 | while ((code = getcode(zs)) > -1) { | 230 | while ((code = getcode(zs)) > -1) { | |
239 | if ((code == CLEAR) && block_compress) { | 231 | if ((code == CLEAR) && block_compress) { | |
240 | for (code = 255; code >= 0; code--) | 232 | for (code = 255; code >= 0; code--) | |
241 | tab_prefixof(code) = 0; | 233 | tab_prefixof(code) = 0; | |
242 | clear_flg = 1; | 234 | clear_flg = 1; | |
243 | free_ent = FIRST - 1; | 235 | free_ent = FIRST ; | |
244 | if ((code = getcode(zs)) == -1) | 236 | oldcode = -1; | |
245 | /* O, untimely death! */ | 237 | continue; | |
246 | break; | |||
247 | } | 238 | } | |
248 | incode = code; | 239 | incode = code; | |
249 | 240 | |||
250 | /* Special case for KwKwK string. */ | 241 | /* Special case for KwKwK string. */ | |
251 | if (code >= free_ent) { | 242 | if (code >= free_ent) { | |
243 | if (code > free_ent || oldcode == -1) { | |||
244 | /* Bad stream. */ | |||
245 | errno = EINVAL; | |||
246 | return (-1); | |||
247 | } | |||
252 | *stackp++ = finchar; | 248 | *stackp++ = finchar; | |
253 | code = oldcode; | 249 | code = oldcode; | |
254 | } | 250 | } | |
255 | 251 | |||
256 | /* Generate output characters in reverse order. */ | 252 | /* Generate output characters in reverse order. */ | |
257 | while (code >= 256) { | 253 | while (code >= 256) { | |
258 | *stackp++ = tab_suffixof(code); | 254 | *stackp++ = tab_suffixof(code); | |
259 | code = tab_prefixof(code); | 255 | code = tab_prefixof(code); | |
260 | } | 256 | } | |
261 | *stackp++ = finchar = tab_suffixof(code); | 257 | *stackp++ = finchar = tab_suffixof(code); | |
262 | 258 | |||
263 | /* And put them out in forward order. */ | 259 | /* And put them out in forward order. */ | |
264 | middle: | 260 | middle: | |
265 | if (stackp == de_stack) | 261 | if (stackp == de_stack) | |
266 | continue; | 262 | continue; | |
267 | 263 | |||
268 | do { | 264 | do { | |
269 | if (count-- == 0) { | 265 | if (count-- == 0) { | |
270 | return zs->avail_out; | 266 | return zs->avail_out; | |
271 | } | 267 | } | |
272 | *(zs->next_out)++ = *--stackp; | 268 | *(zs->next_out)++ = *--stackp; | |
273 | zs->total_out++; | 269 | zs->total_out++; | |
274 | } while (stackp > de_stack); | 270 | } while (stackp > de_stack); | |
275 | 271 | |||
276 | /* Generate the new entry. */ | 272 | /* Generate the new entry. */ | |
277 | if ((code = free_ent) < maxmaxcode) { | 273 | if ((code = free_ent) < maxmaxcode && oldcode != -1) { | |
278 | tab_prefixof(code) = (unsigned short) oldcode; | 274 | tab_prefixof(code) = (unsigned short) oldcode; | |
279 | tab_suffixof(code) = finchar; | 275 | tab_suffixof(code) = finchar; | |
280 | free_ent = code + 1; | 276 | free_ent = code + 1; | |
281 | } | 277 | } | |
282 | 278 | |||
283 | /* Remember previous code. */ | 279 | /* Remember previous code. */ | |
284 | oldcode = incode; | 280 | oldcode = incode; | |
285 | } | 281 | } | |
286 | /* state = S_EOF; */ | 282 | /* state = S_EOF; */ | |
287 | eof: return (zs->avail_out - count); | 283 | eof: return (zs->avail_out - count); | |
288 | } | 284 | } | |
289 | 285 | |||
290 | /*- | 286 | /*- |