Skip to content

Commit 511cd7a

Browse files
Correct parsing of connect string so that the last @ symbol is searched for
instead of the first @ symbol; otherwise, passwords containing an @ symbol will result in the incorrect DSN being extracted (#290).
1 parent c94d999 commit 511cd7a

File tree

4 files changed

+24
-6
lines changed

4 files changed

+24
-6
lines changed

doc/src/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
# The short X.Y version.
4343
version = '7.1'
4444
# The full version, including alpha/beta/rc tags.
45-
release = '7.1.2'
45+
release = '7.1.3'
4646

4747
# There are two options for replacing |today|: either, you set today to some
4848
# non-false value, then it is used:

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from distutils.extension import Extension
2121

2222
# define build constants
23-
BUILD_VERSION = "7.1.2"
23+
BUILD_VERSION = "7.1.3"
2424

2525
# setup extra link and compile args
2626
extraLinkArgs = []

src/cxoConnection.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -643,14 +643,16 @@ static PyObject *cxoConnection_new(PyTypeObject *type, PyObject *args,
643643
// string in to the target.
644644
//-----------------------------------------------------------------------------
645645
static int cxoConnection_splitComponent(PyObject **sourceObj,
646-
PyObject **targetObj, const char *splitString)
646+
PyObject **targetObj, const char *splitString, int first)
647647
{
648648
PyObject *temp, *posObj;
649649
Py_ssize_t size, pos;
650+
char *methodName;
650651

651652
if (!*sourceObj || *targetObj)
652653
return 0;
653-
posObj = PyObject_CallMethod(*sourceObj, "find", "s", splitString);
654+
methodName = (first) ? "find" : "rfind";
655+
posObj = PyObject_CallMethod(*sourceObj, methodName, "s", splitString);
654656
if (!posObj)
655657
return -1;
656658
pos = PyInt_AsLong(posObj);
@@ -742,9 +744,9 @@ static int cxoConnection_init(cxoConnection *conn, PyObject *args,
742744
conn->dsn = dsnObj;
743745

744746
// perform some parsing, if necessary
745-
if (cxoConnection_splitComponent(&conn->username, &passwordObj, "/") < 0)
747+
if (cxoConnection_splitComponent(&conn->username, &passwordObj, "/", 1) < 0)
746748
return -1;
747-
if (cxoConnection_splitComponent(&passwordObj, &conn->dsn, "@") < 0)
749+
if (cxoConnection_splitComponent(&passwordObj, &conn->dsn, "@", 0) < 0)
748750
return -1;
749751

750752
// setup parameters

test/Connection.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,22 @@ def testChangePasswordNegative(self):
144144
self.assertRaises(cx_Oracle.DatabaseError, connection.changepassword,
145145
TestEnv.GetMainPassword(), newPassword)
146146

147+
def testParsePassword(self):
148+
"test connecting with password containing / and @ symbols"
149+
sysRandom = random.SystemRandom()
150+
chars = list(sysRandom.choice(string.ascii_letters) for i in range(20))
151+
chars[4] = "/"
152+
chars[8] = "@"
153+
newPassword = "".join(chars)
154+
connection = TestEnv.GetConnection()
155+
connection.changepassword(TestEnv.GetMainPassword(), newPassword)
156+
try:
157+
arg = "%s/%s@%s" % (TestEnv.GetMainUser(), newPassword,
158+
TestEnv.GetConnectString())
159+
cx_Oracle.connect(arg)
160+
finally:
161+
connection.changepassword(newPassword, TestEnv.GetMainPassword())
162+
147163
def testEncodings(self):
148164
"connection with only encoding or nencoding specified should work"
149165
connection = cx_Oracle.connect(TestEnv.GetMainUser(),

0 commit comments

Comments
 (0)