@@ -602,9 +602,9 @@ typedef struct {
602
602
} PyMemoEntry ;
603
603
604
604
typedef struct {
605
- Py_ssize_t mt_mask ;
606
- Py_ssize_t mt_used ;
607
- Py_ssize_t mt_allocated ;
605
+ size_t mt_mask ;
606
+ size_t mt_used ;
607
+ size_t mt_allocated ;
608
608
PyMemoEntry * mt_table ;
609
609
} PyMemoTable ;
610
610
@@ -650,8 +650,8 @@ typedef struct UnpicklerObject {
650
650
/* The unpickler memo is just an array of PyObject *s. Using a dict
651
651
is unnecessary, since the keys are contiguous ints. */
652
652
PyObject * * memo ;
653
- Py_ssize_t memo_size ; /* Capacity of the memo array */
654
- Py_ssize_t memo_len ; /* Number of objects in the memo */
653
+ size_t memo_size ; /* Capacity of the memo array */
654
+ size_t memo_len ; /* Number of objects in the memo */
655
655
656
656
PyObject * pers_func ; /* persistent_load() method, can be NULL. */
657
657
PyObject * pers_func_self ; /* borrowed reference to self if pers_func
@@ -737,7 +737,6 @@ PyMemoTable_New(void)
737
737
static PyMemoTable *
738
738
PyMemoTable_Copy (PyMemoTable * self )
739
739
{
740
- Py_ssize_t i ;
741
740
PyMemoTable * new = PyMemoTable_New ();
742
741
if (new == NULL )
743
742
return NULL ;
@@ -754,7 +753,7 @@ PyMemoTable_Copy(PyMemoTable *self)
754
753
PyErr_NoMemory ();
755
754
return NULL ;
756
755
}
757
- for (i = 0 ; i < self -> mt_allocated ; i ++ ) {
756
+ for (size_t i = 0 ; i < self -> mt_allocated ; i ++ ) {
758
757
Py_XINCREF (self -> mt_table [i ].me_key );
759
758
}
760
759
memcpy (new -> mt_table , self -> mt_table ,
@@ -800,7 +799,7 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
800
799
{
801
800
size_t i ;
802
801
size_t perturb ;
803
- size_t mask = ( size_t ) self -> mt_mask ;
802
+ size_t mask = self -> mt_mask ;
804
803
PyMemoEntry * table = self -> mt_table ;
805
804
PyMemoEntry * entry ;
806
805
Py_hash_t hash = (Py_hash_t )key >> 3 ;
@@ -821,22 +820,24 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
821
820
822
821
/* Returns -1 on failure, 0 on success. */
823
822
static int
824
- _PyMemoTable_ResizeTable (PyMemoTable * self , Py_ssize_t min_size )
823
+ _PyMemoTable_ResizeTable (PyMemoTable * self , size_t min_size )
825
824
{
826
825
PyMemoEntry * oldtable = NULL ;
827
826
PyMemoEntry * oldentry , * newentry ;
828
- Py_ssize_t new_size = MT_MINSIZE ;
829
- Py_ssize_t to_process ;
827
+ size_t new_size = MT_MINSIZE ;
828
+ size_t to_process ;
830
829
831
830
assert (min_size > 0 );
832
831
833
- /* Find the smallest valid table size >= min_size. */
834
- while (new_size < min_size && new_size > 0 )
835
- new_size <<= 1 ;
836
- if (new_size <= 0 ) {
832
+ if (min_size > PY_SSIZE_T_MAX ) {
837
833
PyErr_NoMemory ();
838
834
return -1 ;
839
835
}
836
+
837
+ /* Find the smallest valid table size >= min_size. */
838
+ while (new_size < min_size ) {
839
+ new_size <<= 1 ;
840
+ }
840
841
/* new_size needs to be a power of two. */
841
842
assert ((new_size & (new_size - 1 )) == 0 );
842
843
@@ -909,10 +910,12 @@ PyMemoTable_Set(PyMemoTable *self, PyObject *key, Py_ssize_t value)
909
910
* Very large memo tables (over 50K items) use doubling instead.
910
911
* This may help applications with severe memory constraints.
911
912
*/
912
- if (!( self -> mt_used * 3 >= ( self -> mt_mask + 1 ) * 2 ))
913
+ if (SIZE_MAX / 3 >= self -> mt_used && self -> mt_used * 3 < self -> mt_allocated * 2 ) {
913
914
return 0 ;
914
- return _PyMemoTable_ResizeTable (self ,
915
- (self -> mt_used > 50000 ? 2 : 4 ) * self -> mt_used );
915
+ }
916
+ // self->mt_used is always < PY_SSIZE_T_MAX, so this can't overflow.
917
+ size_t desired_size = (self -> mt_used > 50000 ? 2 : 4 ) * self -> mt_used ;
918
+ return _PyMemoTable_ResizeTable (self , desired_size );
916
919
}
917
920
918
921
#undef MT_MINSIZE
@@ -1376,9 +1379,9 @@ _Unpickler_Readline(UnpicklerObject *self, char **result)
1376
1379
/* Returns -1 (with an exception set) on failure, 0 on success. The memo array
1377
1380
will be modified in place. */
1378
1381
static int
1379
- _Unpickler_ResizeMemoList (UnpicklerObject * self , Py_ssize_t new_size )
1382
+ _Unpickler_ResizeMemoList (UnpicklerObject * self , size_t new_size )
1380
1383
{
1381
- Py_ssize_t i ;
1384
+ size_t i ;
1382
1385
1383
1386
assert (new_size > self -> memo_size );
1384
1387
@@ -1397,9 +1400,9 @@ _Unpickler_ResizeMemoList(UnpicklerObject *self, Py_ssize_t new_size)
1397
1400
1398
1401
/* Returns NULL if idx is out of bounds. */
1399
1402
static PyObject *
1400
- _Unpickler_MemoGet (UnpicklerObject * self , Py_ssize_t idx )
1403
+ _Unpickler_MemoGet (UnpicklerObject * self , size_t idx )
1401
1404
{
1402
- if (idx < 0 || idx >= self -> memo_size )
1405
+ if (idx >= self -> memo_size )
1403
1406
return NULL ;
1404
1407
1405
1408
return self -> memo [idx ];
@@ -1408,7 +1411,7 @@ _Unpickler_MemoGet(UnpicklerObject *self, Py_ssize_t idx)
1408
1411
/* Returns -1 (with an exception set) on failure, 0 on success.
1409
1412
This takes its own reference to `value`. */
1410
1413
static int
1411
- _Unpickler_MemoPut (UnpicklerObject * self , Py_ssize_t idx , PyObject * value )
1414
+ _Unpickler_MemoPut (UnpicklerObject * self , size_t idx , PyObject * value )
1412
1415
{
1413
1416
PyObject * old_item ;
1414
1417
@@ -4413,14 +4416,13 @@ static PyObject *
4413
4416
_pickle_PicklerMemoProxy_copy_impl (PicklerMemoProxyObject * self )
4414
4417
/*[clinic end generated code: output=bb83a919d29225ef input=b73043485ac30b36]*/
4415
4418
{
4416
- Py_ssize_t i ;
4417
4419
PyMemoTable * memo ;
4418
4420
PyObject * new_memo = PyDict_New ();
4419
4421
if (new_memo == NULL )
4420
4422
return NULL ;
4421
4423
4422
4424
memo = self -> pickler -> memo ;
4423
- for (i = 0 ; i < memo -> mt_allocated ; ++ i ) {
4425
+ for (size_t i = 0 ; i < memo -> mt_allocated ; ++ i ) {
4424
4426
PyMemoEntry entry = memo -> mt_table [i ];
4425
4427
if (entry .me_key != NULL ) {
4426
4428
int status ;
@@ -6843,7 +6845,7 @@ static PyObject *
6843
6845
_pickle_UnpicklerMemoProxy_copy_impl (UnpicklerMemoProxyObject * self )
6844
6846
/*[clinic end generated code: output=e12af7e9bc1e4c77 input=97769247ce032c1d]*/
6845
6847
{
6846
- Py_ssize_t i ;
6848
+ size_t i ;
6847
6849
PyObject * new_memo = PyDict_New ();
6848
6850
if (new_memo == NULL )
6849
6851
return NULL ;
@@ -6994,8 +6996,7 @@ static int
6994
6996
Unpickler_set_memo (UnpicklerObject * self , PyObject * obj )
6995
6997
{
6996
6998
PyObject * * new_memo ;
6997
- Py_ssize_t new_memo_size = 0 ;
6998
- Py_ssize_t i ;
6999
+ size_t new_memo_size = 0 ;
6999
7000
7000
7001
if (obj == NULL ) {
7001
7002
PyErr_SetString (PyExc_TypeError ,
@@ -7012,7 +7013,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
7012
7013
if (new_memo == NULL )
7013
7014
return -1 ;
7014
7015
7015
- for (i = 0 ; i < new_memo_size ; i ++ ) {
7016
+ for (size_t i = 0 ; i < new_memo_size ; i ++ ) {
7016
7017
Py_XINCREF (unpickler -> memo [i ]);
7017
7018
new_memo [i ] = unpickler -> memo [i ];
7018
7019
}
@@ -7060,8 +7061,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
7060
7061
7061
7062
error :
7062
7063
if (new_memo_size ) {
7063
- i = new_memo_size ;
7064
- while (-- i >= 0 ) {
7064
+ for (size_t i = new_memo_size - 1 ; i != SIZE_MAX ; i -- ) {
7065
7065
Py_XDECREF (new_memo [i ]);
7066
7066
}
7067
7067
PyMem_FREE (new_memo );
0 commit comments