Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2efdc90

Browse files
Issue #17073: Fix some integer overflows in sqlite3 module.
2 parents 03ee12e + 3cf96ac commit 2efdc90

8 files changed

Lines changed: 196 additions & 61 deletions

File tree

Lib/sqlite3/test/hooks.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,25 @@ def mycoll(x, y):
7676
except sqlite.OperationalError as e:
7777
self.assertEqual(e.args[0].lower(), "no such collation sequence: mycoll")
7878

79+
def CheckCollationReturnsLargeInteger(self):
80+
def mycoll(x, y):
81+
# reverse order
82+
return -((x > y) - (x < y)) * 2**32
83+
con = sqlite.connect(":memory:")
84+
con.create_collation("mycoll", mycoll)
85+
sql = """
86+
select x from (
87+
select 'a' as x
88+
union
89+
select 'b' as x
90+
union
91+
select 'c' as x
92+
) order by x collate mycoll
93+
"""
94+
result = con.execute(sql).fetchall()
95+
self.assertEqual(result, [('c',), ('b',), ('a',)],
96+
msg="the expected order was not returned")
97+
7998
def CheckCollationRegisterTwice(self):
8099
"""
81100
Register two different collation functions under the same name.

Lib/sqlite3/test/userfunctions.py

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -375,14 +375,15 @@ def CheckAggrCheckAggrSum(self):
375375
val = cur.fetchone()[0]
376376
self.assertEqual(val, 60)
377377

378-
def authorizer_cb(action, arg1, arg2, dbname, source):
379-
if action != sqlite.SQLITE_SELECT:
380-
return sqlite.SQLITE_DENY
381-
if arg2 == 'c2' or arg1 == 't2':
382-
return sqlite.SQLITE_DENY
383-
return sqlite.SQLITE_OK
384-
385378
class AuthorizerTests(unittest.TestCase):
379+
@staticmethod
380+
def authorizer_cb(action, arg1, arg2, dbname, source):
381+
if action != sqlite.SQLITE_SELECT:
382+
return sqlite.SQLITE_DENY
383+
if arg2 == 'c2' or arg1 == 't2':
384+
return sqlite.SQLITE_DENY
385+
return sqlite.SQLITE_OK
386+
386387
def setUp(self):
387388
self.con = sqlite.connect(":memory:")
388389
self.con.executescript("""
@@ -395,12 +396,12 @@ def setUp(self):
395396
# For our security test:
396397
self.con.execute("select c2 from t2")
397398

398-
self.con.set_authorizer(authorizer_cb)
399+
self.con.set_authorizer(self.authorizer_cb)
399400

400401
def tearDown(self):
401402
pass
402403

403-
def CheckTableAccess(self):
404+
def test_table_access(self):
404405
try:
405406
self.con.execute("select * from t2")
406407
except sqlite.DatabaseError as e:
@@ -409,7 +410,7 @@ def CheckTableAccess(self):
409410
return
410411
self.fail("should have raised an exception due to missing privileges")
411412

412-
def CheckColumnAccess(self):
413+
def test_column_access(self):
413414
try:
414415
self.con.execute("select c2 from t1")
415416
except sqlite.DatabaseError as e:
@@ -418,11 +419,46 @@ def CheckColumnAccess(self):
418419
return
419420
self.fail("should have raised an exception due to missing privileges")
420421

422+
class AuthorizerRaiseExceptionTests(AuthorizerTests):
423+
@staticmethod
424+
def authorizer_cb(action, arg1, arg2, dbname, source):
425+
if action != sqlite.SQLITE_SELECT:
426+
raise ValueError
427+
if arg2 == 'c2' or arg1 == 't2':
428+
raise ValueError
429+
return sqlite.SQLITE_OK
430+
431+
class AuthorizerIllegalTypeTests(AuthorizerTests):
432+
@staticmethod
433+
def authorizer_cb(action, arg1, arg2, dbname, source):
434+
if action != sqlite.SQLITE_SELECT:
435+
return 0.0
436+
if arg2 == 'c2' or arg1 == 't2':
437+
return 0.0
438+
return sqlite.SQLITE_OK
439+
440+
class AuthorizerLargeIntegerTests(AuthorizerTests):
441+
@staticmethod
442+
def authorizer_cb(action, arg1, arg2, dbname, source):
443+
if action != sqlite.SQLITE_SELECT:
444+
return 2**32
445+
if arg2 == 'c2' or arg1 == 't2':
446+
return 2**32
447+
return sqlite.SQLITE_OK
448+
449+
421450
def suite():
422451
function_suite = unittest.makeSuite(FunctionTests, "Check")
423452
aggregate_suite = unittest.makeSuite(AggregateTests, "Check")
424-
authorizer_suite = unittest.makeSuite(AuthorizerTests, "Check")
425-
return unittest.TestSuite((function_suite, aggregate_suite, authorizer_suite))
453+
authorizer_suite = unittest.makeSuite(AuthorizerTests)
454+
return unittest.TestSuite((
455+
function_suite,
456+
aggregate_suite,
457+
authorizer_suite,
458+
unittest.makeSuite(AuthorizerRaiseExceptionTests),
459+
unittest.makeSuite(AuthorizerIllegalTypeTests),
460+
unittest.makeSuite(AuthorizerLargeIntegerTests),
461+
))
426462

427463
def test():
428464
runner = unittest.TextTestRunner()

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ Core and Builtins
166166
Library
167167
-------
168168

169+
- Issue #17073: Fix some integer overflows in sqlite3 module.
170+
169171
- Issue #17114: IDLE now uses non-strict config parser.
170172

171173
- Issue #16723: httplib.HTTPResponse no longer marked closed when the connection

Modules/_sqlite/connection.c

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -482,32 +482,35 @@ PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args
482482
}
483483
}
484484

485-
void _pysqlite_set_result(sqlite3_context* context, PyObject* py_val)
485+
static int
486+
_pysqlite_set_result(sqlite3_context* context, PyObject* py_val)
486487
{
487-
const char* buffer;
488-
Py_ssize_t buflen;
489-
490-
if ((!py_val) || PyErr_Occurred()) {
491-
sqlite3_result_null(context);
492-
} else if (py_val == Py_None) {
488+
if (py_val == Py_None) {
493489
sqlite3_result_null(context);
494490
} else if (PyLong_Check(py_val)) {
495-
sqlite3_result_int64(context, PyLong_AsLongLong(py_val));
491+
sqlite_int64 value = _pysqlite_long_as_int64(py_val);
492+
if (value == -1 && PyErr_Occurred())
493+
return -1;
494+
sqlite3_result_int64(context, value);
496495
} else if (PyFloat_Check(py_val)) {
497496
sqlite3_result_double(context, PyFloat_AsDouble(py_val));
498497
} else if (PyUnicode_Check(py_val)) {
499-
char *str = _PyUnicode_AsString(py_val);
500-
if (str != NULL)
501-
sqlite3_result_text(context, str, -1, SQLITE_TRANSIENT);
498+
const char *str = _PyUnicode_AsString(py_val);
499+
if (str == NULL)
500+
return -1;
501+
sqlite3_result_text(context, str, -1, SQLITE_TRANSIENT);
502502
} else if (PyObject_CheckBuffer(py_val)) {
503+
const char* buffer;
504+
Py_ssize_t buflen;
503505
if (PyObject_AsCharBuffer(py_val, &buffer, &buflen) != 0) {
504506
PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer");
505-
} else {
506-
sqlite3_result_blob(context, buffer, buflen, SQLITE_TRANSIENT);
507+
return -1;
507508
}
509+
sqlite3_result_blob(context, buffer, buflen, SQLITE_TRANSIENT);
508510
} else {
509-
/* TODO: raise error */
511+
return -1;
510512
}
513+
return 0;
511514
}
512515

513516
PyObject* _pysqlite_build_py_params(sqlite3_context *context, int argc, sqlite3_value** argv)
@@ -528,7 +531,7 @@ PyObject* _pysqlite_build_py_params(sqlite3_context *context, int argc, sqlite3_
528531
cur_value = argv[i];
529532
switch (sqlite3_value_type(argv[i])) {
530533
case SQLITE_INTEGER:
531-
cur_py_value = PyLong_FromLongLong(sqlite3_value_int64(cur_value));
534+
cur_py_value = _pysqlite_long_from_int64(sqlite3_value_int64(cur_value));
532535
break;
533536
case SQLITE_FLOAT:
534537
cur_py_value = PyFloat_FromDouble(sqlite3_value_double(cur_value));
@@ -571,6 +574,7 @@ void _pysqlite_func_callback(sqlite3_context* context, int argc, sqlite3_value**
571574
PyObject* args;
572575
PyObject* py_func;
573576
PyObject* py_retval = NULL;
577+
int ok;
574578

575579
#ifdef WITH_THREAD
576580
PyGILState_STATE threadstate;
@@ -586,10 +590,12 @@ void _pysqlite_func_callback(sqlite3_context* context, int argc, sqlite3_value**
586590
Py_DECREF(args);
587591
}
588592

593+
ok = 0;
589594
if (py_retval) {
590-
_pysqlite_set_result(context, py_retval);
595+
ok = _pysqlite_set_result(context, py_retval) == 0;
591596
Py_DECREF(py_retval);
592-
} else {
597+
}
598+
if (!ok) {
593599
if (_enable_callback_tracebacks) {
594600
PyErr_Print();
595601
} else {
@@ -669,9 +675,10 @@ static void _pysqlite_step_callback(sqlite3_context *context, int argc, sqlite3_
669675

670676
void _pysqlite_final_callback(sqlite3_context* context)
671677
{
672-
PyObject* function_result = NULL;
678+
PyObject* function_result;
673679
PyObject** aggregate_instance;
674680
_Py_IDENTIFIER(finalize);
681+
int ok;
675682

676683
#ifdef WITH_THREAD
677684
PyGILState_STATE threadstate;
@@ -688,21 +695,23 @@ void _pysqlite_final_callback(sqlite3_context* context)
688695
}
689696

690697
function_result = _PyObject_CallMethodId(*aggregate_instance, &PyId_finalize, "");
691-
if (!function_result) {
698+
Py_DECREF(*aggregate_instance);
699+
700+
ok = 0;
701+
if (function_result) {
702+
ok = _pysqlite_set_result(context, function_result) == 0;
703+
Py_DECREF(function_result);
704+
}
705+
if (!ok) {
692706
if (_enable_callback_tracebacks) {
693707
PyErr_Print();
694708
} else {
695709
PyErr_Clear();
696710
}
697711
_sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1);
698-
} else {
699-
_pysqlite_set_result(context, function_result);
700712
}
701713

702714
error:
703-
Py_XDECREF(*aggregate_instance);
704-
Py_XDECREF(function_result);
705-
706715
#ifdef WITH_THREAD
707716
PyGILState_Release(threadstate);
708717
#endif
@@ -859,7 +868,9 @@ static int _authorizer_callback(void* user_arg, int action, const char* arg1, co
859868
rc = SQLITE_DENY;
860869
} else {
861870
if (PyLong_Check(ret)) {
862-
rc = (int)PyLong_AsLong(ret);
871+
rc = _PyLong_AsInt(ret);
872+
if (rc == -1 && PyErr_Occurred())
873+
rc = SQLITE_DENY;
863874
} else {
864875
rc = SQLITE_DENY;
865876
}
@@ -1327,6 +1338,7 @@ pysqlite_collation_callback(
13271338
PyGILState_STATE gilstate;
13281339
#endif
13291340
PyObject* retval = NULL;
1341+
long longval;
13301342
int result = 0;
13311343
#ifdef WITH_THREAD
13321344
gilstate = PyGILState_Ensure();
@@ -1350,10 +1362,17 @@ pysqlite_collation_callback(
13501362
goto finally;
13511363
}
13521364

1353-
result = PyLong_AsLong(retval);
1354-
if (PyErr_Occurred()) {
1365+
longval = PyLong_AsLongAndOverflow(retval, &result);
1366+
if (longval == -1 && PyErr_Occurred()) {
1367+
PyErr_Clear();
13551368
result = 0;
13561369
}
1370+
else if (!result) {
1371+
if (longval > 0)
1372+
result = 1;
1373+
else if (longval < 0)
1374+
result = -1;
1375+
}
13571376

13581377
finally:
13591378
Py_XDECREF(string1);

Modules/_sqlite/cursor.c

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,6 @@
2626
#include "util.h"
2727
#include "sqlitecompat.h"
2828

29-
/* used to decide wether to call PyLong_FromLong or PyLong_FromLongLong */
30-
#ifndef INT32_MIN
31-
#define INT32_MIN (-2147483647 - 1)
32-
#endif
33-
#ifndef INT32_MAX
34-
#define INT32_MAX 2147483647
35-
#endif
36-
3729
PyObject* pysqlite_cursor_iternext(pysqlite_Cursor* self);
3830

3931
static char* errmsg_fetch_across_rollback = "Cursor needed to be reset because of commit/rollback and can no longer be fetched from.";
@@ -279,7 +271,6 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self)
279271
PyObject* row;
280272
PyObject* item = NULL;
281273
int coltype;
282-
PY_LONG_LONG intval;
283274
PyObject* converter;
284275
PyObject* converted;
285276
Py_ssize_t nbytes;
@@ -339,12 +330,7 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self)
339330
Py_INCREF(Py_None);
340331
converted = Py_None;
341332
} else if (coltype == SQLITE_INTEGER) {
342-
intval = sqlite3_column_int64(self->statement->st, i);
343-
if (intval < INT32_MIN || intval > INT32_MAX) {
344-
converted = PyLong_FromLongLong(intval);
345-
} else {
346-
converted = PyLong_FromLong((long)intval);
347-
}
333+
converted = _pysqlite_long_from_int64(sqlite3_column_int64(self->statement->st, i));
348334
} else if (coltype == SQLITE_FLOAT) {
349335
converted = PyFloat_FromDouble(sqlite3_column_double(self->statement->st, i));
350336
} else if (coltype == SQLITE_TEXT) {
@@ -446,7 +432,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
446432
PyObject* func_args;
447433
PyObject* result;
448434
int numcols;
449-
PY_LONG_LONG lastrowid;
450435
int statement_type;
451436
PyObject* descriptor;
452437
PyObject* second_argument = NULL;
@@ -716,10 +701,11 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
716701

717702
Py_DECREF(self->lastrowid);
718703
if (!multiple && statement_type == STATEMENT_INSERT) {
704+
sqlite3_int64 lastrowid;
719705
Py_BEGIN_ALLOW_THREADS
720706
lastrowid = sqlite3_last_insert_rowid(self->connection->db);
721707
Py_END_ALLOW_THREADS
722-
self->lastrowid = PyLong_FromLong((long)lastrowid);
708+
self->lastrowid = _pysqlite_long_from_int64(lastrowid);
723709
} else {
724710
Py_INCREF(Py_None);
725711
self->lastrowid = Py_None;

Modules/_sqlite/statement.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "connection.h"
2727
#include "microprotocols.h"
2828
#include "prepare_protocol.h"
29+
#include "util.h"
2930
#include "sqlitecompat.h"
3031

3132
/* prototypes */
@@ -90,7 +91,6 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con
9091
int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter)
9192
{
9293
int rc = SQLITE_OK;
93-
PY_LONG_LONG longlongval;
9494
const char* buffer;
9595
char* string;
9696
Py_ssize_t buflen;
@@ -120,11 +120,14 @@ int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObjec
120120
}
121121

122122
switch (paramtype) {
123-
case TYPE_LONG:
124-
/* in the overflow error case, longval/longlongval is -1, and an exception is set */
125-
longlongval = PyLong_AsLongLong(parameter);
126-
rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longlongval);
123+
case TYPE_LONG: {
124+
sqlite_int64 value = _pysqlite_long_as_int64(parameter);
125+
if (value == -1 && PyErr_Occurred())
126+
rc = -1;
127+
else
128+
rc = sqlite3_bind_int64(self->st, pos, value);
127129
break;
130+
}
128131
case TYPE_FLOAT:
129132
rc = sqlite3_bind_double(self->st, pos, PyFloat_AsDouble(parameter));
130133
break;

0 commit comments

Comments
 (0)