Repository: tesseract-ocr/tesseract
File: src/classify/intproto.cpp (C++)

Code before:
}

/**
 * This routine reads a set of integer templates from
 * File.  File must already be open and must be in the
 * correct binary format.
 * @param  fp open file to read templates from
 * @return Pointer to integer templates read from File.
 * @note Globals: none
 */
INT_TEMPLATES Classify::ReadIntTemplates(TFile *fp) {
  int i, j, w, x, y, z;
  int unicharset_size;
  int version_id = 0;
  INT_TEMPLATES Templates;
  CLASS_PRUNER_STRUCT *Pruner;
  INT_CLASS Class;
  uint8_t *Lengths;
  PROTO_SET ProtoSet;

  /* variables for conversion from older inttemp formats */
  int b, bit_number, last_cp_bit_number, new_b, new_i, new_w;
  CLASS_ID class_id, max_class_id;
  auto *IndexFor = new int16_t[MAX_NUM_CLASSES];
  auto *ClassIdFor = new CLASS_ID[MAX_NUM_CLASSES];
  auto **TempClassPruner = new CLASS_PRUNER_STRUCT *[MAX_NUM_CLASS_PRUNERS];
  uint32_t SetBitsForMask =          // word with NUM_BITS_PER_CLASS
      (1 << NUM_BITS_PER_CLASS) - 1; // set starting at bit 0
  uint32_t Mask, NewMask, ClassBits;
  int MaxNumConfigs = MAX_NUM_CONFIGS;
  int WerdsPerConfigVec = WERDS_PER_CONFIG_VEC;

  /* first read the high level template struct */
  Templates = NewIntTemplates();
  // Read Templates in parts for 64 bit compatibility.
  if (fp->FReadEndian(&unicharset_size, sizeof(unicharset_size), 1) != 1)
    tprintf("Bad read of inttemp!\n");
  if (fp->FReadEndian(&Templates->NumClasses, sizeof(Templates->NumClasses), 1) != 1 ||
      fp->FReadEndian(&Templates->NumClassPruners, sizeof(Templates->NumClassPruners), 1) != 1)
    tprintf("Bad read of inttemp!\n");
  if (Templates->NumClasses < 0) {
    // This file has a version id!
    version_id = -Templates->NumClasses;
    if (fp->FReadEndian(&Templates->NumClasses, sizeof(Templates->NumClasses), 1) != 1)
      tprintf("Bad read of inttemp!\n");
  }

  if (version_id < 3) {
    MaxNumConfigs = OLD_MAX_NUM_CONFIGS;
    WerdsPerConfigVec = OLD_WERDS_PER_CONFIG_VEC;
  }

Review comment (bug):
Use this with caution.
On recursive calls and big size of such arrays it may cause stack overflow.
This comes to mind because dynamic memory allocation probably was used intentionally.
We should double check this.

Code after:
  free(templates);
}

/**
 * This routine reads a set of integer templates from
 * File.  File must already be open and must be in the
 * correct binary format.
 * @param  fp open file to read templates from
 * @return Pointer to integer templates read from File.
 * @note Globals: none
 */
INT_TEMPLATES Classify::ReadIntTemplates(TFile *fp) {
  int i, j, w, x, y, z;
  int unicharset_size;
  int version_id = 0;
  INT_TEMPLATES Templates;
  CLASS_PRUNER_STRUCT *Pruner;
  INT_CLASS Class;
  uint8_t *Lengths;
  PROTO_SET ProtoSet;

  /* variables for conversion from older inttemp formats */
  int b, bit_number, last_cp_bit_number, new_b, new_i, new_w;
  CLASS_ID class_id, max_class_id;
  std::array<CLASS_ID, MAX_NUM_CLASSES> ClassIdFor;
  std::array<CLASS_PRUNER_STRUCT *, MAX_NUM_CLASS_PRUNERS> TempClassPruner;
  uint32_t SetBitsForMask =          // word with NUM_BITS_PER_CLASS
      (1 << NUM_BITS_PER_CLASS) - 1; // set starting at bit 0
  uint32_t Mask, NewMask, ClassBits;
  int MaxNumConfigs = MAX_NUM_CONFIGS;
  int WerdsPerConfigVec = WERDS_PER_CONFIG_VEC;

  /* first read the high level template struct */
  Templates = NewIntTemplates();
  // Read Templates in parts for 64 bit compatibility.
  if (fp->FReadEndian(&unicharset_size, sizeof(unicharset_size), 1) != 1)
    tprintf("Bad read of inttemp!\n");
  if (fp->FReadEndian(&Templates->NumClasses, sizeof(Templates->NumClasses), 1) != 1 ||
      fp->FReadEndian(&Templates->NumClassPruners, sizeof(Templates->NumClassPruners), 1) != 1)
    tprintf("Bad read of inttemp!\n");
  if (Templates->NumClasses < 0) {
    // This file has a version id!
    version_id = -Templates->NumClasses;
    if (fp->FReadEndian(&Templates->NumClasses, sizeof(Templates->NumClasses), 1) != 1)
      tprintf("Bad read of inttemp!\n");
  }

  if (version_id < 3) {
    MaxNumConfigs = OLD_MAX_NUM_CONFIGS;
    WerdsPerConfigVec = OLD_WERDS_PER_CONFIG_VEC;
  }