diff options
| -rw-r--r-- | meta/recipes-multimedia/libtiff/files/0001-Revised-handling-of-TIFFTAG_INKNAMES-and-related-TIF.patch | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/meta/recipes-multimedia/libtiff/files/0001-Revised-handling-of-TIFFTAG_INKNAMES-and-related-TIF.patch b/meta/recipes-multimedia/libtiff/files/0001-Revised-handling-of-TIFFTAG_INKNAMES-and-related-TIF.patch new file mode 100644 index 0000000000..17b37be041 --- /dev/null +++ b/meta/recipes-multimedia/libtiff/files/0001-Revised-handling-of-TIFFTAG_INKNAMES-and-related-TIF.patch | |||
| @@ -0,0 +1,267 @@ | |||
| 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 | |||
