Example #1
0
/* scans first IDF and returns the type of the n-th tag */
uint32 TIFFGetRawTagTypeListEntry( TIFF  * tif, int tagidx ) {
if (tagidx >= 0) {
    ifd_entry_t ifd_entry;
    ifd_entry =  TIFFGetRawTagIFDListEntry( tif, tagidx );
    return ifd_entry.datatype;
  } else { /* tag not defined */ 
    fprintf(stderr, "tagidx should be greater 0");
    exit(EXIT_FAILURE);
  }
}
Example #2
0
/*  TODO */
ifd_entry_t TIFFGetRawIFDEntry( TIFF * tif, tag_t tag) {
  int tagidx = -1;
  int i;
  for (i= 0; i < TIFFGetRawTagListCount( tif ); i++) {
    if (tag == TIFFGetRawTagListEntry( tif, i ) && tag > 253) {
      tagidx= i;
      break;
    };
  };
  if (tagidx >= 0) {
    ifd_entry_t ifd_entry;
    ifd_entry =  TIFFGetRawTagIFDListEntry( tif, tagidx );
    return ifd_entry;
  } else { /* tag not defined */ 
    fprintf(stderr, "tag %u (%s) should exist, because defined\n", tag, TIFFTagName(tif, tag));
    exit(EXIT_FAILURE);
  }
}
/* check if offsets are greater zero */
ret_t check_all_offsets_are_greater_zero(ctiff_t * ctif) {
  GET_EMPTY_RET(ret)
  tifp_check( ctif);
  int count = get_ifd0_count( ctif);
  int tagidx;
  for (tagidx = 0; tagidx< count; tagidx++) {
    ifd_entry_t ifd_entry = TIFFGetRawTagIFDListEntry( ctif, tagidx );
    uint32 tag = TIFFGetRawTagListEntry( ctif, tagidx);
    if (ifd_entry.value_or_offset==is_offset || tag == TIFFTAG_EXIFIFD) {
      uint32 offset=0;
      if (ifd_entry.value_or_offset==is_offset) offset = ifd_entry.data32offset;
      else if (tag == TIFFTAG_EXIFIFD) {
        if (ifd_entry.count > 1) {
          ret = set_value_found_ret(&ret, int2str(ifd_entry.count));
          ret.returncode = tagerror_expected_count_isgreaterone;
          return ret;
        }
        switch (ifd_entry.datatype) {
          case TIFF_LONG: { /*  correct type */
                            offset = ifd_entry.data32;
                            break;
                          }
          default: { /*  incorrect type for EXIF IFD */
                     ret = set_value_found_ret(&ret, TIFFTypeName(ifd_entry.datatype));
                     ret.returncode = tagerror_unexpected_type_found;
                     return ret;
                     /* break; */
                   };

        }
      } /*  end else if tag == TIFFTAG_EXIFIFD */
      if ( 0 == offset) {
        // FIXME: tif_fails?
        char array[TIFFAILSTRLEN];
        snprintf(array, sizeof(array), "tag %u pointing to 0x%08x", tag, offset);
        ret = set_value_found_ret (&ret, array);
        ret.returncode = tagerror_offset_is_zero;
        return ret;
      }
    }
  }
  ret.returncode=is_valid;
  return ret;
}
/* check if offsets are word aligned */
ret_t check_all_offsets_are_word_aligned(ctiff_t * ctif) {
  //printf("check if all offsets are word aligned\n");
  tif_rules("all offsets are word aligned");
  int count = get_ifd0_count( ctif);
  int tagidx;
  for (tagidx = 0; tagidx< count; tagidx++) {
    ifd_entry_t ifd_entry = TIFFGetRawTagIFDListEntry( ctif, tagidx );
    if (ifd_entry.value_or_offset==is_offset) {
      uint32 offset = ifd_entry.data32offset;
      if ( 0 != (offset & 1)) {
        uint32 tag = TIFFGetRawTagListEntry( ctif, tagidx);
        // FIXME: tif_fails?
        char array[TIFFAILSTRLEN];
        snprintf(array, sizeof(array), "pointing to 0x%08x and is not word-aligned", offset);
        return tif_fails_tag( tag, "word-aligned", array);
      }
    }
  }
  ret_t res;
  res.returnmsg=NULL;
  res.returncode=0;
  return res;
}
/* TODO: add support for StripOffsets and StripByteCounts */
mem_map_t * scan_mem_map(ctiff_t * ctif) {
  assert( NULL != ctif);
  static mem_map_t memmap;
  memmap.count = 0;
  memmap.base_p = NULL;
  memmap.max_entries = 2048;
  memmap.base_p = malloc (sizeof(mem_map_entry_t) * memmap.max_entries);
  if (NULL == memmap.base_p) {
	  perror ("could not allocate mem for memmap, abort");
  }
  /* size of tiff file in bytes */
  memmap.max_len = ctif->streamlen;
  /* header */
  add_mem_entry( &memmap, 0, 4, mt_constant);
  /* IFD0 Offset */
  add_mem_entry( &memmap, 4, 4, mt_offset_to_ifd0);
  /* IFDO */
  uint32 ifd = get_ifd0_pos( ctif );
  uint16 count = get_ifd0_count( ctif);

  add_mem_entry( &memmap, ifd, 2, mt_ifd); /* count of tags in ifd */
  int ifdbase=2+ifd;
  /* iterate through IFD0 entries */
  uint16 tagidx;
  ifd_entry_t stripoffset_entry; 

  for (tagidx = 0; tagidx< count; tagidx++) {
	  add_mem_entry( &memmap, ifdbase+(tagidx*12), 8, mt_ifd); /* tagid, field type, count */
	  ifd_entry_t ifd_entry = TIFFGetRawTagIFDListEntry( ctif, tagidx );
	  uint32 tag = TIFFGetRawTagListEntry( ctif, tagidx);
	  TIFFDataType datatype = TIFFGetRawTagType( ctif, tag);
	  int datasize;
	  switch (datatype) {
		  case TIFF_ASCII: datasize = 1; break;
		  case TIFF_LONG: datasize =  4; break;
		  case TIFF_SHORT: datasize =  2; break;
		  case TIFF_BYTE: datasize =  1; break;
		  case TIFF_UNDEFINED: datasize =  1; break;
		  case TIFF_RATIONAL: datasize =  8; break;
		  case TIFF_SSHORT: datasize =  2; break;
		  case TIFF_SBYTE: datasize =  1; break;
		  case TIFF_SLONG: datasize =  4; break;
		  case TIFF_SRATIONAL: datasize =  8; break;
		  case TIFF_FLOAT: datasize =  4; break;
		  case TIFF_DOUBLE: datasize =  8; break;
                  default: fprintf(stderr, "unknown datatype %i, possible a program error", datatype); exit(EXIT_FAILURE);
	  }
          uint32 offset = ifd_entry.data32offset;
          uint16 count = ifd_entry.count;

          if (tag == TIFFTAG_STRIPOFFSETS) {
                  if (ifd_entry.value_or_offset == is_offset) {
                  add_mem_entry( &memmap, ifdbase+(tagidx*12)+8,4,mt_ifd_offset_to_standardized_value ); 
                  add_mem_entry( &memmap, offset, ((uint32) count)*datasize, mt_ifd_offset_to_stripoffsets );
                  } else if (ifd_entry.value_or_offset==is_value) {
                        add_mem_entry( &memmap, ifdbase+(tagidx*12)+8, 4,mt_ifd_embedded_standardized_value );
                  }
                  stripoffset_entry=ifd_entry;
          } else if (ifd_entry.value_or_offset==is_offset) { /* offset */
		  if (tag < 32768) { /* standard tag */
			  add_mem_entry( &memmap, ifdbase+(tagidx*12)+8, 4,mt_ifd_offset_to_standardized_value ); 
			  add_mem_entry( &memmap, offset, ((uint32) count)*datasize, mt_standardized_value );
		  } else if (tag < 65000) { /* registered tag */
			  add_mem_entry( &memmap, ifdbase+(tagidx*12)+8, 4,mt_ifd_offset_to_registered_value ); 
			  add_mem_entry( &memmap, offset, ((uint32) count)*datasize, mt_registered_value );
		  } else { /* private tag */
			  add_mem_entry( &memmap, ifdbase+(tagidx*12)+8, 4,mt_ifd_offset_to_private_value ); 
			  add_mem_entry( &memmap, offset, ((uint32) count)*datasize, mt_private_value );
		  }
	  } else if (ifd_entry.value_or_offset==is_value) { /* embedded value */
		  if (tag < 32768) { /* standard tag */
			  add_mem_entry( &memmap, ifdbase+(tagidx*12)+8, 4,mt_ifd_embedded_standardized_value ); 
		  } else if (tag < 65000) { /* registered tag */
			  add_mem_entry( &memmap, ifdbase+(tagidx*12)+8, 4,mt_ifd_embedded_registered_value ); 
		  } else { /* private tag */
			  add_mem_entry( &memmap, ifdbase+(tagidx*12)+8, 4,mt_ifd_embedded_private_value ); 
		  }

	  }
  }
 
  /* check next IFD mark */
  // uint32 offset = get_ifd0_pos(ctif );
  // uint32 IFDn = get_next_ifd_pos( ctif, offset );
  // printf("IFD: offset=%i, IFD0=%i IFDn=%i ifd+count=%i\n", offset, ifd, IFDn, ifdbase+12*count);
  add_mem_entry( &memmap, ifdbase+12*count, 4, mt_offset_to_ifd);

  /* handle stripoffset data */
  //printf("ifd_count=%i, stripoffset_count=%i\n", stripoffset_entry.count, stripoffset_count);
  uint32 stripoffset_values[stripoffset_entry.count];
  switch (stripoffset_entry.datatype) {
    case TIFF_LONG: {
                      /*  value */
                      if (stripoffset_entry.value_or_offset == is_value) {
                        for (uint32 i=0; i< stripoffset_entry.count; i++) {
                          stripoffset_values[i] = stripoffset_entry.data32;
                        }
                      }
                      /*  offset */
                      if (stripoffset_entry.value_or_offset == is_offset) {
                        offset_t offset;
                        ret_t ret = read_offsetdata(ctif, stripoffset_entry.data32offset, stripoffset_entry.count, stripoffset_entry.datatype, &offset, &ret);
                        if (ret.returncode != is_valid) {
                          fprintf(stderr, "error reading offset data, stripoffset_entry.count has size %u, resulting address %zu, but only offset to %lu is possible\n", stripoffset_entry.count, ((uint64) stripoffset_entry.count*sizeof(uint32)), (uint64) 0xffffffff);
                          exit(EXIT_FAILURE);
                        }
                        uint32 * p = offset.data32p;
                        if ((uint64) stripoffset_entry.count*sizeof(uint32) > 0xffffffff) {
                          fprintf(stderr, "stripoffset_entry.count has size %u, resulting address %zu, but only offset to %lu is possible\n", stripoffset_entry.count, ((uint64) stripoffset_entry.count*sizeof(uint32)), (uint64) 0xffffffff);
                          exit(EXIT_FAILURE);
                        }
                        for (uint32 i=0; i< stripoffset_entry.count; i++) {
                          uint32 pval = *p;
                          if (is_byteswapped(ctif)) {
                            TIFFSwabLong(&pval);
                          }
                          stripoffset_values[i]=pval;
                          p++;
                        }
                      }
                      break;
                    }
    case TIFF_SHORT: {
                       /*  value */
                       if (stripoffset_entry.value_or_offset == is_value) {
                         for (uint32 i=0; i< stripoffset_entry.count; i++) {
                           stripoffset_values[i]= stripoffset_entry.data16[i];
                         }
                       }
                       /*  offset */
                       if (stripoffset_entry.value_or_offset == is_offset) {
                         offset_t offset;
                         ret_t ret = read_offsetdata(ctif, stripoffset_entry.data32offset, stripoffset_entry.count, stripoffset_entry.datatype, &offset, &ret);
                         if (ret.returncode != is_valid) {
                           fprintf(stderr, "error reading offset data, stripoffset_entry.count has size %u, resulting address %zu, but only offset to %lu is possible\n", stripoffset_entry.count, ((uint64) stripoffset_entry.count*sizeof(uint32)), (uint64) 0xffffffff);
                           exit(EXIT_FAILURE);
                         }
                         uint16 * p = offset.data16p;
                         if ((uint64) stripoffset_entry.count*sizeof(uint16) > 0xffffffff) {
                           fprintf(stderr, "stripoffset_entry.count has size %u, resulting address %zu, but only offset to %lu is possible\n", stripoffset_entry.count, ((uint64) stripoffset_entry.count*sizeof(uint16)), (uint64) 0xffffffff);
                           exit(EXIT_FAILURE);
                         }
                         for (uint32 i=0; i< count; i++) {
                           uint16 pval = *p;
                           if (is_byteswapped(ctif)) {
                             TIFFSwabShort(&pval);
                           }
                           stripoffset_values[i]=pval;
                           p++;
                         }
                       }
                       break;
                     }
    default: {
               perror("stripoffset_entry.datatype has an unexpected value, possible a program error\n");
               exit(EXIT_FAILURE);
             }
  }
  //printf("count=%i\n", stripoffset_entry.count);
/*TODO:
  for (int i=0; i< stripoffset_entry.count; i++) {
    uint32 rawstriplen = TIFFRawStripSize(ctif->tif, i);
    //printf("OFFSET: p[%i]=%u len=%i\n", i,stripoffset_values[i], rawstriplen);
    add_mem_entry( &memmap, stripoffset_values[i], rawstriplen, mt_stripoffset_value);
  }
*/
  /* sort entries by offset */
  qsort(memmap.base_p, memmap.count, sizeof( mem_map_entry_t), compare_memmap);
  /*
  printf("memmap before HOLE detection\n");
  print_mem_map( &memmap );
  printf("----------------------------\n");
  */

  /* add all unused areas */
  uint32 memmap_orig_count = memmap.count;
  for (uint32 j=1; j< memmap_orig_count; j++) {
    mem_map_entry_t * prev=memmap.base_p+j-1;
    mem_map_entry_t * act =memmap.base_p+j;
    uint32 estimated_offset = (prev->offset + prev->count);
    if (estimated_offset < act->offset) { /*  found a hole */
      printf("HOLE FOUND at %u\n", estimated_offset);
      
      printf("\tprev->offset=%u prev->count=%u estimated=%u\n", prev->offset, prev->count, estimated_offset);
      printf("\tact->offset=%u act->count=%u\n", act->offset, act->count);
      
      add_mem_entry( &memmap, estimated_offset, (act->offset -estimated_offset), mt_unused);
    }
  }
  /* sort entries by offset again */
  qsort(memmap.base_p, memmap.count, sizeof( mem_map_entry_t), compare_memmap);
  /*  add unused area at end */
  mem_map_entry_t * last = memmap.base_p + memmap.count-1;
  uint32 estimated_offset = (last->offset + last->count);
  if (memmap.max_len > estimated_offset) {
      printf("HOLE (at end) FOUND at %u\n", estimated_offset);
      add_mem_entry( &memmap, estimated_offset, (memmap.max_len -estimated_offset), mt_unused);
  }
  /* sort entries by offset again */
  qsort(memmap.base_p, memmap.count, sizeof( mem_map_entry_t), compare_memmap);
  return &memmap;
}