Commit message: None
CVE: CVE-2017-18201
CWE: CWE-415
Vulnerability description: An issue was discovered in GNU libcdio before 2.0.0. There is a double free in get_cdtext_generic() in lib/driver/_cdio_generic.c.

Project: savannah

cdio_add_device_list(char **device_list[], const char *drive,
                     unsigned int *num_drives)
{
  if (NULL != drive) {
    unsigned int j;
    char real_device_1[PATH_MAX];
    char real_device_2[PATH_MAX];
    cdio_realpath(drive, real_device_1);
    /* Check if drive is already in list. */
    for (j=0; j<*num_drives; j++) {
      cdio_realpath((*device_list)[j], real_device_2);
      if (strcmp(real_device_1, real_device_2) == 0) break;
    }

    if (j==*num_drives) {
      /* Drive not in list. Add it. */
      (*num_drives)++;
      *device_list = realloc(*device_list, (*num_drives) * sizeof(char *));
      cdio_debug("Adding drive %s to list of devices", drive);
      (*device_list)[*num_drives-1] = strdup(drive);
      }

  } else {
    (*num_drives)++;
    if (*device_list) {
      *device_list = realloc(*device_list, (*num_drives) * sizeof(char *));
    } else {
      *device_list = malloc((*num_drives) * sizeof(char *));
    }
    cdio_debug("Adding NULL to end of drive list of size %d", (*num_drives)-1);
    (*device_list)[*num_drives-1] = NULL;
  }
}

Project: savannah

cdio_generic_free (void *p_user_data)
{
  generic_img_private_t *p_env = p_user_data;

  if (NULL == p_env) return;
  if (p_env->source_name) free (p_env->source_name);

  if (NULL != p_env->cdtext) {
      cdtext_destroy(p_env->cdtext);
      p_env->cdtext = NULL;
  }

  if (p_env->fd >= 0)
    close (p_env->fd);

  if (p_env->scsi_tuple != NULL)
    free (p_env->scsi_tuple);

  free (p_env);
}

Project: savannah

cdio_generic_init (void *user_data, int open_flags)
{
  generic_img_private_t *p_env = user_data;
  if (p_env->init) {
    cdio_warn ("init called more than once");
    return false;
  }

  p_env->fd = open (p_env->source_name, open_flags, 0);

  if (p_env->fd < 0)
    {
      cdio_warn ("open (%s): %s", p_env->source_name, strerror (errno));
      return false;
    }

  p_env->init = true;
  p_env->toc_init = false;
  p_env->cdtext  = NULL;
  p_env->scsi_tuple  = NULL;
  p_env->b_cdtext_error = false;
  p_env->u_joliet_level = 0;  /* Assume no Joliet extensions initally */
  return true;
}

Project: savannah

cdio_generic_lseek (void *user_data, off_t offset, int whence)
{
  generic_img_private_t *p_env = user_data;
  return CDIO_LSEEK(p_env->fd, offset, whence);
}

Project: savannah

cdio_generic_read_form1_sector (void * user_data, void *data, lsn_t lsn)
{
  if (0 > cdio_generic_lseek(user_data, CDIO_CD_FRAMESIZE*lsn, SEEK_SET))
    return DRIVER_OP_ERROR;
  return cdio_generic_read(user_data, data, CDIO_CD_FRAMESIZE);
}

Project: savannah

cdio_generic_stdio_free (void *p_user_data)
{
  generic_img_private_t *p_env = p_user_data;

  if (NULL == p_env) return;
  if (NULL != p_env->source_name)
    free (p_env->source_name);

  if (p_env->data_source)
    cdio_stdio_destroy (p_env->data_source);
}

Project: savannah

cdio_generic_unimplemented_set_blocksize (void *p_user_data,
                                          uint16_t i_blocksize) {
  /* Sort of a stub here. Perhaps log a message? */
  return DRIVER_OP_UNSUPPORTED;
}

Project: savannah

cdio_generic_unimplemented_set_speed (void *p_user_data, int i_speed) {
  /* Sort of a stub here. Perhaps log a message? */
  return DRIVER_OP_UNSUPPORTED;
}

Project: savannah

cdio_is_device_generic(const char *source_name)
{
  struct stat buf;
  if (0 != stat(source_name, &buf)) {
    cdio_warn ("Can't get file status for %s:\n%s", source_name,
                strerror(errno));
    return false;
  }
  return (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode));
}

Project: savannah

cdio_is_device_quiet_generic(const char *source_name)
{
  struct stat buf;
  if (0 != stat(source_name, &buf)) {
    return false;
  }
  return (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode));
}