@@ -527,9 +527,9 @@ typedef struct {
527527} PyMemoEntry ;
528528
529529typedef struct {
530- Py_ssize_t mt_mask ;
531- Py_ssize_t mt_used ;
532- Py_ssize_t mt_allocated ;
530+ size_t mt_mask ;
531+ size_t mt_used ;
532+ size_t mt_allocated ;
533533 PyMemoEntry * mt_table ;
534534} PyMemoTable ;
535535
@@ -573,8 +573,8 @@ typedef struct UnpicklerObject {
573573 /* The unpickler memo is just an array of PyObject *s. Using a dict
574574 is unnecessary, since the keys are contiguous ints. */
575575 PyObject * * memo ;
576- Py_ssize_t memo_size ; /* Capacity of the memo array */
577- Py_ssize_t memo_len ; /* Number of objects in the memo */
576+ size_t memo_size ; /* Capacity of the memo array */
577+ size_t memo_len ; /* Number of objects in the memo */
578578
579579 PyObject * pers_func ; /* persistent_load() method, can be NULL. */
580580
@@ -658,7 +658,6 @@ PyMemoTable_New(void)
658658static PyMemoTable *
659659PyMemoTable_Copy (PyMemoTable * self )
660660{
661- Py_ssize_t i ;
662661 PyMemoTable * new = PyMemoTable_New ();
663662 if (new == NULL )
664663 return NULL ;
@@ -675,7 +674,7 @@ PyMemoTable_Copy(PyMemoTable *self)
675674 PyErr_NoMemory ();
676675 return NULL ;
677676 }
678- for (i = 0 ; i < self -> mt_allocated ; i ++ ) {
677+ for (size_t i = 0 ; i < self -> mt_allocated ; i ++ ) {
679678 Py_XINCREF (self -> mt_table [i ].me_key );
680679 }
681680 memcpy (new -> mt_table , self -> mt_table ,
@@ -721,7 +720,7 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
721720{
722721 size_t i ;
723722 size_t perturb ;
724- size_t mask = ( size_t ) self -> mt_mask ;
723+ size_t mask = self -> mt_mask ;
725724 PyMemoEntry * table = self -> mt_table ;
726725 PyMemoEntry * entry ;
727726 Py_hash_t hash = (Py_hash_t )key >> 3 ;
@@ -743,22 +742,24 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
743742
744743/* Returns -1 on failure, 0 on success. */
745744static int
746- _PyMemoTable_ResizeTable (PyMemoTable * self , Py_ssize_t min_size )
745+ _PyMemoTable_ResizeTable (PyMemoTable * self , size_t min_size )
747746{
748747 PyMemoEntry * oldtable = NULL ;
749748 PyMemoEntry * oldentry , * newentry ;
750- Py_ssize_t new_size = MT_MINSIZE ;
751- Py_ssize_t to_process ;
749+ size_t new_size = MT_MINSIZE ;
750+ size_t to_process ;
752751
753752 assert (min_size > 0 );
754753
755- /* Find the smallest valid table size >= min_size. */
756- while (new_size < min_size && new_size > 0 )
757- new_size <<= 1 ;
758- if (new_size <= 0 ) {
754+ if (min_size > PY_SSIZE_T_MAX ) {
759755 PyErr_NoMemory ();
760756 return -1 ;
761757 }
758+
759+ /* Find the smallest valid table size >= min_size. */
760+ while (new_size < min_size ) {
761+ new_size <<= 1 ;
762+ }
762763 /* new_size needs to be a power of two. */
763764 assert ((new_size & (new_size - 1 )) == 0 );
764765
@@ -808,6 +809,7 @@ static int
808809PyMemoTable_Set (PyMemoTable * self , PyObject * key , Py_ssize_t value )
809810{
810811 PyMemoEntry * entry ;
812+ size_t desired_size ;
811813
812814 assert (key != NULL );
813815
@@ -831,10 +833,12 @@ PyMemoTable_Set(PyMemoTable *self, PyObject *key, Py_ssize_t value)
831833 * Very large memo tables (over 50K items) use doubling instead.
832834 * This may help applications with severe memory constraints.
833835 */
834- if (!( self -> mt_used * 3 >= ( self -> mt_mask + 1 ) * 2 ))
836+ if (SIZE_MAX / 3 >= self -> mt_used && self -> mt_used * 3 < self -> mt_allocated * 2 ) {
835837 return 0 ;
836- return _PyMemoTable_ResizeTable (self ,
837- (self -> mt_used > 50000 ? 2 : 4 ) * self -> mt_used );
838+ }
839+ // self->mt_used is always < PY_SSIZE_T_MAX, so this can't overflow.
840+ desired_size = (self -> mt_used > 50000 ? 2 : 4 ) * self -> mt_used ;
841+ return _PyMemoTable_ResizeTable (self , desired_size );
838842}
839843
840844#undef MT_MINSIZE
@@ -1273,9 +1277,9 @@ _Unpickler_Readline(UnpicklerObject *self, char **result)
12731277/* Returns -1 (with an exception set) on failure, 0 on success. The memo array
12741278 will be modified in place. */
12751279static int
1276- _Unpickler_ResizeMemoList (UnpicklerObject * self , Py_ssize_t new_size )
1280+ _Unpickler_ResizeMemoList (UnpicklerObject * self , size_t new_size )
12771281{
1278- Py_ssize_t i ;
1282+ size_t i ;
12791283
12801284 assert (new_size > self -> memo_size );
12811285
@@ -1292,9 +1296,9 @@ _Unpickler_ResizeMemoList(UnpicklerObject *self, Py_ssize_t new_size)
12921296
12931297/* Returns NULL if idx is out of bounds. */
12941298static PyObject *
1295- _Unpickler_MemoGet (UnpicklerObject * self , Py_ssize_t idx )
1299+ _Unpickler_MemoGet (UnpicklerObject * self , size_t idx )
12961300{
1297- if (idx < 0 || idx >= self -> memo_size )
1301+ if (idx >= self -> memo_size )
12981302 return NULL ;
12991303
13001304 return self -> memo [idx ];
@@ -1303,7 +1307,7 @@ _Unpickler_MemoGet(UnpicklerObject *self, Py_ssize_t idx)
13031307/* Returns -1 (with an exception set) on failure, 0 on success.
13041308 This takes its own reference to `value`. */
13051309static int
1306- _Unpickler_MemoPut (UnpicklerObject * self , Py_ssize_t idx , PyObject * value )
1310+ _Unpickler_MemoPut (UnpicklerObject * self , size_t idx , PyObject * value )
13071311{
13081312 PyObject * old_item ;
13091313
@@ -4194,14 +4198,13 @@ static PyObject *
41944198_pickle_PicklerMemoProxy_copy_impl (PicklerMemoProxyObject * self )
41954199/*[clinic end generated code: output=bb83a919d29225ef input=b73043485ac30b36]*/
41964200{
4197- Py_ssize_t i ;
41984201 PyMemoTable * memo ;
41994202 PyObject * new_memo = PyDict_New ();
42004203 if (new_memo == NULL )
42014204 return NULL ;
42024205
42034206 memo = self -> pickler -> memo ;
4204- for (i = 0 ; i < memo -> mt_allocated ; ++ i ) {
4207+ for (size_t i = 0 ; i < memo -> mt_allocated ; ++ i ) {
42054208 PyMemoEntry entry = memo -> mt_table [i ];
42064209 if (entry .me_key != NULL ) {
42074210 int status ;
@@ -6620,7 +6623,7 @@ static PyObject *
66206623_pickle_UnpicklerMemoProxy_copy_impl (UnpicklerMemoProxyObject * self )
66216624/*[clinic end generated code: output=e12af7e9bc1e4c77 input=97769247ce032c1d]*/
66226625{
6623- Py_ssize_t i ;
6626+ size_t i ;
66246627 PyObject * new_memo = PyDict_New ();
66256628 if (new_memo == NULL )
66266629 return NULL ;
@@ -6771,8 +6774,7 @@ static int
67716774Unpickler_set_memo (UnpicklerObject * self , PyObject * obj )
67726775{
67736776 PyObject * * new_memo ;
6774- Py_ssize_t new_memo_size = 0 ;
6775- Py_ssize_t i ;
6777+ size_t new_memo_size = 0 ;
67766778
67776779 if (obj == NULL ) {
67786780 PyErr_SetString (PyExc_TypeError ,
@@ -6789,7 +6791,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
67896791 if (new_memo == NULL )
67906792 return -1 ;
67916793
6792- for (i = 0 ; i < new_memo_size ; i ++ ) {
6794+ for (size_t i = 0 ; i < new_memo_size ; i ++ ) {
67936795 Py_XINCREF (unpickler -> memo [i ]);
67946796 new_memo [i ] = unpickler -> memo [i ];
67956797 }
@@ -6837,8 +6839,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
68376839
68386840 error :
68396841 if (new_memo_size ) {
6840- i = new_memo_size ;
6841- while (-- i >= 0 ) {
6842+ for (size_t i = new_memo_size - 1 ; i != SIZE_MAX ; i -- ) {
68426843 Py_XDECREF (new_memo [i ]);
68436844 }
68446845 PyMem_FREE (new_memo );
0 commit comments