|
5 | 5 | * its documentation for any purpose is hereby granted without fee, provided
|
6 | 6 | * that (i) the above copyright notices and this permission notice appear in
|
7 | 7 | * all copies of the software and related documentation, and (ii) the names of
|
8 |
| - * Sam Leffler and Silicon Graphics may not be used in any advertising or |
| 8 | + * the author may not be used in any advertising or |
9 | 9 | * publicity relating to the software without the specific, prior written
|
10 |
| - * permission of Sam Leffler and Silicon Graphics. |
| 10 | + * permission of the author. |
11 | 11 | *
|
12 | 12 | * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
13 | 13 | * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
14 | 14 | * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
15 | 15 | *
|
16 |
| - * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR |
| 16 | + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
17 | 17 | * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
18 | 18 | * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
19 | 19 | * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
20 | 20 | * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
21 | 21 | * OF THIS SOFTWARE.
|
22 | 22 | */
|
23 | 23 |
|
| 24 | +/* =========== Purpose =============================================== |
| 25 | + * Tests the following points: |
| 26 | + * - Handling of signed tags |
| 27 | + * - Definition of additional, user-defined tags |
| 28 | + * - Specification of field name strings or with field_name = NULL |
| 29 | + * - Prevent reading anonymous tags by specifying them as FIELD_IGNORE |
| 30 | + * (see https://gitlab.com/libtiff/libtiff/-/issues/532) |
| 31 | + * - Immediate clearing of the memory for the definition of the additional tags |
| 32 | + * (allocate memory for TIFFFieldInfo structure and free that memory |
| 33 | + * immediately after calling TIFFMergeFieldInfo(). |
| 34 | + */ |
| 35 | + |
| 36 | +#include <memory.h> /* necessary for linux compiler (memset) */ |
24 | 37 | #include <stdio.h>
|
| 38 | +#include <stdlib.h> /* necessary for linux compiler */ |
25 | 39 |
|
26 | 40 | #include "tif_config.h" /* necessary for linux compiler to get HAVE_UNISTD_H */
|
27 | 41 | #ifdef HAVE_UNISTD_H
|
|
36 | 50 |
|
37 | 51 | #define N(a) (sizeof(a) / sizeof(a[0]))
|
38 | 52 |
|
| 53 | +#define FIELD_IGNORE 0 /* same as FIELD_PSEUDO */ |
| 54 | + |
39 | 55 | enum
|
40 | 56 | {
|
41 | 57 | SINT8 = 65100,
|
|
54 | 70 | C32_SINT16,
|
55 | 71 | C32_SINT32,
|
56 | 72 | C32_SINT64,
|
| 73 | + C32_SINT64NULL, |
57 | 74 | };
|
58 | 75 |
|
59 | 76 | static const TIFFFieldInfo tiff_field_info[] = {
|
@@ -81,17 +98,34 @@ static const TIFFFieldInfo tiff_field_info[] = {
|
81 | 98 | "C32_SINT32"},
|
82 | 99 | {C32_SINT64, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_SLONG8, FIELD_CUSTOM, 0,
|
83 | 100 | 1, "C32_SINT64"},
|
| 101 | + /* Test field_name=NULL in static const array, which is now possible because |
| 102 | + * handled within TIFFMergeFieldInfo(). */ |
| 103 | + {C32_SINT64NULL, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_SLONG8, FIELD_CUSTOM, |
| 104 | + 0, 1, NULL}, |
84 | 105 | };
|
85 | 106 |
|
| 107 | +/* Global parameter for the field array to be passed to extender, which can be |
| 108 | + * changed during runtime. */ |
| 109 | +static TIFFFieldInfo *p_tiff_field_info = (TIFFFieldInfo *)tiff_field_info; |
| 110 | +static uint32_t N_tiff_field_info = |
| 111 | + sizeof(tiff_field_info) / sizeof(tiff_field_info[0]); |
| 112 | + |
86 | 113 | static TIFFExtendProc parent = NULL;
|
87 | 114 |
|
88 | 115 | static void extender(TIFF *tif)
|
89 | 116 | {
|
90 |
| - TIFFMergeFieldInfo(tif, tiff_field_info, |
91 |
| - sizeof(tiff_field_info) / sizeof(tiff_field_info[0])); |
92 |
| - if (parent) |
| 117 | + if (p_tiff_field_info != NULL) |
93 | 118 | {
|
94 |
| - (*parent)(tif); |
| 119 | + TIFFMergeFieldInfo(tif, p_tiff_field_info, N_tiff_field_info); |
| 120 | + if (parent) |
| 121 | + { |
| 122 | + (*parent)(tif); |
| 123 | + } |
| 124 | + } |
| 125 | + else |
| 126 | + { |
| 127 | + TIFFErrorExtR(tif, "field_info_extender", |
| 128 | + "Pointer to tiff_field_info array is NULL."); |
95 | 129 | }
|
96 | 130 | }
|
97 | 131 |
|
@@ -187,6 +221,12 @@ static int writeTestTiff(const char *szFileName, int isBigTiff)
|
187 | 221 | fprintf(stdout, "Error writing C32_SINT64: ret=%d\n", ret);
|
188 | 222 | GOTOFAILURE;
|
189 | 223 | }
|
| 224 | + ret = TIFFSetField(tif, C32_SINT64NULL, N(s64), &s64); |
| 225 | + if (ret != 1) |
| 226 | + { |
| 227 | + fprintf(stdout, "Error writing C32_SINT64NULL: ret=%d\n", ret); |
| 228 | + GOTOFAILURE; |
| 229 | + } |
190 | 230 | }
|
191 | 231 |
|
192 | 232 | TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, 1);
|
@@ -506,20 +546,145 @@ static int readTestTiff(const char *szFileName, int isBigTiff)
|
506 | 546 | TIFFClose(tif);
|
507 | 547 | return (retcode);
|
508 | 548 | }
|
| 549 | +/*-- readTestTiff() --*/ |
| 550 | + |
| 551 | +static int readTestTiff_ignore_some_tags(const char *szFileName) |
| 552 | +{ |
| 553 | + int ret; |
| 554 | + int8_t s8l; |
| 555 | + int16_t s16l; |
| 556 | + int32_t s32l; |
| 557 | + int retcode = FAULT_RETURN; |
| 558 | + |
| 559 | + /* There is a use case, where LibTIFF shall be prevented from reading |
| 560 | + * unknown tags that are present in the file as anonymous tags. This can be |
| 561 | + * achieved by defining these tags with ".field_bit = FIELD_IGNORE". */ |
| 562 | + |
| 563 | + /* Copy const array to be manipulated and freed just after TIFFMergeFields() |
| 564 | + * within the "extender()" called by TIFFOpen(). */ |
| 565 | + TIFFFieldInfo *tiff_field_info2; |
| 566 | + tiff_field_info2 = (TIFFFieldInfo *)malloc(sizeof(tiff_field_info)); |
| 567 | + if (tiff_field_info2 == (TIFFFieldInfo *)NULL) |
| 568 | + { |
| 569 | + fprintf(stdout, |
| 570 | + "Can't allocate memoy for tiff_field_info2 structure.\n"); |
| 571 | + return (FAULT_RETURN); |
| 572 | + } |
| 573 | + memcpy(tiff_field_info2, tiff_field_info, sizeof(tiff_field_info)); |
| 574 | + /* Switch field array for extender callback. */ |
| 575 | + p_tiff_field_info = tiff_field_info2; |
| 576 | + |
| 577 | + /*-- Adapt tiff_field_info array for ignoring unknown tags to LibTIFF, which |
| 578 | + * have been written to file before. --*/ |
| 579 | + /* a.) Just set field_bit to FIELD_IGNORE = 0 */ |
| 580 | + tiff_field_info2[2].field_bit = FIELD_IGNORE; |
| 581 | + /* b.) Usecase with all field array infos zero but the tag value. */ |
| 582 | + ttag_t tag = tiff_field_info2[4].field_tag; |
| 583 | + memset(&tiff_field_info2[4], 0, sizeof(tiff_field_info2[4])); |
| 584 | + tiff_field_info2[4].field_tag = tag; |
| 585 | + |
| 586 | + fprintf(stdout, "\n-- Reading file with unknown tags to be ignored ...\n"); |
| 587 | + TIFF *tif = TIFFOpen(szFileName, "r"); |
| 588 | + |
| 589 | + /* tiff_field_info2 should not be needed anymore, as long as the still |
| 590 | + * active extender() is not called again. Therefore, the extender callback |
| 591 | + * should be disabled by resetting it to the saved one. */ |
| 592 | + free(tiff_field_info2); |
| 593 | + tiff_field_info2 = NULL; |
| 594 | + TIFFSetTagExtender(parent); |
| 595 | + |
| 596 | + if (!tif) |
| 597 | + { |
| 598 | + fprintf(stdout, "Can't open test TIFF file %s.\n", szFileName); |
| 599 | + return (FAULT_RETURN); |
| 600 | + } |
| 601 | + |
| 602 | + /* Read the first two known tags for testing */ |
| 603 | + ret = TIFFGetField(tif, SINT8, &s8l); |
| 604 | + if (ret != 1) |
| 605 | + { |
| 606 | + fprintf(stdout, "Error reading SINT8: ret=%d\n", ret); |
| 607 | + GOTOFAILURE |
| 608 | + } |
| 609 | + else |
| 610 | + { |
| 611 | + if (s8l != s8[idxSingle]) |
| 612 | + { |
| 613 | + fprintf(stdout, |
| 614 | + "Read value of SINT8 %d differs from set value %d\n", s8l, |
| 615 | + s8[idxSingle]); |
| 616 | + GOTOFAILURE |
| 617 | + } |
| 618 | + } |
| 619 | + ret = TIFFGetField(tif, SINT16, &s16l); |
| 620 | + if (ret != 1) |
| 621 | + { |
| 622 | + fprintf(stdout, "Error reading SINT16: ret=%d\n", ret); |
| 623 | + GOTOFAILURE |
| 624 | + } |
| 625 | + else |
| 626 | + { |
| 627 | + if (s16l != s16[idxSingle]) |
| 628 | + { |
| 629 | + fprintf(stdout, |
| 630 | + "Read value of SINT16 %d differs from set value %d\n", |
| 631 | + s16l, s16[idxSingle]); |
| 632 | + GOTOFAILURE |
| 633 | + } |
| 634 | + } |
| 635 | + |
| 636 | + /* The two ignored tags shall not be present. */ |
| 637 | + ret = TIFFGetField(tif, tiff_field_info[2].field_tag, &s32l); |
| 638 | + if (ret != 0) |
| 639 | + { |
| 640 | + fprintf(stdout, |
| 641 | + "Error: Tag %d, set to be ignored, has been read from file.\n", |
| 642 | + tiff_field_info[2].field_tag); |
| 643 | + GOTOFAILURE |
| 644 | + } |
| 645 | + |
| 646 | + ret = TIFFGetField(tif, tiff_field_info[4].field_tag, &s32l); |
| 647 | + if (ret != 0) |
| 648 | + { |
| 649 | + fprintf(stdout, |
| 650 | + "Error: Tag %d, set to be ignored, has been read from file.\n", |
| 651 | + tiff_field_info[4].field_tag); |
| 652 | + GOTOFAILURE |
| 653 | + } |
| 654 | + |
| 655 | + retcode = OK_RETURN; |
| 656 | +failure: |
| 657 | + |
| 658 | + fprintf(stdout, |
| 659 | + "-- End of test for ignored unknown tags. Closing TIFF file. --\n"); |
| 660 | + TIFFClose(tif); |
| 661 | + return (retcode); |
| 662 | +} |
| 663 | +/*-- readTestTiff_ignore_some_tags() --*/ |
509 | 664 |
|
510 | 665 | int main(void)
|
511 | 666 | {
|
| 667 | + /*-- Signed tags test --*/ |
512 | 668 | parent = TIFFSetTagExtender(&extender);
|
513 | 669 | if (writeTestTiff("temp.tif", 0) != OK_RETURN)
|
514 | 670 | return (-1);
|
515 | 671 | if (readTestTiff("temp.tif", 0) != OK_RETURN)
|
516 | 672 | return (-1);
|
517 |
| - unlink("temp.tif"); |
| 673 | + |
518 | 674 | if (writeTestTiff("tempBig.tif", 1) != OK_RETURN)
|
519 | 675 | return (-1);
|
520 | 676 | if (readTestTiff("tempBig.tif", 1) != OK_RETURN)
|
521 | 677 | return (-1);
|
522 | 678 | unlink("tempBig.tif");
|
523 |
| - fprintf(stdout, "---------- Test finished OK -----------\n"); |
| 679 | + fprintf(stdout, "---------- Signed tag test finished OK -----------\n"); |
| 680 | + |
| 681 | + /*-- Adapt tiff_field_info array for ignoring unknown tags to LibTIFF, which |
| 682 | + * have been written to file. --*/ |
| 683 | + if (readTestTiff_ignore_some_tags("temp.tif") != OK_RETURN) |
| 684 | + return (-1); |
| 685 | + unlink("temp.tif"); |
| 686 | + fprintf(stdout, |
| 687 | + "---------- Ignoring unknown tag test finished OK -----------\n"); |
| 688 | + |
524 | 689 | return 0;
|
525 | 690 | }
|
0 commit comments