@@ -600,9 +600,9 @@ typedef struct {
600600} PyMemoEntry ;
601601
602602typedef 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 ;
606606 PyMemoEntry * mt_table ;
607607} PyMemoTable ;
608608
@@ -648,8 +648,8 @@ typedef struct UnpicklerObject {
648648 /* The unpickler memo is just an array of PyObject *s. Using a dict
649649 is unnecessary, since the keys are contiguous ints. */
650650 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 */
653653
654654 PyObject * pers_func ; /* persistent_load() method, can be NULL. */
655655 PyObject * pers_func_self ; /* borrowed reference to self if pers_func
@@ -735,7 +735,6 @@ PyMemoTable_New(void)
735735static PyMemoTable *
736736PyMemoTable_Copy (PyMemoTable * self )
737737{
738- Py_ssize_t i ;
739738 PyMemoTable * new = PyMemoTable_New ();
740739 if (new == NULL )
741740 return NULL ;
@@ -752,7 +751,7 @@ PyMemoTable_Copy(PyMemoTable *self)
752751 PyErr_NoMemory ();
753752 return NULL ;
754753 }
755- for (i = 0 ; i < self -> mt_allocated ; i ++ ) {
754+ for (size_t i = 0 ; i < self -> mt_allocated ; i ++ ) {
756755 Py_XINCREF (self -> mt_table [i ].me_key );
757756 }
758757 memcpy (new -> mt_table , self -> mt_table ,
@@ -798,7 +797,7 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
798797{
799798 size_t i ;
800799 size_t perturb ;
801- size_t mask = ( size_t ) self -> mt_mask ;
800+ size_t mask = self -> mt_mask ;
802801 PyMemoEntry * table = self -> mt_table ;
803802 PyMemoEntry * entry ;
804803 Py_hash_t hash = (Py_hash_t )key >> 3 ;
@@ -819,22 +818,24 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
819818
820819/* Returns -1 on failure, 0 on success. */
821820static int
822- _PyMemoTable_ResizeTable (PyMemoTable * self , Py_ssize_t min_size )
821+ _PyMemoTable_ResizeTable (PyMemoTable * self , size_t min_size )
823822{
824823 PyMemoEntry * oldtable = NULL ;
825824 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 ;
828827
829828 assert (min_size > 0 );
830829
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 ) {
835831 PyErr_NoMemory ();
836832 return -1 ;
837833 }
834+
835+ /* Find the smallest valid table size >= min_size. */
836+ while (new_size < min_size ) {
837+ new_size <<= 1 ;
838+ }
838839 /* new_size needs to be a power of two. */
839840 assert ((new_size & (new_size - 1 )) == 0 );
840841
@@ -907,10 +908,12 @@ PyMemoTable_Set(PyMemoTable *self, PyObject *key, Py_ssize_t value)
907908 * Very large memo tables (over 50K items) use doubling instead.
908909 * This may help applications with severe memory constraints.
909910 */
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 ) {
911912 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 );
914917}
915918
916919#undef MT_MINSIZE
@@ -1374,9 +1377,9 @@ _Unpickler_Readline(UnpicklerObject *self, char **result)
13741377/* Returns -1 (with an exception set) on failure, 0 on success. The memo array
13751378 will be modified in place. */
13761379static int
1377- _Unpickler_ResizeMemoList (UnpicklerObject * self , Py_ssize_t new_size )
1380+ _Unpickler_ResizeMemoList (UnpicklerObject * self , size_t new_size )
13781381{
1379- Py_ssize_t i ;
1382+ size_t i ;
13801383
13811384 assert (new_size > self -> memo_size );
13821385
@@ -1395,9 +1398,9 @@ _Unpickler_ResizeMemoList(UnpicklerObject *self, Py_ssize_t new_size)
13951398
13961399/* Returns NULL if idx is out of bounds. */
13971400static PyObject *
1398- _Unpickler_MemoGet (UnpicklerObject * self , Py_ssize_t idx )
1401+ _Unpickler_MemoGet (UnpicklerObject * self , size_t idx )
13991402{
1400- if (idx < 0 || idx >= self -> memo_size )
1403+ if (idx >= self -> memo_size )
14011404 return NULL ;
14021405
14031406 return self -> memo [idx ];
@@ -1406,7 +1409,7 @@ _Unpickler_MemoGet(UnpicklerObject *self, Py_ssize_t idx)
14061409/* Returns -1 (with an exception set) on failure, 0 on success.
14071410 This takes its own reference to `value`. */
14081411static int
1409- _Unpickler_MemoPut (UnpicklerObject * self , Py_ssize_t idx , PyObject * value )
1412+ _Unpickler_MemoPut (UnpicklerObject * self , size_t idx , PyObject * value )
14101413{
14111414 PyObject * old_item ;
14121415
@@ -4415,14 +4418,13 @@ static PyObject *
44154418_pickle_PicklerMemoProxy_copy_impl (PicklerMemoProxyObject * self )
44164419/*[clinic end generated code: output=bb83a919d29225ef input=b73043485ac30b36]*/
44174420{
4418- Py_ssize_t i ;
44194421 PyMemoTable * memo ;
44204422 PyObject * new_memo = PyDict_New ();
44214423 if (new_memo == NULL )
44224424 return NULL ;
44234425
44244426 memo = self -> pickler -> memo ;
4425- for (i = 0 ; i < memo -> mt_allocated ; ++ i ) {
4427+ for (size_t i = 0 ; i < memo -> mt_allocated ; ++ i ) {
44264428 PyMemoEntry entry = memo -> mt_table [i ];
44274429 if (entry .me_key != NULL ) {
44284430 int status ;
@@ -6855,7 +6857,7 @@ static PyObject *
68556857_pickle_UnpicklerMemoProxy_copy_impl (UnpicklerMemoProxyObject * self )
68566858/*[clinic end generated code: output=e12af7e9bc1e4c77 input=97769247ce032c1d]*/
68576859{
6858- Py_ssize_t i ;
6860+ size_t i ;
68596861 PyObject * new_memo = PyDict_New ();
68606862 if (new_memo == NULL )
68616863 return NULL ;
@@ -7006,8 +7008,7 @@ static int
70067008Unpickler_set_memo (UnpicklerObject * self , PyObject * obj )
70077009{
70087010 PyObject * * new_memo ;
7009- Py_ssize_t new_memo_size = 0 ;
7010- Py_ssize_t i ;
7011+ size_t new_memo_size = 0 ;
70117012
70127013 if (obj == NULL ) {
70137014 PyErr_SetString (PyExc_TypeError ,
@@ -7024,7 +7025,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
70247025 if (new_memo == NULL )
70257026 return -1 ;
70267027
7027- for (i = 0 ; i < new_memo_size ; i ++ ) {
7028+ for (size_t i = 0 ; i < new_memo_size ; i ++ ) {
70287029 Py_XINCREF (unpickler -> memo [i ]);
70297030 new_memo [i ] = unpickler -> memo [i ];
70307031 }
@@ -7072,8 +7073,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
70727073
70737074 error :
70747075 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 -- ) {
70777077 Py_XDECREF (new_memo [i ]);
70787078 }
70797079 PyMem_FREE (new_memo );
0 commit comments