summaryrefslogtreecommitdiffstats
path: root/meta/recipes-multimedia/libtiff/files/CVE-2022-40090.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-multimedia/libtiff/files/CVE-2022-40090.patch')
-rw-r--r--meta/recipes-multimedia/libtiff/files/CVE-2022-40090.patch548
1 files changed, 548 insertions, 0 deletions
diff --git a/meta/recipes-multimedia/libtiff/files/CVE-2022-40090.patch b/meta/recipes-multimedia/libtiff/files/CVE-2022-40090.patch
new file mode 100644
index 0000000000..0a88f59553
--- /dev/null
+++ b/meta/recipes-multimedia/libtiff/files/CVE-2022-40090.patch
@@ -0,0 +1,548 @@
1From d385738335deb0c4bb70449f12e411f2203c0d01 Mon Sep 17 00:00:00 2001
2From: Su_Laus <sulau@freenet.de>
3Date: Fri, 2 Sep 2022 21:20:28 +0200
4Subject: [PATCH 1/4] Improved IFD-Loop Handling (fixes #455)
5
6Basic approach:
7- The order in the entire chain must be checked, and not only whether an offset has already been read once.
8- To do this, pairs of directory number and offset are stored and checked.
9- The offset of a directory number can change.
10- TIFFAdvanceDirectory() must also perform an IFD loop check.
11- TIFFCheckDirOffset() is replaced by _TIFFCheckDirNumberAndOffset().
12
13Rules for the check:
14- If an offset is already in the list, it must have the same IFD number. Otherwise it is an IDF loop.
15- If the offset is not in the list and the IFD number is greater than there are list entries, a new list entry is added.
16- Otherwise, the offset of the IFD number is updated.
17
18Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/tiff/tree/debian/patches/CVE-2022-40090.patch?h=ubuntu/focal-security
19Upstream commit
20https://gitlab.com/libtiff/libtiff/-/commit/c7caec9a4d8f24c17e667480d2c7d0d51c9fae41]
21CVE: CVE-2022-40090
22Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
23---
24 libtiff/tif_close.c | 6 ++-
25 libtiff/tif_dir.c | 91 +++++++++++++++++++++++++----------------
26 libtiff/tif_dir.h | 1 +
27 libtiff/tif_dirread.c | 94 ++++++++++++++++++++++++++++++-------------
28 libtiff/tif_open.c | 3 +-
29 libtiff/tiffiop.h | 3 +-
30 6 files changed, 131 insertions(+), 67 deletions(-)
31
32--- tiff-4.1.0+git191117.orig/libtiff/tif_close.c
33+++ tiff-4.1.0+git191117/libtiff/tif_close.c
34@@ -52,8 +52,10 @@ TIFFCleanup(TIFF* tif)
35 (*tif->tif_cleanup)(tif);
36 TIFFFreeDirectory(tif);
37
38- if (tif->tif_dirlist)
39- _TIFFfree(tif->tif_dirlist);
40+ if (tif->tif_dirlistoff)
41+ _TIFFfree(tif->tif_dirlistoff);
42+ if (tif->tif_dirlistdirn)
43+ _TIFFfree(tif->tif_dirlistdirn);
44
45 /*
46 * Clean up client info links.
47--- tiff-4.1.0+git191117.orig/libtiff/tif_dir.c
48+++ tiff-4.1.0+git191117/libtiff/tif_dir.c
49@@ -1463,12 +1463,22 @@ TIFFDefaultDirectory(TIFF* tif)
50 }
51
52 static int
53-TIFFAdvanceDirectory(TIFF* tif, uint64* nextdir, uint64* off)
54+TIFFAdvanceDirectory(TIFF* tif, uint64* nextdiroff, uint64* off, uint16* nextdirnum)
55 {
56 static const char module[] = "TIFFAdvanceDirectory";
57+
58+ /* Add this directory to the directory list, if not already in. */
59+ if (!_TIFFCheckDirNumberAndOffset(tif, *nextdirnum, *nextdiroff)) {
60+ TIFFErrorExt(tif->tif_clientdata, module, "Starting directory %hu at offset 0x%lx (%lu) might cause an IFD loop",
61+ *nextdirnum, *nextdiroff, *nextdiroff);
62+ *nextdiroff = 0;
63+ *nextdirnum = 0;
64+ return(0);
65+ }
66+
67 if (isMapped(tif))
68 {
69- uint64 poff=*nextdir;
70+ uint64 poff=*nextdiroff;
71 if (!(tif->tif_flags&TIFF_BIGTIFF))
72 {
73 tmsize_t poffa,poffb,poffc,poffd;
74@@ -1479,7 +1489,7 @@ TIFFAdvanceDirectory(TIFF* tif, uint64*
75 if (((uint64)poffa!=poff)||(poffb<poffa)||(poffb<(tmsize_t)sizeof(uint16))||(poffb>tif->tif_size))
76 {
77 TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory count");
78- *nextdir=0;
79+ *nextdiroff=0;
80 return(0);
81 }
82 _TIFFmemcpy(&dircount,tif->tif_base+poffa,sizeof(uint16));
83@@ -1497,7 +1507,7 @@ TIFFAdvanceDirectory(TIFF* tif, uint64*
84 _TIFFmemcpy(&nextdir32,tif->tif_base+poffc,sizeof(uint32));
85 if (tif->tif_flags&TIFF_SWAB)
86 TIFFSwabLong(&nextdir32);
87- *nextdir=nextdir32;
88+ *nextdiroff=nextdir32;
89 }
90 else
91 {
92@@ -1529,11 +1539,10 @@ TIFFAdvanceDirectory(TIFF* tif, uint64*
93 }
94 if (off!=NULL)
95 *off=(uint64)poffc;
96- _TIFFmemcpy(nextdir,tif->tif_base+poffc,sizeof(uint64));
97+ _TIFFmemcpy(nextdiroff,tif->tif_base+poffc,sizeof(uint64));
98 if (tif->tif_flags&TIFF_SWAB)
99- TIFFSwabLong8(nextdir);
100+ TIFFSwabLong8(nextdiroff);
101 }
102- return(1);
103 }
104 else
105 {
106@@ -1541,7 +1550,7 @@ TIFFAdvanceDirectory(TIFF* tif, uint64*
107 {
108 uint16 dircount;
109 uint32 nextdir32;
110- if (!SeekOK(tif, *nextdir) ||
111+ if (!SeekOK(tif, *nextdiroff) ||
112 !ReadOK(tif, &dircount, sizeof (uint16))) {
113 TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count",
114 tif->tif_name);
115@@ -1562,13 +1571,13 @@ TIFFAdvanceDirectory(TIFF* tif, uint64*
116 }
117 if (tif->tif_flags & TIFF_SWAB)
118 TIFFSwabLong(&nextdir32);
119- *nextdir=nextdir32;
120+ *nextdiroff=nextdir32;
121 }
122 else
123 {
124 uint64 dircount64;
125 uint16 dircount16;
126- if (!SeekOK(tif, *nextdir) ||
127+ if (!SeekOK(tif, *nextdiroff) ||
128 !ReadOK(tif, &dircount64, sizeof (uint64))) {
129 TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count",
130 tif->tif_name);
131@@ -1588,17 +1597,27 @@ TIFFAdvanceDirectory(TIFF* tif, uint64*
132 else
133 (void) TIFFSeekFile(tif,
134 dircount16*20, SEEK_CUR);
135- if (!ReadOK(tif, nextdir, sizeof (uint64))) {
136+ if (!ReadOK(tif, nextdiroff, sizeof (uint64))) {
137 TIFFErrorExt(tif->tif_clientdata, module,
138 "%s: Error fetching directory link",
139 tif->tif_name);
140 return (0);
141 }
142 if (tif->tif_flags & TIFF_SWAB)
143- TIFFSwabLong8(nextdir);
144+ TIFFSwabLong8(nextdiroff);
145 }
146- return (1);
147 }
148+ if (*nextdiroff != 0) {
149+ (*nextdirnum)++;
150+ /* Check next directory for IFD looping and if so, set it as last directory. */
151+ if (!_TIFFCheckDirNumberAndOffset(tif, *nextdirnum, *nextdiroff)) {
152+ TIFFWarningExt(tif->tif_clientdata, module, "the next directory %hu at offset 0x%lx (%lu) might be an IFD loop. Treating directory %hu as last directory",
153+ *nextdirnum, *nextdiroff, *nextdiroff, *nextdirnum-1);
154+ *nextdiroff = 0;
155+ (*nextdirnum)--;
156+ }
157+ }
158+ return (1);
159 }
160
161 /*
162@@ -1608,14 +1627,16 @@ uint16
163 TIFFNumberOfDirectories(TIFF* tif)
164 {
165 static const char module[] = "TIFFNumberOfDirectories";
166- uint64 nextdir;
167+ uint64 nextdiroff;
168+ uint16 nextdirnum;
169 uint16 n;
170 if (!(tif->tif_flags&TIFF_BIGTIFF))
171- nextdir = tif->tif_header.classic.tiff_diroff;
172+ nextdiroff = tif->tif_header.classic.tiff_diroff;
173 else
174- nextdir = tif->tif_header.big.tiff_diroff;
175+ nextdiroff = tif->tif_header.big.tiff_diroff;
176+ nextdirnum = 0;
177 n = 0;
178- while (nextdir != 0 && TIFFAdvanceDirectory(tif, &nextdir, NULL))
179+ while (nextdiroff != 0 && TIFFAdvanceDirectory(tif, &nextdiroff, NULL, &nextdirnum))
180 {
181 if (n != 65535) {
182 ++n;
183@@ -1638,28 +1659,30 @@ TIFFNumberOfDirectories(TIFF* tif)
184 int
185 TIFFSetDirectory(TIFF* tif, uint16 dirn)
186 {
187- uint64 nextdir;
188+ uint64 nextdiroff;
189+ uint16 nextdirnum;
190 uint16 n;
191
192 if (!(tif->tif_flags&TIFF_BIGTIFF))
193- nextdir = tif->tif_header.classic.tiff_diroff;
194+ nextdiroff = tif->tif_header.classic.tiff_diroff;
195 else
196- nextdir = tif->tif_header.big.tiff_diroff;
197- for (n = dirn; n > 0 && nextdir != 0; n--)
198- if (!TIFFAdvanceDirectory(tif, &nextdir, NULL))
199+ nextdiroff = tif->tif_header.big.tiff_diroff;
200+ nextdirnum = 0;
201+ for (n = dirn; n > 0 && nextdiroff != 0; n--)
202+ if (!TIFFAdvanceDirectory(tif, &nextdiroff, NULL, &nextdirnum))
203 return (0);
204- tif->tif_nextdiroff = nextdir;
205+ /* If the n-th directory could not be reached (does not exist),
206+ * return here without touching anything further. */
207+ if (nextdiroff == 0 || n > 0)
208+ return (0);
209+
210+ tif->tif_nextdiroff = nextdiroff;
211 /*
212 * Set curdir to the actual directory index. The
213 * -1 is because TIFFReadDirectory will increment
214 * tif_curdir after successfully reading the directory.
215 */
216 tif->tif_curdir = (dirn - n) - 1;
217- /*
218- * Reset tif_dirnumber counter and start new list of seen directories.
219- * We need this to prevent IFD loops.
220- */
221- tif->tif_dirnumber = 0;
222 return (TIFFReadDirectory(tif));
223 }
224
225@@ -1672,13 +1695,42 @@ TIFFSetDirectory(TIFF* tif, uint16 dirn)
226 int
227 TIFFSetSubDirectory(TIFF* tif, uint64 diroff)
228 {
229- tif->tif_nextdiroff = diroff;
230- /*
231- * Reset tif_dirnumber counter and start new list of seen directories.
232- * We need this to prevent IFD loops.
233+ /* Match nextdiroff and curdir for consistent IFD-loop checking.
234+ * Only with TIFFSetSubDirectory() the IFD list can be corrupted with invalid offsets
235+ * within the main IFD tree.
236+ * In the case of several subIFDs of a main image,
237+ * there are two possibilities that are not even mutually exclusive.
238+ * a.) The subIFD tag contains an array with all offsets of the subIFDs.
239+ * b.) The SubIFDs are concatenated with their NextIFD parameters.
240+ * (refer to https://www.awaresystems.be/imaging/tiff/specification/TIFFPM6.pdf.)
241 */
242- tif->tif_dirnumber = 0;
243- return (TIFFReadDirectory(tif));
244+ int retval;
245+ uint16 curdir = 0;
246+ int8 probablySubIFD = 0;
247+ if (diroff == 0) {
248+ /* Special case to invalidate the tif_lastdiroff member. */
249+ tif->tif_curdir = 65535;
250+ } else {
251+ if (!_TIFFGetDirNumberFromOffset(tif, diroff, &curdir)) {
252+ /* Non-existing offsets might point to a SubIFD or invalid IFD.*/
253+ probablySubIFD = 1;
254+ }
255+ /* -1 because TIFFReadDirectory() will increment tif_curdir. */
256+ tif->tif_curdir = curdir - 1;
257+ }
258+
259+ tif->tif_nextdiroff = diroff;
260+ retval = TIFFReadDirectory(tif);
261+ /* If failed, curdir was not incremented in TIFFReadDirectory(), so set it back. */
262+ if (!retval )tif->tif_curdir++;
263+ if (retval && probablySubIFD) {
264+ /* Reset IFD list to start new one for SubIFD chain and also start SubIFD chain with tif_curdir=0. */
265+ tif->tif_dirnumber = 0;
266+ tif->tif_curdir = 0; /* first directory of new chain */
267+ /* add this offset to new IFD list */
268+ _TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff);
269+ }
270+ return (retval);
271 }
272
273 /*
274@@ -1702,12 +1754,15 @@ TIFFLastDirectory(TIFF* tif)
275
276 /*
277 * Unlink the specified directory from the directory chain.
278+ * Note: First directory starts with number dirn=1.
279+ * This is different to TIFFSetDirectory() where the first directory starts with zero.
280 */
281 int
282 TIFFUnlinkDirectory(TIFF* tif, uint16 dirn)
283 {
284 static const char module[] = "TIFFUnlinkDirectory";
285 uint64 nextdir;
286+ uint16 nextdirnum;
287 uint64 off;
288 uint16 n;
289
290@@ -1731,19 +1786,21 @@ TIFFUnlinkDirectory(TIFF* tif, uint16 di
291 nextdir = tif->tif_header.big.tiff_diroff;
292 off = 8;
293 }
294+ nextdirnum = 0; /* First directory is dirn=0 */
295+
296 for (n = dirn-1; n > 0; n--) {
297 if (nextdir == 0) {
298 TIFFErrorExt(tif->tif_clientdata, module, "Directory %d does not exist", dirn);
299 return (0);
300 }
301- if (!TIFFAdvanceDirectory(tif, &nextdir, &off))
302+ if (!TIFFAdvanceDirectory(tif, &nextdir, &off, &nextdirnum))
303 return (0);
304 }
305 /*
306 * Advance to the directory to be unlinked and fetch
307 * the offset of the directory that follows.
308 */
309- if (!TIFFAdvanceDirectory(tif, &nextdir, NULL))
310+ if (!TIFFAdvanceDirectory(tif, &nextdir, NULL, &nextdirnum))
311 return (0);
312 /*
313 * Go back and patch the link field of the preceding
314--- tiff-4.1.0+git191117.orig/libtiff/tif_dir.h
315+++ tiff-4.1.0+git191117/libtiff/tif_dir.h
316@@ -300,6 +300,8 @@ extern int _TIFFMergeFields(TIFF*, const
317 extern const TIFFField* _TIFFFindOrRegisterField(TIFF *, uint32, TIFFDataType);
318 extern TIFFField* _TIFFCreateAnonField(TIFF *, uint32, TIFFDataType);
319 extern int _TIFFCheckFieldIsValidForCodec(TIFF *tif, ttag_t tag);
320+extern int _TIFFCheckDirNumberAndOffset(TIFF *tif, uint16 dirn, uint64 diroff);
321+extern int _TIFFGetDirNumberFromOffset(TIFF *tif, uint64 diroff, uint16 *dirn);
322
323 #if defined(__cplusplus)
324 }
325--- tiff-4.1.0+git191117.orig/libtiff/tif_dirread.c
326+++ tiff-4.1.0+git191117/libtiff/tif_dirread.c
327@@ -158,7 +158,6 @@ static void TIFFReadDirectoryFindFieldIn
328
329 static int EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount);
330 static void MissingRequired(TIFF*, const char*);
331-static int TIFFCheckDirOffset(TIFF* tif, uint64 diroff);
332 static int CheckDirCount(TIFF*, TIFFDirEntry*, uint32);
333 static uint16 TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir, uint64* nextdiroff);
334 static int TIFFFetchNormalTag(TIFF*, TIFFDirEntry*, int recover);
335@@ -3584,12 +3583,19 @@ TIFFReadDirectory(TIFF* tif)
336 int bitspersample_read = FALSE;
337 int color_channels;
338
339- tif->tif_diroff=tif->tif_nextdiroff;
340- if (!TIFFCheckDirOffset(tif,tif->tif_nextdiroff))
341- return 0; /* last offset or bad offset (IFD looping) */
342- (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */
343- tif->tif_curdir++;
344- nextdiroff = tif->tif_nextdiroff;
345+ if (tif->tif_nextdiroff == 0) {
346+ /* In this special case, tif_diroff needs also to be set to 0. */
347+ tif->tif_diroff = tif->tif_nextdiroff;
348+ return 0; /* last offset, thus no checking necessary */
349+ }
350+
351+ nextdiroff = tif->tif_nextdiroff;
352+ /* tif_curdir++ and tif_nextdiroff should only be updated after SUCCESSFUL reading of the directory. Otherwise, invalid IFD offsets could corrupt the IFD list. */
353+ if (!_TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir + 1, nextdiroff)) {
354+ TIFFWarningExt(tif->tif_clientdata, module,
355+ "Didn't read next directory due to IFD looping at offset 0x%lx (%lu) to offset 0x%lx (%lu)", tif->tif_diroff, tif->tif_diroff, nextdiroff, nextdiroff);
356+ return 0; /* bad offset (IFD looping) */
357+ }
358 dircount=TIFFFetchDirectory(tif,nextdiroff,&dir,&tif->tif_nextdiroff);
359 if (!dircount)
360 {
361@@ -3597,6 +3603,11 @@ TIFFReadDirectory(TIFF* tif)
362 "Failed to read directory at offset " TIFF_UINT64_FORMAT,nextdiroff);
363 return 0;
364 }
365+ /* Set global values after a valid directory has been fetched.
366+ * tif_diroff is already set to nextdiroff in TIFFFetchDirectory() in the beginning. */
367+ tif->tif_curdir++;
368+ (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */
369+
370 TIFFReadDirectoryCheckOrder(tif,dir,dircount);
371
372 /*
373@@ -4628,13 +4639,17 @@ MissingRequired(TIFF* tif, const char* t
374 }
375
376 /*
377- * Check the directory offset against the list of already seen directory
378- * offsets. This is a trick to prevent IFD looping. The one can create TIFF
379- * file with looped directory pointers. We will maintain a list of already
380- * seen directories and check every IFD offset against that list.
381+ * Check the directory number and offset against the list of already seen
382+ * directory numbers and offsets. This is a trick to prevent IFD looping.
383+ * The one can create TIFF file with looped directory pointers. We will
384+ * maintain a list of already seen directories and check every IFD offset
385+ * and its IFD number against that list. However, the offset of an IFD number
386+ * can change - e.g. when writing updates to file.
387+ * Returns 1 if all is ok; 0 if last directory or IFD loop is encountered,
388+ * or an error has occured.
389 */
390-static int
391-TIFFCheckDirOffset(TIFF* tif, uint64 diroff)
392+int
393+_TIFFCheckDirNumberAndOffset(TIFF* tif, uint16 dirn, uint64 diroff)
394 {
395 uint16 n;
396
397@@ -4646,35 +4661,64 @@ TIFFCheckDirOffset(TIFF* tif, uint64 dir
398 return 0;
399 }
400
401- for (n = 0; n < tif->tif_dirnumber && tif->tif_dirlist; n++) {
402- if (tif->tif_dirlist[n] == diroff)
403- return 0;
404+ /* Check if offset is already in the list:
405+ * - yes: check, if offset is at the same IFD number - if not, it is an IFD loop
406+ * - no: add to list or update offset at that IFD number
407+ */
408+ for (n = 0; n < tif->tif_dirnumber && tif->tif_dirlistdirn && tif->tif_dirlistoff; n++) {
409+ if (tif->tif_dirlistoff[n] == diroff) {
410+ if (tif->tif_dirlistdirn[n] == dirn) {
411+ return 1;
412+ } else {
413+ TIFFWarningExt(tif->tif_clientdata, "_TIFFCheckDirNumberAndOffset",
414+ "TIFF directory %hu has IFD looping to directory %hu at offset 0x%lx (%lu)",
415+ dirn-1, tif->tif_dirlistdirn[n], diroff, diroff);
416+ return 0;
417+ }
418+ }
419+ }
420+ /* Check if offset of an IFD has been changed and update offset of that IFD number. */
421+ if (dirn < tif->tif_dirnumber && tif->tif_dirlistdirn && tif->tif_dirlistoff) {
422+ /* tif_dirlistdirn can have IFD numbers dirn in random order */
423+ for (n = 0; n < tif->tif_dirnumber; n++) {
424+ if (tif->tif_dirlistdirn[n] == dirn) {
425+ tif->tif_dirlistoff[n] = diroff;
426+ return 1;
427+ }
428+ }
429 }
430
431+ /* Add IFD offset and dirn to IFD directory list */
432 tif->tif_dirnumber++;
433
434- if (tif->tif_dirlist == NULL || tif->tif_dirnumber > tif->tif_dirlistsize) {
435- uint64* new_dirlist;
436-
437+ if (tif->tif_dirlistoff == NULL || tif->tif_dirlistdirn == NULL || tif->tif_dirnumber > tif->tif_dirlistsize) {
438+ uint64 *new_dirlist;
439 /*
440 * XXX: Reduce memory allocation granularity of the dirlist
441 * array.
442 */
443- new_dirlist = (uint64*)_TIFFCheckRealloc(tif, tif->tif_dirlist,
444- tif->tif_dirnumber, 2 * sizeof(uint64), "for IFD list");
445+ if (tif->tif_dirnumber >= 32768)
446+ tif->tif_dirlistsize = 65535;
447+ else
448+ tif->tif_dirlistsize = 2 * tif->tif_dirnumber;
449+
450+ new_dirlist = (uint64 *)_TIFFCheckRealloc(tif, tif->tif_dirlistoff,
451+ tif->tif_dirlistsize, sizeof(uint64), "for IFD offset list");
452 if (!new_dirlist)
453 return 0;
454- if( tif->tif_dirnumber >= 32768 )
455- tif->tif_dirlistsize = 65535;
456- else
457- tif->tif_dirlistsize = 2 * tif->tif_dirnumber;
458- tif->tif_dirlist = new_dirlist;
459+ tif->tif_dirlistoff = new_dirlist;
460+ new_dirlist = (uint64 *)_TIFFCheckRealloc(tif, tif->tif_dirlistdirn,
461+ tif->tif_dirlistsize, sizeof(uint16), "for IFD dirnumber list");
462+ if (!new_dirlist)
463+ return 0;
464+ tif->tif_dirlistdirn = (uint16 *)new_dirlist;
465 }
466
467- tif->tif_dirlist[tif->tif_dirnumber - 1] = diroff;
468+ tif->tif_dirlistoff[tif->tif_dirnumber - 1] = diroff;
469+ tif->tif_dirlistdirn[tif->tif_dirnumber - 1] = dirn;
470
471 return 1;
472-}
473+} /* --- _TIFFCheckDirNumberAndOffset() ---*/
474
475 /*
476 * Check the count field of a directory entry against a known value. The
477@@ -4703,6 +4747,47 @@ CheckDirCount(TIFF* tif, TIFFDirEntry* d
478 }
479
480 /*
481+ * Retrieve the matching IFD directory number of a given IFD offset
482+ * from the list of directories already seen.
483+ * Returns 1 if the offset was in the list and the directory number
484+ * can be returned.
485+ * Otherwise returns 0 or if an error occured.
486+ */
487+int
488+_TIFFGetDirNumberFromOffset(TIFF *tif, uint64 diroff, uint16* dirn)
489+{
490+ uint16 n;
491+
492+ if (diroff == 0) /* no more directories */
493+ return 0;
494+ if (tif->tif_dirnumber == 65535) {
495+ TIFFErrorExt(tif->tif_clientdata, "_TIFFGetDirNumberFromOffset",
496+ "Cannot handle more than 65535 TIFF directories");
497+ return 0;
498+ }
499+
500+ /* Check if offset is already in the list and return matching directory number.
501+ * Otherwise update IFD list using TIFFNumberOfDirectories()
502+ * and search again in IFD list.
503+ */
504+ for (n = 0; n < tif->tif_dirnumber && tif->tif_dirlistoff && tif->tif_dirlistdirn; n++) {
505+ if (tif->tif_dirlistoff[n] == diroff) {
506+ *dirn = tif->tif_dirlistdirn[n];
507+ return 1;
508+ }
509+ }
510+ TIFFNumberOfDirectories(tif);
511+ for (n = 0; n < tif->tif_dirnumber && tif->tif_dirlistoff && tif->tif_dirlistdirn; n++) {
512+ if (tif->tif_dirlistoff[n] == diroff) {
513+ *dirn = tif->tif_dirlistdirn[n];
514+ return 1;
515+ }
516+ }
517+ return 0;
518+} /*--- _TIFFGetDirNumberFromOffset() ---*/
519+
520+
521+/*
522 * Read IFD structure from the specified offset. If the pointer to
523 * nextdiroff variable has been specified, read it too. Function returns a
524 * number of fields in the directory or 0 if failed.
525--- tiff-4.1.0+git191117.orig/libtiff/tif_open.c
526+++ tiff-4.1.0+git191117/libtiff/tif_open.c
527@@ -353,7 +353,8 @@ TIFFClientOpen(
528 if (!TIFFDefaultDirectory(tif))
529 goto bad;
530 tif->tif_diroff = 0;
531- tif->tif_dirlist = NULL;
532+ tif->tif_dirlistoff = NULL;
533+ tif->tif_dirlistdirn = NULL;
534 tif->tif_dirlistsize = 0;
535 tif->tif_dirnumber = 0;
536 return (tif);
537--- tiff-4.1.0+git191117.orig/libtiff/tiffiop.h
538+++ tiff-4.1.0+git191117/libtiff/tiffiop.h
539@@ -145,7 +145,8 @@ struct tiff {
540 #define TIFF_CHOPPEDUPARRAYS 0x4000000U /* set when allocChoppedUpStripArrays() has modified strip array */
541 uint64 tif_diroff; /* file offset of current directory */
542 uint64 tif_nextdiroff; /* file offset of following directory */
543- uint64* tif_dirlist; /* list of offsets to already seen directories to prevent IFD looping */
544+ uint64* tif_dirlistoff; /* list of offsets to already seen directories to prevent IFD looping */
545+ uint16* tif_dirlistdirn; /* list of directory numbers to already seen directories to prevent IFD looping */
546 uint16 tif_dirlistsize; /* number of entries in offset list */
547 uint16 tif_dirnumber; /* number of already seen directories */
548 TIFFDirectory tif_dir; /* internal rep of current directory */