xref: /OK3568_Linux_fs/yocto/poky/meta/recipes-multimedia/libtiff/tiff/CVE-2022-1354.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1From 281fa3cf0e0e8a44b93478c63d90dbfb64359e88 Mon Sep 17 00:00:00 2001
2From: Even Rouault <even.rouault@spatialys.com>
3Date: Sun, 5 Dec 2021 14:37:46 +0100
4Subject: [PATCH] TIFFReadDirectory: fix OJPEG hack (fixes #319)
5
6to avoid having the size of the strip arrays inconsistent with the
7number of strips returned by TIFFNumberOfStrips(), which may cause
8out-ouf-bounds array read afterwards.
9
10One of the OJPEG hack that alters SamplesPerPixel may influence the
11number of strips. Hence compute tif_dir.td_nstrips only afterwards.
12
13CVE: CVE-2022-1354
14
15Upstream-Status: Backport
16[https://gitlab.com/libtiff/libtiff/-/commit/87f580f39011109b3bb5f6eca13fac543a542798]
17
18Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
19
20---
21 libtiff/tif_dirread.c | 162 ++++++++++++++++++++++--------------------
22 1 file changed, 83 insertions(+), 79 deletions(-)
23
24diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c
25index a31109a..d7cccbe 100644
26--- a/libtiff/tif_dirread.c
27+++ b/libtiff/tif_dirread.c
28@@ -3794,50 +3794,7 @@ TIFFReadDirectory(TIFF* tif)
29 		MissingRequired(tif,"ImageLength");
30 		goto bad;
31 	}
32-	/*
33-	 * Setup appropriate structures (by strip or by tile)
34-	 */
35-	if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) {
36-		tif->tif_dir.td_nstrips = TIFFNumberOfStrips(tif);
37-		tif->tif_dir.td_tilewidth = tif->tif_dir.td_imagewidth;
38-		tif->tif_dir.td_tilelength = tif->tif_dir.td_rowsperstrip;
39-		tif->tif_dir.td_tiledepth = tif->tif_dir.td_imagedepth;
40-		tif->tif_flags &= ~TIFF_ISTILED;
41-	} else {
42-		tif->tif_dir.td_nstrips = TIFFNumberOfTiles(tif);
43-		tif->tif_flags |= TIFF_ISTILED;
44-	}
45-	if (!tif->tif_dir.td_nstrips) {
46-		TIFFErrorExt(tif->tif_clientdata, module,
47-		    "Cannot handle zero number of %s",
48-		    isTiled(tif) ? "tiles" : "strips");
49-		goto bad;
50-	}
51-	tif->tif_dir.td_stripsperimage = tif->tif_dir.td_nstrips;
52-	if (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE)
53-		tif->tif_dir.td_stripsperimage /= tif->tif_dir.td_samplesperpixel;
54-	if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) {
55-#ifdef OJPEG_SUPPORT
56-		if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG) &&
57-		    (isTiled(tif)==0) &&
58-		    (tif->tif_dir.td_nstrips==1)) {
59-			/*
60-			 * XXX: OJPEG hack.
61-			 * If a) compression is OJPEG, b) it's not a tiled TIFF,
62-			 * and c) the number of strips is 1,
63-			 * then we tolerate the absence of stripoffsets tag,
64-			 * because, presumably, all required data is in the
65-			 * JpegInterchangeFormat stream.
66-			 */
67-			TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
68-		} else
69-#endif
70-        {
71-			MissingRequired(tif,
72-				isTiled(tif) ? "TileOffsets" : "StripOffsets");
73-			goto bad;
74-		}
75-	}
76+
77 	/*
78 	 * Second pass: extract other information.
79 	 */
80@@ -4042,41 +3999,6 @@ TIFFReadDirectory(TIFF* tif)
81 			} /* -- if (!dp->tdir_ignore) */
82 		} /* -- for-loop -- */
83
84-        if( tif->tif_mode == O_RDWR &&
85-            tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
86-            tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
87-            tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
88-            tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
89-            tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
90-            tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
91-            tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
92-            tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 )
93-        {
94-            /* Directory typically created with TIFFDeferStrileArrayWriting() */
95-            TIFFSetupStrips(tif);
96-        }
97-        else if( !(tif->tif_flags&TIFF_DEFERSTRILELOAD) )
98-        {
99-            if( tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 )
100-            {
101-                if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripoffset_entry),
102-                                         tif->tif_dir.td_nstrips,
103-                                         &tif->tif_dir.td_stripoffset_p))
104-                {
105-                    goto bad;
106-                }
107-            }
108-            if( tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 )
109-            {
110-                if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripbytecount_entry),
111-                                         tif->tif_dir.td_nstrips,
112-                                         &tif->tif_dir.td_stripbytecount_p))
113-                {
114-                    goto bad;
115-                }
116-            }
117-        }
118-
119 	/*
120 	 * OJPEG hack:
121 	 * - If a) compression is OJPEG, and b) photometric tag is missing,
122@@ -4147,6 +4069,88 @@ TIFFReadDirectory(TIFF* tif)
123 		}
124 	}
125
126+	/*
127+	 * Setup appropriate structures (by strip or by tile)
128+	 * We do that only after the above OJPEG hack which alters SamplesPerPixel
129+	 * and thus influences the number of strips in the separate planarconfig.
130+	 */
131+	if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) {
132+		tif->tif_dir.td_nstrips = TIFFNumberOfStrips(tif);
133+		tif->tif_dir.td_tilewidth = tif->tif_dir.td_imagewidth;
134+		tif->tif_dir.td_tilelength = tif->tif_dir.td_rowsperstrip;
135+		tif->tif_dir.td_tiledepth = tif->tif_dir.td_imagedepth;
136+		tif->tif_flags &= ~TIFF_ISTILED;
137+	} else {
138+		tif->tif_dir.td_nstrips = TIFFNumberOfTiles(tif);
139+		tif->tif_flags |= TIFF_ISTILED;
140+	}
141+	if (!tif->tif_dir.td_nstrips) {
142+		TIFFErrorExt(tif->tif_clientdata, module,
143+		    "Cannot handle zero number of %s",
144+		    isTiled(tif) ? "tiles" : "strips");
145+		goto bad;
146+	}
147+	tif->tif_dir.td_stripsperimage = tif->tif_dir.td_nstrips;
148+	if (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE)
149+		tif->tif_dir.td_stripsperimage /= tif->tif_dir.td_samplesperpixel;
150+	if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) {
151+#ifdef OJPEG_SUPPORT
152+		if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG) &&
153+		    (isTiled(tif)==0) &&
154+		    (tif->tif_dir.td_nstrips==1)) {
155+			/*
156+			 * XXX: OJPEG hack.
157+			 * If a) compression is OJPEG, b) it's not a tiled TIFF,
158+			 * and c) the number of strips is 1,
159+			 * then we tolerate the absence of stripoffsets tag,
160+			 * because, presumably, all required data is in the
161+			 * JpegInterchangeFormat stream.
162+			 */
163+			TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
164+		} else
165+#endif
166+        {
167+			MissingRequired(tif,
168+				isTiled(tif) ? "TileOffsets" : "StripOffsets");
169+			goto bad;
170+		}
171+	}
172+
173+        if( tif->tif_mode == O_RDWR &&
174+            tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
175+            tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
176+            tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
177+            tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
178+            tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
179+            tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
180+            tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
181+            tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 )
182+        {
183+            /* Directory typically created with TIFFDeferStrileArrayWriting() */
184+            TIFFSetupStrips(tif);
185+        }
186+        else if( !(tif->tif_flags&TIFF_DEFERSTRILELOAD) )
187+        {
188+            if( tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 )
189+            {
190+                if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripoffset_entry),
191+                                         tif->tif_dir.td_nstrips,
192+                                         &tif->tif_dir.td_stripoffset_p))
193+                {
194+                    goto bad;
195+                }
196+            }
197+            if( tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 )
198+            {
199+                if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripbytecount_entry),
200+                                         tif->tif_dir.td_nstrips,
201+                                         &tif->tif_dir.td_stripbytecount_p))
202+                {
203+                    goto bad;
204+                }
205+            }
206+        }
207+
208 	/*
209 	 * Make sure all non-color channels are extrasamples.
210 	 * If it's not the case, define them as such.
211