summaryrefslogtreecommitdiff
path: root/src/fontfile/decompress.c
diff options
context:
space:
mode:
authorJoerg Sonnenberger <joerg@britannica.bec.de>2011-08-21 18:51:53 +0200
committerMatthieu Herrb <matthieu.herrb@laas.fr>2011-09-17 18:43:26 +0200
commitbd48ad11fd11412c62c3ac8ed5d52c4f10a985aa (patch)
tree21b2b63890e93b5af7761ae1dd7fc79cc60c157a /src/fontfile/decompress.c
parent098ab294deed98371ee362fadafcf2e510e0cc50 (diff)
Do proper input validation to fix for CVE-2011-2895.
It ensures that all valid input can be decompressed, checks that the overflow conditions doesn't happen and generally tightens the validation of the LZW stream and doesn't pessimize the inner loop for no good reason. It's derived from a change in libarchive from 2004. Signed-off-by: Matthieu Herrb <matthieu.herrb@laas.fr> Reviewed-by: Tomas Hoger <thoger@redhat.com>
Diffstat (limited to 'src/fontfile/decompress.c')
-rw-r--r--src/fontfile/decompress.c29
1 files changed, 16 insertions, 13 deletions
diff --git a/src/fontfile/decompress.c b/src/fontfile/decompress.c
index 0f28c3f..6405d76 100644
--- a/src/fontfile/decompress.c
+++ b/src/fontfile/decompress.c
@@ -99,3 +99,3 @@ static char_type magic_header[] = { "\037\235" }; /* 1F 9D */
-#define STACK_SIZE 8192
+#define STACK_SIZE 65300
@@ -180,2 +180,3 @@ BufFilePushCompressed (BufFilePtr f)
file->free_ent = ((file->block_compress) ? FIRST : 256 );
+ file->oldcode = -1;
file->clear_flg = 0;
@@ -185,5 +186,2 @@ BufFilePushCompressed (BufFilePtr f)
bzero(file->buf, BITS);
- file->finchar = file->oldcode = getcode (file);
- if (file->oldcode != -1)
- *file->stackp++ = file->finchar;
return BufFileCreate ((char *) file,
@@ -232,5 +230,2 @@ BufCompressedFill (BufFilePtr f)
- if (oldcode == -1)
- break;
-
code = getcode (file);
@@ -243,5 +238,5 @@ BufCompressedFill (BufFilePtr f)
file->clear_flg = 1;
- file->free_ent = FIRST - 1;
- if ( (code = getcode (file)) == -1 ) /* O, untimely death! */
- break;
+ file->free_ent = FIRST;
+ oldcode = -1;
+ continue;
}
@@ -252,2 +247,6 @@ BufCompressedFill (BufFilePtr f)
if ( code >= file->free_ent ) {
+ if ( code > file->free_ent || oldcode == -1 ) {
+ /* Bad stream. */
+ return BUFFILEEOF;
+ }
*stackp++ = finchar;
@@ -255,2 +254,8 @@ BufCompressedFill (BufFilePtr f)
}
+ /*
+ * The above condition ensures that code < free_ent.
+ * The construction of tab_prefixof in turn guarantees that
+ * each iteration decreases code and therefore stack usage is
+ * bound by 1 << BITS - 256.
+ */
@@ -261,4 +266,2 @@ BufCompressedFill (BufFilePtr f)
{
- if (stackp - de_stack >= STACK_SIZE - 1)
- return BUFFILEEOF;
*stackp++ = file->tab_suffix[code];
@@ -272,3 +275,3 @@ BufCompressedFill (BufFilePtr f)
*/
- if ( (code=file->free_ent) < file->maxmaxcode ) {
+ if ( (code=file->free_ent) < file->maxmaxcode && oldcode != -1) {
file->tab_prefix[code] = (unsigned short)oldcode;