Ascii85Encode() assembled the 32-bit tuple with

    word = (uint32_t)((((raw[0] << 8) + raw[1]) << 16) +
                      (raw[2] << 8) + raw[3]);

The sub-expression ((raw[0] << 8) + raw[1]) has type int (the unsigned
char operands are promoted to int). When raw[0] >= 128 its value is
>= 0x8000, so the following "<< 16" shifts a set bit into and past the
sign bit and the result is not representable in int, which is undefined
behaviour.

The bytes passed to Ascii85Encode() are attacker controlled: among them
are the ColorMap values emitted by PS_Lvl2colorspace() via
Ascii85Put() -> Ascii85Encode() when a palette TIFF is converted with
"tiff2ps -a -2". UBSan reports, for a palette image whose colormap
contains a byte >= 128:

    tools/tiff2ps.c:3474:46: runtime error: left shift of 36922 by 16
    places cannot be represented in type 'int'
        #0 Ascii85Encode      tiff2ps.c:3474
        #1 Ascii85Put         tiff2ps.c:3512
        #2 PS_Lvl2colorspace  tiff2ps.c:2173

Compute the word using unsigned (uint32_t) shifts, matching the encoder
already used in Ascii85EncodeBlock(). The numeric result is unchanged on
two's-complement targets, so the generated PostScript is byte-identical.
---
diff --git a/tools/tiff2ps.c b/tools/tiff2ps.c
index be2f5a0..514f901 100644
--- a/tools/tiff2ps.c
+++ b/tools/tiff2ps.c
@@ -3470,8 +3470,8 @@ static char *Ascii85Encode(unsigned char *raw)
     static char encoded[6];
     uint32_t word;
 
-    word =
-        (uint32_t)((((raw[0] << 8) + raw[1]) << 16) + (raw[2] << 8) + raw[3]);
+    word = ((uint32_t)raw[0] << 24) | ((uint32_t)raw[1] << 16) |
+           ((uint32_t)raw[2] << 8) | (uint32_t)raw[3];
     if (word != 0L)
     {
         uint32_t q;
-- 
2.50.1 (Apple Git-155)
_______________________________________________
Tiff mailing list
[email protected]
https://lists.osgeo.org/mailman/listinfo/tiff

Reply via email to