forked from GitHub/gf-core
no more space leaks
This commit is contained in:
@@ -122,12 +122,18 @@ PyList_AsPgfPrintContext(PyObject *pylist)
|
|||||||
PyErr_SetString(PyExc_TypeError, "variable argument in context must be a string");
|
PyErr_SetString(PyExc_TypeError, "variable argument in context must be a string");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PgfText *input = PyUnicode_AsPgfText(item);
|
|
||||||
|
|
||||||
// TODO a better way to copy into this->name?
|
if (PyUnicode_READY(item) != 0) {
|
||||||
PgfPrintContext *this = (PgfPrintContext *)PyMem_RawMalloc(sizeof(PgfPrintContext *) + sizeof(PgfText) + input->size + 1);
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_ssize_t size;
|
||||||
|
const char *enc = PyUnicode_AsUTF8AndSize(item, &size);
|
||||||
|
|
||||||
|
PgfPrintContext *this = (PgfPrintContext *)PyMem_RawMalloc(sizeof(PgfPrintContext) + size + 1);
|
||||||
this->next = ctxt;
|
this->next = ctxt;
|
||||||
memcpy(&this->name, input, sizeof(PgfText)+input->size+1);
|
this->name.size = size;
|
||||||
|
memcpy(&this->name.text, enc, size+1);
|
||||||
ctxt = this;
|
ctxt = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,6 +260,7 @@ lint(PgfUnmarshaller *this, size_t size, uintmax_t *v)
|
|||||||
Py_DECREF(i);
|
Py_DECREF(i);
|
||||||
i = tmp;
|
i = tmp;
|
||||||
}
|
}
|
||||||
|
Py_DECREF(intShifter);
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -326,42 +333,61 @@ match_lit(PgfMarshaller *this, PgfUnmarshaller *u, PgfLiteral lit)
|
|||||||
PyObject *pyobj = (PyObject *)lit;
|
PyObject *pyobj = (PyObject *)lit;
|
||||||
|
|
||||||
if (PyLong_Check(pyobj)) {
|
if (PyLong_Check(pyobj)) {
|
||||||
PyObject *intShifter = PyLong_FromUnsignedLong(pow(10, floor(log10(ULONG_MAX))));
|
PyObject *intShifter = PyLong_FromUnsignedLong(LINT_BASE);
|
||||||
|
|
||||||
// determine size
|
// determine size
|
||||||
size_t size = 1;
|
size_t size = 1;
|
||||||
PyObject *x = PyNumber_Absolute(PyNumber_Long(pyobj)); // make a copy, ignore sign
|
PyObject *x = PyNumber_Absolute(pyobj); // make a copy, ignore sign
|
||||||
while (PyObject_RichCompareBool(x, intShifter, Py_GE) == 1) {
|
while (PyObject_RichCompareBool(x, intShifter, Py_GE) == 1) {
|
||||||
size++;
|
size++;
|
||||||
x = PyNumber_FloorDivide(x, intShifter);
|
PyObject *tmp = PyNumber_FloorDivide(x, intShifter);
|
||||||
|
Py_DECREF(x);
|
||||||
|
x = tmp;
|
||||||
}
|
}
|
||||||
|
Py_DECREF(x);
|
||||||
|
|
||||||
// chop up into chunks, always positive
|
// chop up into chunks, always positive
|
||||||
bool isPos = PyObject_RichCompareBool(pyobj, PyLong_FromLong(0), Py_GE) == 1;
|
PyObject *zero = PyLong_FromLong(0);
|
||||||
x = PyNumber_Absolute(PyNumber_Long(pyobj)); // make a copy, ignore sign
|
bool isPos = PyObject_RichCompareBool(pyobj, zero, Py_GE) == 1;
|
||||||
|
Py_DECREF(zero);
|
||||||
|
x = PyNumber_Absolute(pyobj); // make a copy, ignore sign
|
||||||
uintmax_t *i = PyMem_RawMalloc(sizeof(uintmax_t)*size); // TODO when does this get freed?
|
uintmax_t *i = PyMem_RawMalloc(sizeof(uintmax_t)*size); // TODO when does this get freed?
|
||||||
for (int n = size-1; n > 0; n--) {
|
for (int n = size-1; n > 0; n--) {
|
||||||
PyObject *rem = PyNumber_Remainder(x, intShifter);
|
PyObject *rem = PyNumber_Remainder(x, intShifter);
|
||||||
i[n] = PyLong_AsUnsignedLong(rem);
|
i[n] = PyLong_AsUnsignedLong(rem);
|
||||||
x = PyNumber_FloorDivide(x, intShifter);
|
Py_DECREF(rem);
|
||||||
|
PyObject *tmp = PyNumber_FloorDivide(x, intShifter);
|
||||||
|
Py_DECREF(x);
|
||||||
|
x = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Py_DECREF(intShifter);
|
||||||
|
|
||||||
// first chunk, re-applying polarity
|
// first chunk, re-applying polarity
|
||||||
if (isPos)
|
if (isPos)
|
||||||
i[0] = PyLong_AsLong(x);
|
i[0] = PyLong_AsLong(x);
|
||||||
else
|
else
|
||||||
i[0] = PyLong_AsLong(PyNumber_Negative(x));
|
i[0] = -PyLong_AsLong(x);
|
||||||
|
|
||||||
|
Py_DECREF(x);
|
||||||
|
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return u->vtbl->lint(u, size, i);
|
|
||||||
|
object res = u->vtbl->lint(u, size, i);
|
||||||
|
|
||||||
|
PyMem_RawFree(i);
|
||||||
|
|
||||||
|
return res;
|
||||||
} else if (PyFloat_Check(pyobj)) {
|
} else if (PyFloat_Check(pyobj)) {
|
||||||
double d = PyFloat_AsDouble(pyobj);
|
double d = PyFloat_AsDouble(pyobj);
|
||||||
return u->vtbl->lflt(u, d);
|
return u->vtbl->lflt(u, d);
|
||||||
} else if (PyUnicode_Check(pyobj)) {
|
} else if (PyUnicode_Check(pyobj)) {
|
||||||
PgfText *t = PyUnicode_AsPgfText(pyobj);
|
PgfText *t = PyUnicode_AsPgfText(pyobj);
|
||||||
return u->vtbl->lstr(u, t);
|
object res = u->vtbl->lstr(u, t);
|
||||||
|
FreePgfText(t);
|
||||||
|
return res;
|
||||||
} else {
|
} else {
|
||||||
PyErr_SetString(PyExc_TypeError, "unable to match on literal");
|
PyErr_SetString(PyExc_TypeError, "unable to match on literal");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -376,7 +402,10 @@ match_expr(PgfMarshaller *this, PgfUnmarshaller *u, PgfExpr expr)
|
|||||||
if (PyObject_TypeCheck(pyobj, &pgf_ExprAbsType)) {
|
if (PyObject_TypeCheck(pyobj, &pgf_ExprAbsType)) {
|
||||||
ExprAbsObject *eabs = (ExprAbsObject *)expr;
|
ExprAbsObject *eabs = (ExprAbsObject *)expr;
|
||||||
long bt = eabs->bind_type == Py_True ? 0 : 1;
|
long bt = eabs->bind_type == Py_True ? 0 : 1;
|
||||||
return u->vtbl->eabs(u, bt, PyUnicode_AsPgfText(eabs->name), (PgfExpr) eabs->body);
|
PgfText *name = PyUnicode_AsPgfText(eabs->name);
|
||||||
|
object res = u->vtbl->eabs(u, bt, name, (PgfExpr) eabs->body);
|
||||||
|
FreePgfText(name);
|
||||||
|
return res;
|
||||||
} else
|
} else
|
||||||
if (PyObject_TypeCheck(pyobj, &pgf_ExprAppType)) {
|
if (PyObject_TypeCheck(pyobj, &pgf_ExprAppType)) {
|
||||||
ExprAppObject *eapp = (ExprAppObject *)expr;
|
ExprAppObject *eapp = (ExprAppObject *)expr;
|
||||||
@@ -392,7 +421,10 @@ match_expr(PgfMarshaller *this, PgfUnmarshaller *u, PgfExpr expr)
|
|||||||
} else
|
} else
|
||||||
if (PyObject_TypeCheck(pyobj, &pgf_ExprFunType)) {
|
if (PyObject_TypeCheck(pyobj, &pgf_ExprFunType)) {
|
||||||
ExprFunObject *efun = (ExprFunObject *)expr;
|
ExprFunObject *efun = (ExprFunObject *)expr;
|
||||||
return u->vtbl->efun(u, PyUnicode_AsPgfText(efun->name));
|
PgfText *name = PyUnicode_AsPgfText(efun->name);
|
||||||
|
object res = u->vtbl->efun(u, name);
|
||||||
|
FreePgfText(name);
|
||||||
|
return res;
|
||||||
} else
|
} else
|
||||||
if (PyObject_TypeCheck(pyobj, &pgf_ExprVarType)) {
|
if (PyObject_TypeCheck(pyobj, &pgf_ExprVarType)) {
|
||||||
ExprVarObject *evar = (ExprVarObject *)expr;
|
ExprVarObject *evar = (ExprVarObject *)expr;
|
||||||
@@ -442,6 +474,7 @@ match_type(PgfMarshaller *this, PgfUnmarshaller *u, PgfType ty)
|
|||||||
free(hypos[i].cid);
|
free(hypos[i].cid);
|
||||||
Py_DECREF(hypos[i].type);
|
Py_DECREF(hypos[i].type);
|
||||||
}
|
}
|
||||||
|
PyMem_Free(hypos);
|
||||||
FreePgfText(cat);
|
FreePgfText(cat);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@@ -150,6 +150,12 @@ PGF_categoryContext(PGFObject *self, PyObject *args)
|
|||||||
|
|
||||||
PyObject *contexts = PyList_FromHypos(hypos, n_hypos);
|
PyObject *contexts = PyList_FromHypos(hypos, n_hypos);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n_hypos; i++) {
|
||||||
|
free(hypos[i].cid);
|
||||||
|
Py_DECREF((PyObject *)hypos[i].type);
|
||||||
|
}
|
||||||
|
free(hypos);
|
||||||
|
|
||||||
return contexts;
|
return contexts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ PGF_checkoutBranch(PGFObject *self, PyObject *args)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pgf_free_revision(self->db, self->revision);
|
||||||
self->revision = rev;
|
self->revision = rev;
|
||||||
|
|
||||||
Py_RETURN_TRUE;
|
Py_RETURN_TRUE;
|
||||||
@@ -198,8 +199,14 @@ Transaction_createCategory(TransactionObject *self, PyObject *args)
|
|||||||
|
|
||||||
PgfExn err;
|
PgfExn err;
|
||||||
pgf_create_category(self->pgf->db, self->revision, catname, n_hypos, context, prob, &marshaller, &err);
|
pgf_create_category(self->pgf->db, self->revision, catname, n_hypos, context, prob, &marshaller, &err);
|
||||||
|
|
||||||
FreePgfText(catname);
|
FreePgfText(catname);
|
||||||
if (handleError(err) != PGF_EXN_NONE) {
|
for (Py_ssize_t i = 0; i < n_hypos; i++) {
|
||||||
|
FreePgfText(context[i].cid);
|
||||||
|
}
|
||||||
|
PyMem_Free(context);
|
||||||
|
|
||||||
|
if (handleError(err) != PGF_EXN_NONE) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user