1
0
forked from GitHub/gf-core

no more space leaks

This commit is contained in:
krangelov
2021-09-28 11:13:45 +02:00
parent 67f83ebf8a
commit fcad8dd3e2
3 changed files with 62 additions and 16 deletions

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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;
} }