Skip to content

Commit

Permalink
Fixed refcount handling in encrypt_password
Browse files Browse the repository at this point in the history
Added tests to check bad types, which discovered the above problem: on
type error we would have decref'd on exit something that was only
borrowed (because we wouldn't have performed matching increfs).
  • Loading branch information
dvarrazzo committed May 20, 2018
1 parent abca14d commit 9cf658e
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
17 changes: 8 additions & 9 deletions psycopg/psycopgmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,16 +418,20 @@ psyco_encrypt_password(PyObject *self, PyObject *args, PyObject *kwargs)
PyObject *password = NULL, *user = NULL;
PyObject *scope = Py_None, *algorithm = Py_None;
PyObject *res = NULL;
connectionObject *conn = NULL;

static char *kwlist[] = {"password", "user", "scope", "algorithm", NULL};

connectionObject *conn = NULL;

if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|OO", kwlist,
&password, &user, &scope, &algorithm)) {
return NULL;
}

/* for ensure_bytes */
Py_INCREF(user);
Py_INCREF(password);
Py_INCREF(algorithm);

if (scope != Py_None) {
if (PyObject_TypeCheck(scope, &cursorType)) {
conn = ((cursorObject*)scope)->conn;
Expand All @@ -437,16 +441,11 @@ psyco_encrypt_password(PyObject *self, PyObject *args, PyObject *kwargs)
}
else {
PyErr_SetString(PyExc_TypeError,
"the scope must be a connection or a cursor");
"the scope must be a connection or a cursor");
goto exit;
}
}

/* for ensure_bytes */
Py_INCREF(user);
Py_INCREF(password);
Py_INCREF(algorithm);

if (!(user = psycopg_ensure_bytes(user))) { goto exit; }
if (!(password = psycopg_ensure_bytes(password))) { goto exit; }
if (algorithm != Py_None) {
Expand All @@ -473,7 +472,7 @@ psyco_encrypt_password(PyObject *self, PyObject *args, PyObject *kwargs)
goto exit;
}

/* TODO: algo = will block: forbid on async/green conn? */
/* TODO: algo = None will block: forbid on async/green conn? */
encrypted = PQencryptPasswordConn(conn->pgconn,
Bytes_AS_STRING(password), Bytes_AS_STRING(user),
algorithm != Py_None ? Bytes_AS_STRING(algorithm) : NULL);
Expand Down
11 changes: 11 additions & 0 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1482,6 +1482,17 @@ def test_encrypt_scram(self):
password='psycopg2', user='ashesh',
scope=self.conn, algorithm='scram-sha-256')

def test_bad_types(self):
self.assertRaises(TypeError, ext.encrypt_password)
self.assertRaises(TypeError, ext.encrypt_password,
'password', 42, self.conn, 'md5')
self.assertRaises(TypeError, ext.encrypt_password,
42, 'user', self.conn, 'md5')
self.assertRaises(TypeError, ext.encrypt_password,
42, 'user', 'wat', 'abc')
self.assertRaises(TypeError, ext.encrypt_password,
'password', 'user', 'wat', 42)


class AutocommitTests(ConnectingTestCase):
def test_closed(self):
Expand Down

0 comments on commit 9cf658e

Please sign in to comment.