@@ -600,9 +600,9 @@ typedef struct {
600
600
} PyMemoEntry ;
601
601
602
602
typedef struct {
603
- Py_ssize_t mt_mask ;
604
- Py_ssize_t mt_used ;
605
- Py_ssize_t mt_allocated ;
603
+ size_t mt_mask ;
604
+ size_t mt_used ;
605
+ size_t mt_allocated ;
606
606
PyMemoEntry * mt_table ;
607
607
} PyMemoTable ;
608
608
@@ -648,8 +648,8 @@ typedef struct UnpicklerObject {
648
648
/* The unpickler memo is just an array of PyObject *s. Using a dict
649
649
is unnecessary, since the keys are contiguous ints. */
650
650
PyObject * * memo ;
651
- Py_ssize_t memo_size ; /* Capacity of the memo array */
652
- Py_ssize_t memo_len ; /* Number of objects in the memo */
651
+ size_t memo_size ; /* Capacity of the memo array */
652
+ size_t memo_len ; /* Number of objects in the memo */
653
653
654
654
PyObject * pers_func ; /* persistent_load() method, can be NULL. */
655
655
PyObject * pers_func_self ; /* borrowed reference to self if pers_func
@@ -735,7 +735,6 @@ PyMemoTable_New(void)
735
735
static PyMemoTable *
736
736
PyMemoTable_Copy (PyMemoTable * self )
737
737
{
738
- Py_ssize_t i ;
739
738
PyMemoTable * new = PyMemoTable_New ();
740
739
if (new == NULL )
741
740
return NULL ;
@@ -752,7 +751,7 @@ PyMemoTable_Copy(PyMemoTable *self)
752
751
PyErr_NoMemory ();
753
752
return NULL ;
754
753
}
755
- for (i = 0 ; i < self -> mt_allocated ; i ++ ) {
754
+ for (size_t i = 0 ; i < self -> mt_allocated ; i ++ ) {
756
755
Py_XINCREF (self -> mt_table [i ].me_key );
757
756
}
758
757
memcpy (new -> mt_table , self -> mt_table ,
@@ -798,7 +797,7 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
798
797
{
799
798
size_t i ;
800
799
size_t perturb ;
801
- size_t mask = ( size_t ) self -> mt_mask ;
800
+ size_t mask = self -> mt_mask ;
802
801
PyMemoEntry * table = self -> mt_table ;
803
802
PyMemoEntry * entry ;
804
803
Py_hash_t hash = (Py_hash_t )key >> 3 ;
@@ -819,22 +818,24 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
819
818
820
819
/* Returns -1 on failure, 0 on success. */
821
820
static int
822
- _PyMemoTable_ResizeTable (PyMemoTable * self , Py_ssize_t min_size )
821
+ _PyMemoTable_ResizeTable (PyMemoTable * self , size_t min_size )
823
822
{
824
823
PyMemoEntry * oldtable = NULL ;
825
824
PyMemoEntry * oldentry , * newentry ;
826
- Py_ssize_t new_size = MT_MINSIZE ;
827
- Py_ssize_t to_process ;
825
+ size_t new_size = MT_MINSIZE ;
826
+ size_t to_process ;
828
827
829
828
assert (min_size > 0 );
830
829
831
- /* Find the smallest valid table size >= min_size. */
832
- while (new_size < min_size && new_size > 0 )
833
- new_size <<= 1 ;
834
- if (new_size <= 0 ) {
830
+ if (min_size > PY_SSIZE_T_MAX ) {
835
831
PyErr_NoMemory ();
836
832
return -1 ;
837
833
}
834
+
835
+ /* Find the smallest valid table size >= min_size. */
836
+ while (new_size < min_size ) {
837
+ new_size <<= 1 ;
838
+ }
838
839
/* new_size needs to be a power of two. */
839
840
assert ((new_size & (new_size - 1 )) == 0 );
840
841
@@ -907,10 +908,12 @@ PyMemoTable_Set(PyMemoTable *self, PyObject *key, Py_ssize_t value)
907
908
* Very large memo tables (over 50K items) use doubling instead.
908
909
* This may help applications with severe memory constraints.
909
910
*/
910
- if (!( self -> mt_used * 3 >= ( self -> mt_mask + 1 ) * 2 ))
911
+ if (SIZE_MAX / 3 >= self -> mt_used && self -> mt_used * 3 < self -> mt_allocated * 2 ) {
911
912
return 0 ;
912
- return _PyMemoTable_ResizeTable (self ,
913
- (self -> mt_used > 50000 ? 2 : 4 ) * self -> mt_used );
913
+ }
914
+ // self->mt_used is always < PY_SSIZE_T_MAX, so this can't overflow.
915
+ size_t desired_size = (self -> mt_used > 50000 ? 2 : 4 ) * self -> mt_used ;
916
+ return _PyMemoTable_ResizeTable (self , desired_size );
914
917
}
915
918
916
919
#undef MT_MINSIZE
@@ -1374,9 +1377,9 @@ _Unpickler_Readline(UnpicklerObject *self, char **result)
1374
1377
/* Returns -1 (with an exception set) on failure, 0 on success. The memo array
1375
1378
will be modified in place. */
1376
1379
static int
1377
- _Unpickler_ResizeMemoList (UnpicklerObject * self , Py_ssize_t new_size )
1380
+ _Unpickler_ResizeMemoList (UnpicklerObject * self , size_t new_size )
1378
1381
{
1379
- Py_ssize_t i ;
1382
+ size_t i ;
1380
1383
1381
1384
assert (new_size > self -> memo_size );
1382
1385
@@ -1395,9 +1398,9 @@ _Unpickler_ResizeMemoList(UnpicklerObject *self, Py_ssize_t new_size)
1395
1398
1396
1399
/* Returns NULL if idx is out of bounds. */
1397
1400
static PyObject *
1398
- _Unpickler_MemoGet (UnpicklerObject * self , Py_ssize_t idx )
1401
+ _Unpickler_MemoGet (UnpicklerObject * self , size_t idx )
1399
1402
{
1400
- if (idx < 0 || idx >= self -> memo_size )
1403
+ if (idx >= self -> memo_size )
1401
1404
return NULL ;
1402
1405
1403
1406
return self -> memo [idx ];
@@ -1406,7 +1409,7 @@ _Unpickler_MemoGet(UnpicklerObject *self, Py_ssize_t idx)
1406
1409
/* Returns -1 (with an exception set) on failure, 0 on success.
1407
1410
This takes its own reference to `value`. */
1408
1411
static int
1409
- _Unpickler_MemoPut (UnpicklerObject * self , Py_ssize_t idx , PyObject * value )
1412
+ _Unpickler_MemoPut (UnpicklerObject * self , size_t idx , PyObject * value )
1410
1413
{
1411
1414
PyObject * old_item ;
1412
1415
@@ -4415,14 +4418,13 @@ static PyObject *
4415
4418
_pickle_PicklerMemoProxy_copy_impl (PicklerMemoProxyObject * self )
4416
4419
/*[clinic end generated code: output=bb83a919d29225ef input=b73043485ac30b36]*/
4417
4420
{
4418
- Py_ssize_t i ;
4419
4421
PyMemoTable * memo ;
4420
4422
PyObject * new_memo = PyDict_New ();
4421
4423
if (new_memo == NULL )
4422
4424
return NULL ;
4423
4425
4424
4426
memo = self -> pickler -> memo ;
4425
- for (i = 0 ; i < memo -> mt_allocated ; ++ i ) {
4427
+ for (size_t i = 0 ; i < memo -> mt_allocated ; ++ i ) {
4426
4428
PyMemoEntry entry = memo -> mt_table [i ];
4427
4429
if (entry .me_key != NULL ) {
4428
4430
int status ;
@@ -6855,7 +6857,7 @@ static PyObject *
6855
6857
_pickle_UnpicklerMemoProxy_copy_impl (UnpicklerMemoProxyObject * self )
6856
6858
/*[clinic end generated code: output=e12af7e9bc1e4c77 input=97769247ce032c1d]*/
6857
6859
{
6858
- Py_ssize_t i ;
6860
+ size_t i ;
6859
6861
PyObject * new_memo = PyDict_New ();
6860
6862
if (new_memo == NULL )
6861
6863
return NULL ;
@@ -7006,8 +7008,7 @@ static int
7006
7008
Unpickler_set_memo (UnpicklerObject * self , PyObject * obj )
7007
7009
{
7008
7010
PyObject * * new_memo ;
7009
- Py_ssize_t new_memo_size = 0 ;
7010
- Py_ssize_t i ;
7011
+ size_t new_memo_size = 0 ;
7011
7012
7012
7013
if (obj == NULL ) {
7013
7014
PyErr_SetString (PyExc_TypeError ,
@@ -7024,7 +7025,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
7024
7025
if (new_memo == NULL )
7025
7026
return -1 ;
7026
7027
7027
- for (i = 0 ; i < new_memo_size ; i ++ ) {
7028
+ for (size_t i = 0 ; i < new_memo_size ; i ++ ) {
7028
7029
Py_XINCREF (unpickler -> memo [i ]);
7029
7030
new_memo [i ] = unpickler -> memo [i ];
7030
7031
}
@@ -7072,8 +7073,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
7072
7073
7073
7074
error :
7074
7075
if (new_memo_size ) {
7075
- i = new_memo_size ;
7076
- while (-- i >= 0 ) {
7076
+ for (size_t i = new_memo_size - 1 ; i != SIZE_MAX ; i -- ) {
7077
7077
Py_XDECREF (new_memo [i ]);
7078
7078
}
7079
7079
PyMem_FREE (new_memo );
0 commit comments