Checkin f5ee3042 introduces a memory leak in zipfile.c. It is still
present on trunk, tested with 0b1dbd60.

Cause: zipfileDeflate() calls deflateInit2() twice and allocates zlib
stream memory twice in certain situations.

Also, deflateEnd(&str); may not be called if aOut is not allocated after
an out of memory situation.

A test case to reproduce the memory leak follows below.

Possible fix:

static int zipfileDeflate(
  const u8 *aIn, int nIn,         /* Input */
  u8 **ppOut, int *pnOut,         /* Output */
  char **pzErr                    /* OUT: Error message */
){
  int rc = SQLITE_OK;
  sqlite3_int64 nAlloc;
  z_stream str;
  u8 *aOut;

  memset(&str, 0, sizeof(str));
  str.next_in = (Bytef*)aIn;
  str.avail_in = nIn;
  deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);

  nAlloc = deflateBound(&str, nIn);
  aOut = (u8*)sqlite3_malloc64(nAlloc);
  if( aOut==0 ){
    rc = SQLITE_NOMEM;
  }else{
    int res;
    str.next_out = aOut;
    str.avail_out = nAlloc;
    /* Remove: deflateInit2(&str, 9, Z_DEFLATED, -15, 8,
Z_DEFAULT_STRATEGY); */
    res = deflate(&str, Z_FINISH);
    if( res==Z_STREAM_END ){
      *ppOut = aOut;
      *pnOut = (int)str.total_out;
    }else{
      sqlite3_free(aOut);
      *pzErr = sqlite3_mprintf("zipfile: deflate() error");
      rc = SQLITE_ERROR;
    }
    /* Move below: deflateEnd(&str); */
  }
  deflateEnd(&str); /* Move from above. */

  return rc;
}

Ralf

----------------------------------------------

#include <stdio.h>
#include "sqlite3.h"

static void check(int r, int e) {
  if (r != e) {
    printf ("ERROR %d, expected %d\n", e, r);
  }
}

static int callback (void *user, int nCol, char **r, char **c) {
  int i;
  for (i = 0; i < nCol; i++) {
    printf("%s ", r[i]);
  }
  printf("\n");
  return 0;
}

extern int sqlite3_zipfile_init(sqlite3*,char**,const
sqlite3_api_routines*);

int main(void)
{
  sqlite3 *db, *dbRbu;
  int rc;

  remove ("test.db");
  remove ("test.zip");

  check(SQLITE_OK, sqlite3_open_v2 ("test.db", &db,
    SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL));

  check(SQLITE_OK, sqlite3_zipfile_init(db, NULL, NULL));

  check(SQLITE_OK, sqlite3_exec(db,
    "CREATE VIRTUAL TABLE temp.zz USING zipfile('test.zip');",
    callback, NULL, NULL));

  check(SQLITE_OK, sqlite3_exec(db,
    "INSERT INTO zz(name, mode, mtime, data) VALUES('h.txt'," \
    "  '-rw-r--r--', 1000000004, 'aaaaaaaaaabbbbbbbbbb'" \
    ");",
    callback, NULL, NULL));

  sqlite3_close(db);

  printf("Done - Press ENTER to exit.\n");
  getchar();

  return 0;
}
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to