---
source: src/patch/parse.rs
expression: patches
input_file: src/patch/test-data/CVE-2019-12211-13.patch
---
Ok(
    [
        Patch {
            original: Some(
                Filename(
                    "freeimage.orig/Source/FreeImage/PluginTIFF.cpp",
                ),
            ),
            modified: Some(
                Filename(
                    "freeimage/Source/FreeImage/PluginTIFF.cpp",
                ),
            ),
            hunks: [
                Hunk {
                    old_range: HunkRange {
                        start: 122,
                        len: 9,
                    },
                    new_range: HunkRange {
                        start: 122,
                        len: 14,
                    },
                    function_context: Some(
                        "static void ReadThumbnail(FreeImageIO *i\n",
                    ),
                    lines: [
                        Context(
                            "static int s_format_id;\n",
                        ),
                        Context(
                            "\n",
                        ),
                        Context(
                            "typedef struct {\n",
                        ),
                        Insert(
                            "    //! FreeImage IO functions\n",
                        ),
                        Context(
                            "    FreeImageIO *io;\n",
                        ),
                        Insert(
                            "    //! FreeImage handle\n",
                        ),
                        Context(
                            "\tfi_handle handle;\n",
                        ),
                        Insert(
                            "    //! LibTIFF handle\n",
                        ),
                        Context(
                            "\tTIFF *tif;\n",
                        ),
                        Insert(
                            "    //! Count the number of thumbnails already read (used to avoid recursion on loading)\n",
                        ),
                        Insert(
                            "    unsigned thumbnailCount;\n",
                        ),
                        Context(
                            "} fi_TIFFIO;\n",
                        ),
                        Context(
                            "\n",
                        ),
                        Context(
                            "// ----------------------------------------------------------\n",
                        ),
                    ],
                },
                Hunk {
                    old_range: HunkRange {
                        start: 184,
                        len: 9,
                    },
                    new_range: HunkRange {
                        start: 189,
                        len: 7,
                    },
                    function_context: Some(
                        "Open a TIFF file descriptor for reading\n",
                    ),
                    lines: [
                        Context(
                            "*/\n",
                        ),
                        Context(
                            "TIFF *\n",
                        ),
                        Context(
                            "TIFFFdOpen(thandle_t handle, const char *name, const char *mode) {\n",
                        ),
                        Delete(
                            "\tTIFF *tif;\n",
                        ),
                        Delete(
                            "\t\n",
                        ),
                        Context(
                            "\t// Open the file; the callback will set everything up\n",
                        ),
                        Delete(
                            "\ttif = TIFFClientOpen(name, mode, handle,\n",
                        ),
                        Insert(
                            "\tTIFF *tif = TIFFClientOpen(name, mode, handle,\n",
                        ),
                        Context(
                            "\t    _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,\n",
                        ),
                        Context(
                            "\t    _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);\n",
                        ),
                    ],
                },
                Hunk {
                    old_range: HunkRange {
                        start: 460,
                        len: 7,
                    },
                    new_range: HunkRange {
                        start: 463,
                        len: 7,
                    },
                    function_context: Some(
                        "CreateImageType(BOOL header_only, FREE_I\n",
                    ),
                    lines: [
                        Context(
                            "\t\t\t}\n",
                        ),
                        Context(
                            "\t\t\t\n",
                        ),
                        Context(
                            "\t\t}\n",
                        ),
                        Delete(
                            "\t\telse {\n",
                        ),
                        Insert(
                            "\t\telse if (bpp <= 32) {\n",
                        ),
                        Context(
                            "\n",
                        ),
                        Delete(
                            "\t\t\tdib = FreeImage_AllocateHeader(header_only, width, height, MIN(bpp, 32), FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);\n",
                        ),
                        Insert(
                            "\t\t\tdib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);\n",
                        ),
                        Context(
                            "\t\t}\n",
                        ),
                    ],
                },
                Hunk {
                    old_range: HunkRange {
                        start: 1053,
                        len: 6,
                    },
                    new_range: HunkRange {
                        start: 1056,
                        len: 7,
                    },
                    function_context: Some(
                        "Open(FreeImageIO *io, fi_handle handle,\n",
                    ),
                    lines: [
                        Context(
                            "\tif(!fio) return NULL;\n",
                        ),
                        Context(
                            "\tfio->io = io;\n",
                        ),
                        Context(
                            "\tfio->handle = handle;\n",
                        ),
                        Insert(
                            "        fio->thumbnailCount = 0;\n",
                        ),
                        Context(
                            "\n",
                        ),
                        Context(
                            "\tif (read) {\n",
                        ),
                        Context(
                            "\t\tfio->tif = TIFFFdOpen((thandle_t)fio, \"\", \"r\");\n",
                        ),
                    ],
                },
                Hunk {
                    old_range: HunkRange {
                        start: 1108,
                        len: 6,
                    },
                    new_range: HunkRange {
                        start: 1112,
                        len: 27,
                    },
                    function_context: Some(
                        "check for uncommon bitspersample values\n",
                    ),
                    lines: [
                        Context(
                            "*/\n",
                        ),
                        Context(
                            "static BOOL \n",
                        ),
                        Context(
                            "IsValidBitsPerSample(uint16 photometric, uint16 bitspersample, uint16 samplesperpixel) {\n",
                        ),
                        Insert(
                            "        // get the pixel depth in bits\n",
                        ),
                        Insert(
                            "        const uint16 pixel_depth = bitspersample * samplesperpixel;\n",
                        ),
                        Insert(
                            "\n",
                        ),
                        Insert(
                            "        // check for a supported pixel depth\n",
                        ),
                        Insert(
                            "        switch (pixel_depth) {\n",
                        ),
                        Insert(
                            "            case 1:\n",
                        ),
                        Insert(
                            "            case 4:\n",
                        ),
                        Insert(
                            "            case 8:\n",
                        ),
                        Insert(
                            "            case 16:\n",
                        ),
                        Insert(
                            "            case 24:\n",
                        ),
                        Insert(
                            "            case 32:\n",
                        ),
                        Insert(
                            "            case 48:\n",
                        ),
                        Insert(
                            "            case 64:\n",
                        ),
                        Insert(
                            "            case 96:\n",
                        ),
                        Insert(
                            "            case 128:\n",
                        ),
                        Insert(
                            "                // OK, go on\n",
                        ),
                        Insert(
                            "                break;\n",
                        ),
                        Insert(
                            "            default:\n",
                        ),
                        Insert(
                            "                // unsupported pixel depth\n",
                        ),
                        Insert(
                            "                return FALSE;\n",
                        ),
                        Insert(
                            "        }\n",
                        ),
                        Context(
                            "\n",
                        ),
                        Context(
                            "\tswitch(bitspersample) {\n",
                        ),
                        Context(
                            "\t\tcase 1:\n",
                        ),
                    ],
                },
                Hunk {
                    old_range: HunkRange {
                        start: 1148,
                        len: 6,
                    },
                    new_range: HunkRange {
                        start: 1173,
                        len: 8,
                    },
                    function_context: Some(
                        "IsValidBitsPerSample(uint16 photometric,\n",
                    ),
                    lines: [
                        Context(
                            "\t\tdefault:\n",
                        ),
                        Context(
                            "\t\t\treturn FALSE;\n",
                        ),
                        Context(
                            "\t}\n",
                        ),
                        Insert(
                            "\n",
                        ),
                        Insert(
                            "        return FALSE;\n",
                        ),
                        Context(
                            "}\n",
                        ),
                        Context(
                            "\n",
                        ),
                        Context(
                            "static TIFFLoadMethod  \n",
                        ),
                    ],
                },
                Hunk {
                    old_range: HunkRange {
                        start: 1237,
                        len: 16,
                    },
                    new_range: HunkRange {
                        start: 1264,
                        len: 32,
                    },
                    function_context: Some(
                        "Read embedded thumbnail\n",
                    ),
                    lines: [
                        Context(
                            "static void \n",
                        ),
                        Context(
                            "ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib) {\n",
                        ),
                        Context(
                            "\tFIBITMAP* thumbnail = NULL;\n",
                        ),
                        Insert(
                            "\n",
                        ),
                        Insert(
                            "        fi_TIFFIO *fio = (fi_TIFFIO*)data;\n",
                        ),
                        Insert(
                            "\n",
                        ),
                        Insert(
                            "        /*\n",
                        ),
                        Insert(
                            "        Thumbnail loading can cause recursions because of the way \n",
                        ),
                        Insert(
                            "        functions TIFFLastDirectory and TIFFSetSubDirectory are working.\n",
                        ),
                        Insert(
                            "        We use here a hack to count the number of times the ReadThumbnail function was called. \n",
                        ),
                        Insert(
                            "        We only allow one call, check for this\n",
                        ),
                        Insert(
                            "        */\n",
                        ),
                        Insert(
                            "        if (fio->thumbnailCount > 0) {\n",
                        ),
                        Insert(
                            "            return;\n",
                        ),
                        Insert(
                            "        }\n",
                        ),
                        Insert(
                            "        else {\n",
                        ),
                        Insert(
                            "            // update the thumbnail count (used to avoid recursion)\n",
                        ),
                        Insert(
                            "            fio->thumbnailCount++;\n",
                        ),
                        Insert(
                            "        }\n",
                        ),
                        Context(
                            "\t\n",
                        ),
                        Context(
                            "\t// read exif thumbnail (IFD 1) ...\n",
                        ),
                        Context(
                            "\t\n",
                        ),
                        Delete(
                            "\t/*\n",
                        ),
                        Delete(
                            "\t// this code can cause unwanted recursion causing an overflow, it is thus disabled until we have a better solution\n",
                        ),
                        Delete(
                            "\t// do we really need to read a thumbnail from the Exif segment ? knowing that TIFF store the thumbnail in the subIFD ...\n",
                        ),
                        Delete(
                            "\t// \n",
                        ),
                        Context(
                            "\ttoff_t exif_offset = 0;\n",
                        ),
                        Context(
                            "\tif(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) {\n",
                        ),
                        Context(
                            "\t\t\n",
                        ),
                        Insert(
                            "                // this code can cause unwanted recursion causing an overflow,\n",
                        ),
                        Insert(
                            "                // because of the way TIFFLastDirectory work => this is checked\n",
                        ),
                        Insert(
                            "                // using \n",
                        ),
                        Insert(
                            "\n",
                        ),
                        Context(
                            "\t\tif(!TIFFLastDirectory(tiff)) {\n",
                        ),
                        Context(
                            "\t\t\t// save current position\n",
                        ),
                        Context(
                            "\t\t\tconst long tell_pos = io->tell_proc(handle);\n",
                        ),
                    ],
                },
                Hunk {
                    old_range: HunkRange {
                        start: 1264,
                        len: 7,
                    },
                    new_range: HunkRange {
                        start: 1307,
                        len: 6,
                    },
                    function_context: Some(
                        "ReadThumbnail(FreeImageIO *io, fi_handle\n",
                    ),
                    lines: [
                        Context(
                            "\t\t\tTIFFSetDirectory(tiff, cur_dir);\n",
                        ),
                        Context(
                            "\t\t}\n",
                        ),
                        Context(
                            "\t}\n",
                        ),
                        Delete(
                            "\t*/\n",
                        ),
                        Context(
                            "\t\n",
                        ),
                        Context(
                            "\t// ... or read the first subIFD\n",
                        ),
                        Context(
                            "\t\n",
                        ),
                    ],
                },
                Hunk {
                    old_range: HunkRange {
                        start: 1281,
                        len: 6,
                    },
                    new_range: HunkRange {
                        start: 1323,
                        len: 10,
                    },
                    function_context: Some(
                        "ReadThumbnail(FreeImageIO *io, fi_handle\n",
                    ),
                    lines: [
                        Context(
                            "\t\t\t\tconst long tell_pos = io->tell_proc(handle);\n",
                        ),
                        Context(
                            "\t\t\t\tconst uint16 cur_dir = TIFFCurrentDirectory(tiff);\n",
                        ),
                        Context(
                            "\t\t\t\t\n",
                        ),
                        Insert(
                            "                                // this code can cause unwanted recursion\n",
                        ),
                        Insert(
                            "                                // causing an overflow, because of the way\n",
                        ),
                        Insert(
                            "                                // TIFFSetSubDirectory work\n",
                        ),
                        Insert(
                            "\n",
                        ),
                        Context(
                            "\t\t\t\tif(TIFFSetSubDirectory(tiff, subIFD_offsets[0])) {\n",
                        ),
                        Context(
                            "\t\t\t\t\t// load the thumbnail\n",
                        ),
                        Context(
                            "\t\t\t\t\tint page = -1; \n",
                        ),
                    ],
                },
                Hunk {
                    old_range: HunkRange {
                        start: 2041,
                        len: 6,
                    },
                    new_range: HunkRange {
                        start: 2087,
                        len: 6,
                    },
                    function_context: Some(
                        "Load(FreeImageIO *io, fi_handle handle,\n",
                    ),
                    lines: [
                        Context(
                            "\t\t\t\t}\n",
                        ),
                        Context(
                            "\n",
                        ),
                        Context(
                            "\t\t\t\t// calculate src line and dst pitch\n",
                        ),
                        Delete(
                            "\t\t\t\tint dst_pitch = FreeImage_GetPitch(dib);\n",
                        ),
                        Insert(
                            "\t\t\t\tunsigned dst_pitch = FreeImage_GetPitch(dib);\n",
                        ),
                        Context(
                            "\t\t\t\tuint32 tileRowSize = (uint32)TIFFTileRowSize(tif);\n",
                        ),
                        Context(
                            "\t\t\t\tuint32 imageRowSize = (uint32)TIFFScanlineSize(tif);\n",
                        ),
                    ],
                },
                Hunk {
                    old_range: HunkRange {
                        start: 2071,
                        len: 7,
                    },
                    new_range: HunkRange {
                        start: 2117,
                        len: 7,
                    },
                    function_context: Some(
                        "Load(FreeImageIO *io, fi_handle handle,\n",
                    ),
                    lines: [
                        Context(
                            "\t\t\t\t\t\tBYTE *src_bits = tileBuffer;\n",
                        ),
                        Context(
                            "\t\t\t\t\t\tBYTE *dst_bits = bits + rowSize;\n",
                        ),
                        Context(
                            "\t\t\t\t\t\tfor(int k = 0; k < nrows; k++) {\n",
                        ),
                        Delete(
                            "\t\t\t\t\t\t\tmemcpy(dst_bits, src_bits, src_line);\n",
                        ),
                        Insert(
                            "\t\t\t\t\t\t\tmemcpy(dst_bits, src_bits, MIN(dst_pitch, src_line));\n",
                        ),
                        Context(
                            "\t\t\t\t\t\t\tsrc_bits += tileRowSize;\n",
                        ),
                        Context(
                            "\t\t\t\t\t\t\tdst_bits -= dst_pitch;\n",
                        ),
                        Context(
                            "\t\t\t\t\t\t}\n",
                        ),
                    ],
                },
            ],
        },
    ],
)
