view open.cpp @ 411:ad2206c24986 api-inversion

Fix a memory corruption bug. When allocating the adb_t in audiodb_open(), zero the memory; then we're not going to try to free() or delete some arbitrary uninitialized thing if the thing that we're opening turns out not to be an audiodb database.
author mas01cr
date Thu, 11 Dec 2008 08:54:06 +0000
parents 58b88ab69424
children 2d14d21f826b
line wrap: on
line source
#include "audioDB.h"
extern "C" {
#include "audioDB_API.h"
#include "audioDB-internals.h"
}

static bool audiodb_check_header(adb_header_t *header) {
  /* FIXME: use syslog() or write to stderr or something to give the
     poor user some diagnostics. */
  if(header->magic == O2_OLD_MAGIC) {
    return false;
  }
  if(header->magic != O2_MAGIC) {
    return false;
  }
  if(header->version != O2_FORMAT_VERSION) {
    return false;
  }
  if(header->headerSize != O2_HEADERSIZE) {
    return false;
  }
  return true;
}

static int audiodb_collect_keys(adb_t *adb) {
  char *key_table = 0;
  size_t key_table_length = 0;

  if(adb->header->length > 0) {
    unsigned nfiles = adb->header->numFiles;
    key_table_length = ALIGN_PAGE_UP(nfiles * O2_FILETABLE_ENTRY_SIZE);
    mmap_or_goto_error(char *, key_table, adb->header->fileTableOffset, key_table_length);
    for (unsigned i = 0; i < nfiles; i++) {
      adb->keys->insert(key_table + i*O2_FILETABLE_ENTRY_SIZE);
    }
    munmap(key_table, key_table_length);
  }

  return 0;

 error:
  maybe_munmap(key_table, key_table_length);
  return 1;
}

adb_t *audiodb_open(const char *path, int flags) {
  adb_t *adb = 0;
  int fd = -1;

  flags &= (O_RDONLY|O_RDWR);
  fd = open(path, flags);
  if(fd == -1) {
    goto error;
  }
  if(acquire_lock(fd, flags == O_RDWR)) {
    goto error;
  }

  adb = (adb_t *) calloc(1, sizeof(adb_t));
  if(!adb) {
    goto error;
  }
  adb->fd = fd;
  adb->flags = flags;
  adb->path = (char *) malloc(1+strlen(path));
  if(!(adb->path)) {
    goto error;
  }
  strcpy(adb->path, path);

  adb->header = (adb_header_t *) malloc(sizeof(adb_header_t));
  if(!(adb->header)) {
    goto error;
  }
  if(read(fd, (char *) adb->header, O2_HEADERSIZE) != O2_HEADERSIZE) {
    goto error;
  }
  if(!audiodb_check_header(adb->header)) {
    goto error;
  }

  adb->keys = new std::set<std::string>;
  if(!adb->keys) {
    goto error;
  }
  if(audiodb_collect_keys(adb)) {
    goto error;
  }
  return adb;

 error:
  if(adb) {
    if(adb->header) {
      free(adb->header);
    }
    if(adb->path) {
      free(adb->path);
    }
    if(adb->keys) {
      delete adb->keys;
    }
    free(adb);
  }
  if(fd != -1) {
    close(fd);
  }
  return NULL;
}