]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core-contrib.git/blob
17b37be041179d6825a05067fbdd0b9a347ca4ac
[thirdparty/openembedded/openembedded-core-contrib.git] /
1 From f00484b9519df933723deb38fff943dc291a793d Mon Sep 17 00:00:00 2001
2 From: Su_Laus <sulau@freenet.de>
3 Date: Tue, 30 Aug 2022 16:56:48 +0200
4 Subject: [PATCH] Revised handling of TIFFTAG_INKNAMES and related
5 TIFFTAG_NUMBEROFINKS value
6
7 In order to solve the buffer overflow issues related to TIFFTAG_INKNAMES and related TIFFTAG_NUMBEROFINKS value, a revised handling of those tags within LibTiff is proposed:
8
9 Behaviour for writing:
10 `NumberOfInks` MUST fit to the number of inks in the `InkNames` string.
11 `NumberOfInks` is automatically set when `InkNames` is set.
12 If `NumberOfInks` is different to the number of inks within `InkNames` string, that will be corrected and a warning is issued.
13 If `NumberOfInks` is not equal to samplesperpixel only a warning will be issued.
14
15 Behaviour for reading:
16 When reading `InkNames` from a TIFF file, the `NumberOfInks` will be set automatically to the number of inks in `InkNames` string.
17 If `NumberOfInks` is different to the number of inks within `InkNames` string, that will be corrected and a warning is issued.
18 If `NumberOfInks` is not equal to samplesperpixel only a warning will be issued.
19
20 This allows the safe use of the NumberOfInks value to read out the InkNames without buffer overflow
21
22 This MR will close the following issues: #149, #150, #152, #168 (to be checked), #250, #269, #398 and #456.
23
24 It also fixes the old bug at http://bugzilla.maptools.org/show_bug.cgi?id=2599, for which the limitation of `NumberOfInks = SPP` was introduced, which is in my opinion not necessary and does not solve the general issue.
25
26 CVE: CVE-2022-3599 CVE-2022-4645
27 Upstream-Status: Backport [https://gitlab.com/libtiff/libtiff/-/commit/e813112545942107551433d61afd16ac094ff246.patch]
28 Signed-off-by: Ross Burton <ross.burton@arm.com>
29 Signed-off-by: Pawan Badganchi <Pawan.Badganchi@kpit.com>
30 ---
31 libtiff/tif_dir.c | 119 ++++++++++++++++++++++++-----------------
32 libtiff/tif_dir.h | 2 +
33 libtiff/tif_dirinfo.c | 2 +-
34 libtiff/tif_dirwrite.c | 5 ++
35 libtiff/tif_print.c | 4 ++
36 5 files changed, 82 insertions(+), 50 deletions(-)
37
38 diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c
39 index 793e8a79..816f7756 100644
40 --- a/libtiff/tif_dir.c
41 +++ b/libtiff/tif_dir.c
42 @@ -136,32 +136,30 @@ setExtraSamples(TIFF* tif, va_list ap, uint32_t* v)
43 }
44
45 /*
46 - * Confirm we have "samplesperpixel" ink names separated by \0. Returns
47 + * Count ink names separated by \0. Returns
48 * zero if the ink names are not as expected.
49 */
50 -static uint32_t
51 -checkInkNamesString(TIFF* tif, uint32_t slen, const char* s)
52 +static uint16_t
53 +countInkNamesString(TIFF *tif, uint32_t slen, const char *s)
54 {
55 - TIFFDirectory* td = &tif->tif_dir;
56 - uint16_t i = td->td_samplesperpixel;
57 + uint16_t i = 0;
58 + const char *ep = s + slen;
59 + const char *cp = s;
60
61 if (slen > 0) {
62 - const char* ep = s+slen;
63 - const char* cp = s;
64 - for (; i > 0; i--) {
65 + do {
66 for (; cp < ep && *cp != '\0'; cp++) {}
67 if (cp >= ep)
68 goto bad;
69 cp++; /* skip \0 */
70 - }
71 - return ((uint32_t)(cp - s));
72 + i++;
73 + } while (cp < ep);
74 + return (i);
75 }
76 bad:
77 TIFFErrorExt(tif->tif_clientdata, "TIFFSetField",
78 - "%s: Invalid InkNames value; expecting %"PRIu16" names, found %"PRIu16,
79 - tif->tif_name,
80 - td->td_samplesperpixel,
81 - (uint16_t)(td->td_samplesperpixel-i));
82 + "%s: Invalid InkNames value; no NUL at given buffer end location %"PRIu32", after %"PRIu16" ink",
83 + tif->tif_name, slen, i);
84 return (0);
85 }
86
87 @@ -478,13 +476,61 @@ _TIFFVSetField(TIFF* tif, uint32_t tag, va_list ap)
88 _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6);
89 break;
90 case TIFFTAG_INKNAMES:
91 - v = (uint16_t) va_arg(ap, uint16_vap);
92 - s = va_arg(ap, char*);
93 - v = checkInkNamesString(tif, v, s);
94 - status = v > 0;
95 - if( v > 0 ) {
96 - _TIFFsetNString(&td->td_inknames, s, v);
97 - td->td_inknameslen = v;
98 + {
99 + v = (uint16_t) va_arg(ap, uint16_vap);
100 + s = va_arg(ap, char*);
101 + uint16_t ninksinstring;
102 + ninksinstring = countInkNamesString(tif, v, s);
103 + status = ninksinstring > 0;
104 + if(ninksinstring > 0 ) {
105 + _TIFFsetNString(&td->td_inknames, s, v);
106 + td->td_inknameslen = v;
107 + /* Set NumberOfInks to the value ninksinstring */
108 + if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS))
109 + {
110 + if (td->td_numberofinks != ninksinstring) {
111 + TIFFErrorExt(tif->tif_clientdata, module,
112 + "Warning %s; Tag %s:\n Value %"PRIu16" of NumberOfInks is different from the number of inks %"PRIu16".\n -> NumberOfInks value adapted to %"PRIu16"",
113 + tif->tif_name, fip->field_name, td->td_numberofinks, ninksinstring, ninksinstring);
114 + td->td_numberofinks = ninksinstring;
115 + }
116 + } else {
117 + td->td_numberofinks = ninksinstring;
118 + TIFFSetFieldBit(tif, FIELD_NUMBEROFINKS);
119 + }
120 + if (TIFFFieldSet(tif, FIELD_SAMPLESPERPIXEL))
121 + {
122 + if (td->td_numberofinks != td->td_samplesperpixel) {
123 + TIFFErrorExt(tif->tif_clientdata, module,
124 + "Warning %s; Tag %s:\n Value %"PRIu16" of NumberOfInks is different from the SamplesPerPixel value %"PRIu16"",
125 + tif->tif_name, fip->field_name, td->td_numberofinks, td->td_samplesperpixel);
126 + }
127 + }
128 + }
129 + }
130 + break;
131 + case TIFFTAG_NUMBEROFINKS:
132 + v = (uint16_t)va_arg(ap, uint16_vap);
133 + /* If InkNames already set also NumberOfInks is set accordingly and should be equal */
134 + if (TIFFFieldSet(tif, FIELD_INKNAMES))
135 + {
136 + if (v != td->td_numberofinks) {
137 + TIFFErrorExt(tif->tif_clientdata, module,
138 + "Error %s; Tag %s:\n It is not possible to set the value %"PRIu32" for NumberOfInks\n which is different from the number of inks in the InkNames tag (%"PRIu16")",
139 + tif->tif_name, fip->field_name, v, td->td_numberofinks);
140 + /* Do not set / overwrite number of inks already set by InkNames case accordingly. */
141 + status = 0;
142 + }
143 + } else {
144 + td->td_numberofinks = (uint16_t)v;
145 + if (TIFFFieldSet(tif, FIELD_SAMPLESPERPIXEL))
146 + {
147 + if (td->td_numberofinks != td->td_samplesperpixel) {
148 + TIFFErrorExt(tif->tif_clientdata, module,
149 + "Warning %s; Tag %s:\n Value %"PRIu32" of NumberOfInks is different from the SamplesPerPixel value %"PRIu16"",
150 + tif->tif_name, fip->field_name, v, td->td_samplesperpixel);
151 + }
152 + }
153 }
154 break;
155 case TIFFTAG_PERSAMPLE:
156 @@ -986,34 +1032,6 @@ _TIFFVGetField(TIFF* tif, uint32_t tag, va_list ap)
157 if (fip->field_bit == FIELD_CUSTOM) {
158 standard_tag = 0;
159 }
160 -
161 - if( standard_tag == TIFFTAG_NUMBEROFINKS )
162 - {
163 - int i;
164 - for (i = 0; i < td->td_customValueCount; i++) {
165 - uint16_t val;
166 - TIFFTagValue *tv = td->td_customValues + i;
167 - if (tv->info->field_tag != standard_tag)
168 - continue;
169 - if( tv->value == NULL )
170 - return 0;
171 - val = *(uint16_t *)tv->value;
172 - /* Truncate to SamplesPerPixel, since the */
173 - /* setting code for INKNAMES assume that there are SamplesPerPixel */
174 - /* inknames. */
175 - /* Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2599 */
176 - if( val > td->td_samplesperpixel )
177 - {
178 - TIFFWarningExt(tif->tif_clientdata,"_TIFFVGetField",
179 - "Truncating NumberOfInks from %u to %"PRIu16,
180 - val, td->td_samplesperpixel);
181 - val = td->td_samplesperpixel;
182 - }
183 - *va_arg(ap, uint16_t*) = val;
184 - return 1;
185 - }
186 - return 0;
187 - }
188
189 switch (standard_tag) {
190 case TIFFTAG_SUBFILETYPE:
191 @@ -1195,6 +1213,9 @@ _TIFFVGetField(TIFF* tif, uint32_t tag, va_list ap)
192 case TIFFTAG_INKNAMES:
193 *va_arg(ap, const char**) = td->td_inknames;
194 break;
195 + case TIFFTAG_NUMBEROFINKS:
196 + *va_arg(ap, uint16_t *) = td->td_numberofinks;
197 + break;
198 default:
199 {
200 int i;
201 diff --git a/libtiff/tif_dir.h b/libtiff/tif_dir.h
202 index 09065648..0c251c9e 100644
203 --- a/libtiff/tif_dir.h
204 +++ b/libtiff/tif_dir.h
205 @@ -117,6 +117,7 @@ typedef struct {
206 /* CMYK parameters */
207 int td_inknameslen;
208 char* td_inknames;
209 + uint16_t td_numberofinks; /* number of inks in InkNames string */
210
211 int td_customValueCount;
212 TIFFTagValue *td_customValues;
213 @@ -174,6 +175,7 @@ typedef struct {
214 #define FIELD_TRANSFERFUNCTION 44
215 #define FIELD_INKNAMES 46
216 #define FIELD_SUBIFD 49
217 +#define FIELD_NUMBEROFINKS 50
218 /* FIELD_CUSTOM (see tiffio.h) 65 */
219 /* end of support for well-known tags; codec-private tags follow */
220 #define FIELD_CODEC 66 /* base of codec-private tags */
221 diff --git a/libtiff/tif_dirinfo.c b/libtiff/tif_dirinfo.c
222 index 3371cb5c..3b4bcd33 100644
223 --- a/libtiff/tif_dirinfo.c
224 +++ b/libtiff/tif_dirinfo.c
225 @@ -114,7 +114,7 @@ tiffFields[] = {
226 { TIFFTAG_SUBIFD, -1, -1, TIFF_IFD8, 0, TIFF_SETGET_C16_IFD8, TIFF_SETGET_UNDEFINED, FIELD_SUBIFD, 1, 1, "SubIFD", (TIFFFieldArray*) &tiffFieldArray },
227 { TIFFTAG_INKSET, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "InkSet", NULL },
228 { TIFFTAG_INKNAMES, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_C16_ASCII, TIFF_SETGET_UNDEFINED, FIELD_INKNAMES, 1, 1, "InkNames", NULL },
229 - { TIFFTAG_NUMBEROFINKS, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "NumberOfInks", NULL },
230 + { TIFFTAG_NUMBEROFINKS, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_NUMBEROFINKS, 1, 0, "NumberOfInks", NULL },
231 { TIFFTAG_DOTRANGE, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DotRange", NULL },
232 { TIFFTAG_TARGETPRINTER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TargetPrinter", NULL },
233 { TIFFTAG_EXTRASAMPLES, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_EXTRASAMPLES, 0, 1, "ExtraSamples", NULL },
234 diff --git a/libtiff/tif_dirwrite.c b/libtiff/tif_dirwrite.c
235 index 6c86fdca..062e4610 100644
236 --- a/libtiff/tif_dirwrite.c
237 +++ b/libtiff/tif_dirwrite.c
238 @@ -626,6 +626,11 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64_t* pdiroff)
239 if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,TIFFTAG_INKNAMES,tif->tif_dir.td_inknameslen,tif->tif_dir.td_inknames))
240 goto bad;
241 }
242 + if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS))
243 + {
244 + if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir, TIFFTAG_NUMBEROFINKS, tif->tif_dir.td_numberofinks))
245 + goto bad;
246 + }
247 if (TIFFFieldSet(tif,FIELD_SUBIFD))
248 {
249 if (!TIFFWriteDirectoryTagSubifd(tif,&ndir,dir))
250 diff --git a/libtiff/tif_print.c b/libtiff/tif_print.c
251 index 16ce5780..a91b9e7b 100644
252 --- a/libtiff/tif_print.c
253 +++ b/libtiff/tif_print.c
254 @@ -397,6 +397,10 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
255 }
256 fputs("\n", fd);
257 }
258 + if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS)) {
259 + fprintf(fd, " NumberOfInks: %d\n",
260 + td->td_numberofinks);
261 + }
262 if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) {
263 fprintf(fd, " Thresholding: ");
264 switch (td->td_threshholding) {
265 --
266 2.34.1
267