#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
- dbt.data != NULL) { free(dbt.data); }
+ dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
static int makeDBError(int err);
}
else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
PyErr_SetString(PyExc_TypeError,
- "Key and Data values must be of type string or None.");
+ "Data values must be of type string or None.");
return 0;
}
return 1;
/* Recno and Queue DBs can have integer keys. This function figures out
what's been given, verifies that it's allowed, and then makes the DBT.
- Caller should call FREE_DBT(key) when done. */
+ Caller MUST call FREE_DBT(key) when done. */
static int
make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
{
CHECK_DB_NOT_CLOSED(self);
if (!make_key_dbt(self, keyobj, &key, NULL))
return NULL;
- if (!checkTxnObj(txnobj, &txn))
+ if (!checkTxnObj(txnobj, &txn)) {
+ FREE_DBT(key);
return NULL;
+ }
- if (-1 == _DB_delete(self, txn, &key, 0))
+ if (-1 == _DB_delete(self, txn, &key, 0)) {
+ FREE_DBT(key);
return NULL;
+ }
FREE_DBT(key);
RETURN_NONE();
CHECK_DB_NOT_CLOSED(self);
if (!make_key_dbt(self, keyobj, &key, &flags))
return NULL;
- if (!checkTxnObj(txnobj, &txn))
+ if (!checkTxnObj(txnobj, &txn)) {
+ FREE_DBT(key);
return NULL;
+ }
CLEAR_DBT(data);
if (CHECK_DBFLAG(self, DB_THREAD)) {
/* Tell BerkeleyDB to malloc the return value (thread safe) */
data.flags = DB_DBT_MALLOC;
}
- if (!add_partial_dbt(&data, dlen, doff))
+ if (!add_partial_dbt(&data, dlen, doff)) {
+ FREE_DBT(key);
return NULL;
+ }
MYDB_BEGIN_ALLOW_THREADS;
err = self->db->get(self->db, txn, &key, &data, flags);
data.size);
else /* return just the data */
retval = PyString_FromStringAndSize((char*)data.data, data.size);
- FREE_DBT(key);
FREE_DBT(data);
}
+ FREE_DBT(key);
RETURN_IF_ERR();
return retval;
CHECK_DB_NOT_CLOSED(self);
if (!make_key_dbt(self, keyobj, &key, &flags))
return NULL;
- if (!checkTxnObj(txnobj, &txn))
+ if (!checkTxnObj(txnobj, &txn)) {
+ FREE_DBT(key);
return NULL;
+ }
CLEAR_DBT(data);
/* We don't allocate any memory, forcing a ENOMEM error and thus
CHECK_DB_NOT_CLOSED(self);
if (!make_key_dbt(self, keyobj, &key, NULL))
return NULL;
- if (!make_dbt(dataobj, &data))
- return NULL;
- if (!checkTxnObj(txnobj, &txn))
+ if ( !make_dbt(dataobj, &data) ||
+ !checkTxnObj(txnobj, &txn) )
+ {
+ FREE_DBT(key);
return NULL;
+ }
flags |= DB_GET_BOTH;
return NULL;
CHECK_DB_NOT_CLOSED(self);
- if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL;
- if (!make_dbt(dataobj, &data)) return NULL;
- if (!add_partial_dbt(&data, dlen, doff)) return NULL;
- if (!checkTxnObj(txnobj, &txn)) return NULL;
+ if (!make_key_dbt(self, keyobj, &key, NULL))
+ return NULL;
+ if ( !make_dbt(dataobj, &data) ||
+ !add_partial_dbt(&data, dlen, doff) ||
+ !checkTxnObj(txnobj, &txn) )
+ {
+ FREE_DBT(key);
+ return NULL;
+ }
if (-1 == _DB_put(self, txn, &key, &data, flags)) {
FREE_DBT(key);
CHECK_DB_NOT_CLOSED(self);
if (!make_key_dbt(self, keyobj, &key, NULL))
return NULL;
- if (!checkTxnObj(txnobj, &txn))
+ if (!checkTxnObj(txnobj, &txn)) {
+ FREE_DBT(key);
return NULL;
+ }
/* This causes ENOMEM to be returned when the db has the key because
it has a record but can't allocate a buffer for the data. This saves
if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
return NULL;
- if (dataobj && !make_dbt(dataobj, &data))
- return NULL;
- if (!add_partial_dbt(&data, dlen, doff))
+ if ( (dataobj && !make_dbt(dataobj, &data)) ||
+ (!add_partial_dbt(&data, dlen, doff)) )
+ {
+ FREE_DBT(key);
return NULL;
+ }
if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
data.flags = DB_DBT_MALLOC;
- key.flags = DB_DBT_MALLOC;
+ if (!(key.flags & DB_DBT_REALLOC)) {
+ key.flags |= DB_DBT_MALLOC;
+ }
}
MYDB_BEGIN_ALLOW_THREADS;
err = self->dbc->c_get(self->dbc, &key, &data, flags);
MYDB_END_ALLOW_THREADS;
-
if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Py_INCREF(Py_None);
retval = Py_None;
data.data, data.size);
break;
}
- FREE_DBT(key);
FREE_DBT(data);
}
+ FREE_DBT(key);
return retval;
}
if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
return NULL;
- if (!make_dbt(dataobj, &data))
+ if (!make_dbt(dataobj, &data) ||
+ !add_partial_dbt(&data, dlen, doff) )
+ {
+ FREE_DBT(key);
return NULL;
- if (!add_partial_dbt(&data, dlen, doff)) return NULL;
+ }
MYDB_BEGIN_ALLOW_THREADS;
err = self->dbc->c_put(self->dbc, &key, &data, flags);
/* Tell BerkeleyDB to malloc the return value (thread safe) */
data.flags = DB_DBT_MALLOC;
}
- if (!add_partial_dbt(&data, dlen, doff))
+ if (!add_partial_dbt(&data, dlen, doff)) {
+ FREE_DBT(key);
return NULL;
+ }
MYDB_BEGIN_ALLOW_THREADS;
err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
data.data, data.size);
break;
}
- FREE_DBT(key);
FREE_DBT(data);
}
+ FREE_DBT(key);
return retval;
}
return NULL;
CLEAR_DBT(data);
+ if (!add_partial_dbt(&data, dlen, doff)) {
+ FREE_DBT(key);
+ return NULL;
+ }
if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
/* Tell BerkeleyDB to malloc the return value (thread safe) */
- data.flags = DB_DBT_MALLOC;
- key.flags = DB_DBT_MALLOC;
+ data.flags |= DB_DBT_MALLOC;
+ /* only BTREE databases will return anything in the key */
+ if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
+ key.flags |= DB_DBT_MALLOC;
+ }
}
- if (!add_partial_dbt(&data, dlen, doff))
- return NULL;
MYDB_BEGIN_ALLOW_THREADS;
err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
MYDB_END_ALLOW_THREADS;
data.data, data.size);
break;
}
- if (_DB_get_type(self->mydb) == DB_BTREE) {
- /* the only time a malloced key is returned is when we
- * call this on a BTree database because it performs
- * partial matching and needs to return the real key.
- * All others leave key untouched [where calling free()
- * on it would often segfault].
- */
- FREE_DBT(key);
- }
+ FREE_DBT(key);
FREE_DBT(data);
}
+ /* the only time REALLOC should be set is if we used an integer
+ * key that make_dbt_key malloc'd for us. always free these. */
+ if (key.flags & DB_DBT_REALLOC) {
+ FREE_DBT(key);
+ }
return retval;
}
/* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
return NULL;
- if (!make_dbt(dataobj, &data))
+ if (!make_dbt(dataobj, &data)) {
+ FREE_DBT(key);
return NULL;
+ }
MYDB_BEGIN_ALLOW_THREADS;
err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
/* Tell BerkeleyDB to malloc the return value (thread safe) */
data.flags = DB_DBT_MALLOC;
}
- if (!add_partial_dbt(&data, dlen, doff))
+ if (!add_partial_dbt(&data, dlen, doff)) {
+ FREE_DBT(key);
return NULL;
+ }
MYDB_BEGIN_ALLOW_THREADS;
err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
else { /* Can only be used for BTrees, so no need to return int key */
retval = Py_BuildValue("s#s#", key.data, key.size,
data.data, data.size);
- FREE_DBT(key);
FREE_DBT(data);
}
+ FREE_DBT(key);
return retval;
}