?? tif_dirread.c
字號:
toff_t* new_dirlist; /* * XXX: Reduce memory allocation granularity of the dirlist * array. */ new_dirlist = (toff_t *)_TIFFCheckRealloc(tif, tif->tif_dirlist, tif->tif_dirnumber, 2 * sizeof(toff_t), "for IFD list"); if (!new_dirlist) return 0; tif->tif_dirlistsize = 2 * tif->tif_dirnumber; tif->tif_dirlist = new_dirlist; } tif->tif_dirlist[tif->tif_dirnumber - 1] = diroff; return 1;}/* * Check the count field of a directory entry against a known value. The * caller is expected to skip/ignore the tag if there is a mismatch. */static intCheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count){ if (count > dir->tdir_count) { TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "incorrect count for field \"%s\" (%lu, expecting %lu); tag ignored", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, dir->tdir_count, count); return (0); } else if (count < dir->tdir_count) { TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "incorrect count for field \"%s\" (%lu, expecting %lu); tag trimmed", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, dir->tdir_count, count); return (1); } return (1);}/* * Read IFD structure from the specified offset. If the pointer to * nextdiroff variable has been specified, read it too. Function returns a * number of fields in the directory or 0 if failed. */static uint16TIFFFetchDirectory(TIFF* tif, toff_t diroff, TIFFDirEntry **pdir, toff_t *nextdiroff){ static const char module[] = "TIFFFetchDirectory"; TIFFDirEntry *dir; uint16 dircount; assert(pdir); tif->tif_diroff = diroff; if (nextdiroff) *nextdiroff = 0; if (!isMapped(tif)) { if (!SeekOK(tif, tif->tif_diroff)) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Seek error accessing TIFF directory", tif->tif_name); return 0; } if (!ReadOK(tif, &dircount, sizeof (uint16))) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Can not read TIFF directory count", tif->tif_name); return 0; } if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); dir = (TIFFDirEntry *)_TIFFCheckMalloc(tif, dircount, sizeof (TIFFDirEntry), "to read TIFF directory"); if (dir == NULL) return 0; if (!ReadOK(tif, dir, dircount*sizeof (TIFFDirEntry))) { TIFFErrorExt(tif->tif_clientdata, module, "%.100s: Can not read TIFF directory", tif->tif_name); _TIFFfree(dir); return 0; } /* * Read offset to next directory for sequential scans if * needed. */ if (nextdiroff) (void) ReadOK(tif, nextdiroff, sizeof(uint32)); } else { toff_t off = tif->tif_diroff; /* * Check for integer overflow when validating the dir_off, * otherwise a very high offset may cause an OOB read and * crash the client. Make two comparisons instead of * * off + sizeof(uint16) > tif->tif_size * * to avoid overflow. */ if (tif->tif_size < sizeof (uint16) || off > tif->tif_size - sizeof(uint16)) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Can not read TIFF directory count", tif->tif_name); return 0; } else { _TIFFmemcpy(&dircount, tif->tif_base + off, sizeof(uint16)); } off += sizeof (uint16); if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); dir = (TIFFDirEntry *)_TIFFCheckMalloc(tif, dircount, sizeof(TIFFDirEntry), "to read TIFF directory"); if (dir == NULL) return 0; if (off + dircount * sizeof (TIFFDirEntry) > tif->tif_size) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Can not read TIFF directory", tif->tif_name); _TIFFfree(dir); return 0; } else { _TIFFmemcpy(dir, tif->tif_base + off, dircount * sizeof(TIFFDirEntry)); } if (nextdiroff) { off += dircount * sizeof (TIFFDirEntry); if (off + sizeof (uint32) <= tif->tif_size) { _TIFFmemcpy(nextdiroff, tif->tif_base + off, sizeof (uint32)); } } } if (nextdiroff && tif->tif_flags & TIFF_SWAB) TIFFSwabLong(nextdiroff); *pdir = dir; return dircount;}/* * Fetch a contiguous directory item. */static tsize_tTIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp){ int w = TIFFDataWidth((TIFFDataType) dir->tdir_type); tsize_t cc = dir->tdir_count * w; /* Check for overflow. */ if (!dir->tdir_count || !w || cc / w != (tsize_t)dir->tdir_count) goto bad; if (!isMapped(tif)) { if (!SeekOK(tif, dir->tdir_offset)) goto bad; if (!ReadOK(tif, cp, cc)) goto bad; } else { /* Check for overflow. */ if ((tsize_t)dir->tdir_offset + cc < (tsize_t)dir->tdir_offset || (tsize_t)dir->tdir_offset + cc < cc || (tsize_t)dir->tdir_offset + cc > (tsize_t)tif->tif_size) goto bad; _TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, cc); } if (tif->tif_flags & TIFF_SWAB) { switch (dir->tdir_type) { case TIFF_SHORT: case TIFF_SSHORT: TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count); break; case TIFF_LONG: case TIFF_SLONG: case TIFF_FLOAT: TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count); break; case TIFF_RATIONAL: case TIFF_SRATIONAL: TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count); break; case TIFF_DOUBLE: TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count); break; } } return (cc);bad: TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error fetching data for field \"%s\"", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); return (tsize_t) 0;}/* * Fetch an ASCII item from the file. */static tsize_tTIFFFetchString(TIFF* tif, TIFFDirEntry* dir, char* cp){ if (dir->tdir_count <= 4) { uint32 l = dir->tdir_offset; if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&l); _TIFFmemcpy(cp, &l, dir->tdir_count); return (1); } return (TIFFFetchData(tif, dir, cp));}/* * Convert numerator+denominator to float. */static intcvtRational(TIFF* tif, TIFFDirEntry* dir, uint32 num, uint32 denom, float* rv){ if (denom == 0) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%s: Rational with zero denominator (num = %lu)", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, num); return (0); } else { if (dir->tdir_type == TIFF_RATIONAL) *rv = ((float)num / (float)denom); else *rv = ((float)(int32)num / (float)(int32)denom); return (1); }}/* * Fetch a rational item from the file * at offset off and return the value * as a floating point number. */static floatTIFFFetchRational(TIFF* tif, TIFFDirEntry* dir){ uint32 l[2]; float v; return (!TIFFFetchData(tif, dir, (char *)l) || !cvtRational(tif, dir, l[0], l[1], &v) ? 1.0f : v);}/* * Fetch a single floating point value * from the offset field and return it * as a native float. */static floatTIFFFetchFloat(TIFF* tif, TIFFDirEntry* dir){ float v; int32 l = TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset); _TIFFmemcpy(&v, &l, sizeof(float)); TIFFCvtIEEEFloatToNative(tif, 1, &v); return (v);}/* * Fetch an array of BYTE or SBYTE values. */static intTIFFFetchByteArray(TIFF* tif, TIFFDirEntry* dir, uint8* v){ if (dir->tdir_count <= 4) { /* * Extract data from offset field. */ if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { if (dir->tdir_type == TIFF_SBYTE) switch (dir->tdir_count) { case 4: v[3] = dir->tdir_offset & 0xff; case 3: v[2] = (dir->tdir_offset >> 8) & 0xff; case 2: v[1] = (dir->tdir_offset >> 16) & 0xff; case 1: v[0] = dir->tdir_offset >> 24; } else switch (dir->tdir_count) { case 4: v[3] = dir->tdir_offset & 0xff; case 3: v[2] = (dir->tdir_offset >> 8) & 0xff; case 2: v[1] = (dir->tdir_offset >> 16) & 0xff; case 1: v[0] = dir->tdir_offset >> 24; } } else { if (dir->tdir_type == TIFF_SBYTE) switch (dir->tdir_count) { case 4: v[3] = dir->tdir_offset >> 24; case 3: v[2] = (dir->tdir_offset >> 16) & 0xff; case 2: v[1] = (dir->tdir_offset >> 8) & 0xff; case 1: v[0] = dir->tdir_offset & 0xff; } else switch (dir->tdir_count) { case 4: v[3] = dir->tdir_offset >> 24; case 3: v[2] = (dir->tdir_offset >> 16) & 0xff; case 2: v[1] = (dir->tdir_offset >> 8) & 0xff; case 1: v[0] = dir->tdir_offset & 0xff; } } return (1); } else return (TIFFFetchData(tif, dir, (char*) v) != 0); /* XXX */}/* * Fetch an array of SHORT or SSHORT values. */static intTIFFFetchShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v){ if (dir->tdir_count <= 2) { if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { switch (dir->tdir_count) { case 2: v[1] = (uint16) (dir->tdir_offset & 0xffff); case 1: v[0] = (uint16) (dir->tdir_offset >> 16); } } else { switch (dir->tdir_count) { case 2: v[1] = (uint16) (dir->tdir_offset >> 16); case 1: v[0] = (uint16) (dir->tdir_offset & 0xffff); } } return (1); } else return (TIFFFetchData(tif, dir, (char *)v) != 0);}/* * Fetch a pair of SHORT or BYTE values. Some tags may have either BYTE * or SHORT type and this function works with both ones. */static intTIFFFetchShortPair(TIFF* tif, TIFFDirEntry* dir){ /* * Prevent overflowing the v stack arrays below by performing a sanity * check on tdir_count, this should never be greater than two. */ if (dir->tdir_count > 2) { TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "unexpected count for field \"%s\", %lu, expected 2; ignored", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, dir->tdir_count); return 0; } switch (dir->tdir_type) { case TIFF_BYTE: case TIFF_SBYTE: { uint8 v[4]; return TIFFFetchByteArray(tif, dir, v) && TIFFSetField(tif, dir->tdir_tag, v[0], v[1]); } case TIFF_SHORT: case TIFF_SSHORT: { uint16 v[2]; return TIFFFetchShortArray(tif, dir, v) && TIFFSetField(tif, dir->tdir_tag, v[0], v[1]); } default: return 0; }}/* * Fetch an array of LONG or SLONG values. */static intTIFFFetchLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v){ if (dir->tdir_count == 1) { v[0] = dir->tdir_offset; return (1); } else return (TIFFFetchData(tif, dir, (char*) v) != 0);}/* * Fetch an array of RATIONAL or SRATIONAL values. */static intTIFFFetchRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v){ int ok = 0; uint32* l; l = (uint32*)_TIFFCheckMalloc(tif, dir->tdir_count, TIFFDataWidth((TIFFDataType) dir->tdir_type), "to fetch array of rationals"); if (l) { if (TIFFFetchData(tif, dir, (char *)l)) { uint32 i; for (i = 0; i < dir->tdir_count; i++) { ok = cvtRational(tif, dir, l[2*i+0], l[2*i+1], &v[i]); if (!ok) break; } } _TIFFfree((char *)l); } return (ok);}/* * Fetch an array of FLOAT values. */static intTIFFFetchFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v){ if (dir->tdir_count == 1) { v[0] = *(float*) &dir->tdir_offset; TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v); return (1); } else if (TIFFFetchData(tif, dir, (char*) v)) { TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v); return (1); } else return (0);}/* * Fetch an array of DOUBLE values. */static intTIFFFetchDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v){ if (TIFFFetchData(tif, dir, (char*) v)) { TIFFCvtIEEEDoubleToNative(tif, dir->tdir_count, v); return (1); } else return (0);}/* * Fetch an array of ANY values. The actual values are returned as doubles * which should be able hold all the types. Yes, there really should be an * tany_t to avoid this potential non-portability ... Note in particular that * we assume that the double return value vector is large enough to read in * any fundamental type. We use that vector as a buffer to read in the base * type vector and then convert it in place to double (from end to front of * course). */static intTIFFFetchAnyArray(TIFF* tif, TIFFDirEntry* dir, double* v){ int i; switch (dir->tdir_type) { case TIFF_BYTE: case TIFF_SBYTE: if (!TIFFFetchByteArray(tif, dir, (uint8*) v)) return (0); if (dir->tdir_type == TIFF_BYTE) { uint8* vp = (uint8*) v; for (i = dir->tdir_count-1; i >= 0; i--) v[i] = vp[i]; } else { int8* vp = (int8*) v; for (i = dir->tdir_count-1; i >= 0; i--) v[i] = vp[i]; } break; case TIFF_SHORT: case TIFF_SSHORT: if (!TIFFFetchShortArray(tif, dir, (uint16*) v)) return (0); if (dir->tdir_type == TIFF_SHORT) { uint16* vp = (uint16*) v; for (i = dir->tdir_count-1; i >= 0; i--) v[i] = vp[i]; } else { int16* vp = (int16*) v; for (i = dir->tdir_count-1; i >= 0; i--) v[i] = vp[i]; } break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -