I did a very quick review of the C code here (branched from debianlp:subvertpy
on Launchpad, so should be the sid package), and found a number of
questionable things.  I don't know the library code or the svn API very well,
so it's entirely possible that some or all of these are false alarms.  It's
also possible I missed some things.  I list them here because they made me go
"hmm" and I think they're worth a second look.

Most issues I think are not that serious, e.g. leaking a refcount in a rare
error condition, either by not decref'ing an object in a short-circuit exit,
or not checking return values for Python API calls.  I'll list these farther
down.  The most serious issue appears to be in util.c in
config_hash_from_object().

Potentially serious:

Notice how when config is a dictionary, you set `dict = config` but when it's
not, you PyObject_GetAttrString() the config's __dict__.  This sets up a
situation where outside this conditional, you are inconsistent with dict's
refcount.  The if-clause has one lower reference than the else-clause because
PyObject_GetAttrString returns a new reference.  Thus it's possible that
PyDict_Check and PyDict_Next are operating on an object for which the client
doesn't hold sufficient references.  You're also leaking dict when you've gone
through the else-clause.  Suggestion: incref dict in the if-clause and add a
decref of dict before the return at the end of the function.

client.c:318 client_set_notify_funct() where notify_baton2 has inconsistent
refcounting between the if-clause and else-clause.  When you go through the
if-clause, notify_baton2 steals a reference to Py_None, which is going to get
decref'd in client_dealloc().  The Py_XDECREF there does not protect you from
the extra decref of Py_None!  You can see that if you go through the
else-clause, func will get incref'd, but if you go through the if-clause, you
actually leak func!  Suggestion: incref notify_baton2 instead of func.

client_proplist, inside the props->nelts loop, the PyList_Append return value
is not checked.  Not likely to fail, but more seriously, `value` is leaked.
Py_BuildValue returns a new reference, but PyList_Append does not steal its
reference.  Thus you leak every `value`.

editor.c:58, new_editor_object: you (probably, haven't checked the call-sites)
need to incref commit_callback, since it gets decref'd in py_editor_dealloc.
Looks like the refcounts are unmatched.

Other problems:

* wrap_py_commit_items(): leaks ret when the PyList_SetItem returns on line
  118.
* client.c:145: PyList_Append return value unchecked, probably harmless though
  a (void) should be added.
* client.c:167: similar for PyDict_SetItemString
* client.c:256: py_cancel_check should be incref'd?
* client.c, multiple locations: PyArg_Parse* does not incref 'O' arguments, so
  be careful about calling back into Python with any such parsed object.  You
  need to ensure your library increfs such objects before a potential call
  back into Python, and then decrefs it when you're done with the Python
  call.  I haven't audited all the places this happens, so this could be a
  false alarm (i.e. you don't call back into Python).
* client.c:925: prop_list leaks in the error condition return
* client.c:1037: leaks ret when PyList_SetItem returns non-zero.
* client.c:1086: leaks entry_dict in the error return path
* client.c:1251: PyList_SetItem return value not checked
* client.c:1279: PyDict_SetItemString return value not checked
* client.c:1473: leaks `data` when data->pool is NULL.

I'm still reviewing the code, so if I find anything else I'll send a follow up.

Cheers,
-Barry

Attachment: signature.asc
Description: PGP signature

Reply via email to