Skip to content

Commit 756442e

Browse files
Added checks on passing invalid parameters to cursor.var(),
cursor.arrayvar(), cursor.callfunc() and cursor.setinputsizes().
1 parent f7a9eae commit 756442e

3 files changed

Lines changed: 62 additions & 25 deletions

File tree

src/cxoCursor.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,13 +1711,15 @@ static PyObject *cxoCursor_scroll(cxoCursor *cursor, PyObject *args,
17111711
static PyObject *cxoCursor_setInputSizes(cxoCursor *cursor, PyObject *args,
17121712
PyObject *keywordArgs)
17131713
{
1714-
Py_ssize_t numPositionalArgs, i;
1714+
Py_ssize_t numPositionalArgs, numKeywordArgs = 0, i;
17151715
PyObject *key, *value;
17161716
cxoVar *var;
17171717

17181718
// only expect keyword arguments or positional arguments, not both
17191719
numPositionalArgs = PyTuple_Size(args);
1720-
if (keywordArgs && numPositionalArgs > 0)
1720+
if (keywordArgs)
1721+
numKeywordArgs = PyDict_Size(keywordArgs);
1722+
if (numKeywordArgs > 0 && numPositionalArgs > 0)
17211723
return cxoError_raiseFromString(cxoInterfaceErrorException,
17221724
"expecting arguments or keyword arguments, not both");
17231725

@@ -1727,15 +1729,15 @@ static PyObject *cxoCursor_setInputSizes(cxoCursor *cursor, PyObject *args,
17271729

17281730
// eliminate existing bind variables
17291731
Py_CLEAR(cursor->bindVariables);
1730-
if (keywordArgs)
1732+
if (numKeywordArgs > 0)
17311733
cursor->bindVariables = PyDict_New();
17321734
else cursor->bindVariables = PyList_New(numPositionalArgs);
17331735
if (!cursor->bindVariables)
17341736
return NULL;
17351737
cursor->setInputSizes = 1;
17361738

17371739
// process each input
1738-
if (keywordArgs) {
1740+
if (numKeywordArgs > 0) {
17391741
i = 0;
17401742
while (PyDict_Next(keywordArgs, &i, &key, &value)) {
17411743
var = cxoVar_newByType(cursor, value, cursor->bindArraySize);
@@ -1803,9 +1805,9 @@ static PyObject *cxoCursor_var(cxoCursor *cursor, PyObject *args,
18031805
size = 0;
18041806
arraySize = cursor->bindArraySize;
18051807
inConverter = outConverter = typeNameObj = NULL;
1806-
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O|iiOOO", keywordList,
1807-
&type, &size, &arraySize, &inConverter, &outConverter,
1808-
&typeNameObj))
1808+
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O!|iiOOO",
1809+
keywordList, &PyType_Type, &type, &size, &arraySize, &inConverter,
1810+
&outConverter, &typeNameObj))
18091811
return NULL;
18101812

18111813
// determine the type of variable
@@ -1847,7 +1849,7 @@ static PyObject *cxoCursor_arrayVar(cxoCursor *cursor, PyObject *args)
18471849

18481850
// parse arguments
18491851
size = 0;
1850-
if (!PyArg_ParseTuple(args, "OO|i", &type, &value, &size))
1852+
if (!PyArg_ParseTuple(args, "O!O|i", &PyType_Type, &type, &value, &size))
18511853
return NULL;
18521854

18531855
// determine the type of variable

src/cxoVar.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -293,25 +293,28 @@ static cxoVar *cxoVar_newArrayByType(cxoCursor *cursor,
293293
PyObject *typeObj, *numElementsObj;
294294
cxoVarType *varType;
295295
uint32_t numElements;
296+
int ok;
296297

297-
if (PyList_GET_SIZE(value) != 2) {
298-
cxoError_raiseFromString(cxoProgrammingErrorException,
299-
"expecting an array of two elements [type, numelems]");
300-
return NULL;
298+
// validate parameters
299+
ok = (PyList_GET_SIZE(value) == 2);
300+
if (ok) {
301+
typeObj = PyList_GET_ITEM(value, 0);
302+
ok = PyType_Check(typeObj);
301303
}
302-
303-
typeObj = PyList_GET_ITEM(value, 0);
304-
numElementsObj = PyList_GET_ITEM(value, 1);
305-
if (!PyInt_Check(numElementsObj)) {
304+
if (ok) {
305+
numElementsObj = PyList_GET_ITEM(value, 1);
306+
ok = PyInt_Check(numElementsObj);
307+
}
308+
if (!ok) {
306309
cxoError_raiseFromString(cxoProgrammingErrorException,
307-
"number of elements must be an integer");
310+
"expecting an array of two elements [type, numelems]");
308311
return NULL;
309312
}
310313

314+
// create variable
311315
varType = cxoVarType_fromPythonType((PyTypeObject*) typeObj);
312316
if (!varType)
313317
return NULL;
314-
315318
numElements = PyInt_AsLong(numElementsObj);
316319
if (PyErr_Occurred())
317320
return NULL;
@@ -349,10 +352,16 @@ cxoVar *cxoVar_newByType(cxoCursor *cursor, PyObject *value,
349352
}
350353

351354
// everything else ought to be a Python type
352-
varType = cxoVarType_fromPythonType((PyTypeObject*) value);
353-
if (!varType)
354-
return NULL;
355-
return cxoVar_new(cursor, numElements, varType, varType->size, 0, NULL);
355+
if (PyType_Check(value)) {
356+
varType = cxoVarType_fromPythonType((PyTypeObject*) value);
357+
if (!varType)
358+
return NULL;
359+
return cxoVar_new(cursor, numElements, varType, varType->size, 0,
360+
NULL);
361+
}
362+
363+
PyErr_SetString(PyExc_TypeError, "expecting type");
364+
return NULL;
356365
}
357366

358367

test/Cursor.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,22 @@ def testCallFuncNoArgs(self):
100100
results = self.cursor.callfunc("func_TestNoArgs", cx_Oracle.NUMBER)
101101
self.assertEqual(results, 712)
102102

103+
def testCallFuncNegative(self):
104+
"""test executing a stored function with wrong parameters"""
105+
funcName = "func_Test"
106+
self.assertRaises(TypeError, self.cursor.callfunc, cx_Oracle.NUMBER,
107+
funcName, ("hi", 5))
108+
self.assertRaises(cx_Oracle.DatabaseError, self.cursor.callfunc,
109+
funcName, cx_Oracle.NUMBER, ("hi", 5, 7))
110+
self.assertRaises(TypeError, self.cursor.callfunc, funcName,
111+
cx_Oracle.NUMBER, "hi", 7)
112+
self.assertRaises(cx_Oracle.DatabaseError, self.cursor.callfunc,
113+
funcName, cx_Oracle.NUMBER, [5, "hi"])
114+
self.assertRaises(cx_Oracle.DatabaseError, self.cursor.callfunc,
115+
funcName, cx_Oracle.NUMBER)
116+
self.assertRaises(TypeError, self.cursor.callfunc, funcName,
117+
cx_Oracle.NUMBER, 5)
118+
103119
def testExecuteManyByName(self):
104120
"""test executing a statement multiple times (named args)"""
105121
self.cursor.execute("truncate table TestTempTable")
@@ -486,10 +502,12 @@ def testScrollDifferingArrayAndFetchSizes(self):
486502
self.assertEqual(cursor.rowcount,
487503
15 + numRows + numRowsFetched + numRows - 6)
488504

489-
def testSetInputSizesMultipleMethod(self):
490-
"""test setting input sizes with both positional and keyword args"""
505+
def testSetInputSizesNegative(self):
506+
"test cursor.setinputsizes() with invalid parameters"
507+
val = decimal.Decimal(5)
491508
self.assertRaises(cx_Oracle.InterfaceError,
492-
self.cursor.setinputsizes, 5, x = 5)
509+
self.cursor.setinputsizes, val, x = val)
510+
self.assertRaises(TypeError, self.cursor.setinputsizes, val)
493511

494512
def testSetInputSizesByPosition(self):
495513
"""test setting input sizes with positional args"""
@@ -523,3 +541,11 @@ def testParse(self):
523541
self.assertEqual(self.cursor.description,
524542
[ ('LONGINTCOL', cx_Oracle.NUMBER, 17, None, 16, 0, 0) ])
525543

544+
def testVarNegative(self):
545+
"test cursor.var() with invalid parameters"
546+
self.assertRaises(TypeError, self.cursor.var, 5)
547+
548+
def testArrayVarNegative(self):
549+
"test cursor.arrayvar() with invalid parameters"
550+
self.assertRaises(TypeError, self.cursor.arrayvar, 5, 1)
551+

0 commit comments

Comments
 (0)