@@ -596,9 +596,9 @@ typedef struct {
596596} PyMemoEntry ;
597597
598598typedef struct {
599- Py_ssize_t mt_mask ;
600- Py_ssize_t mt_used ;
601- Py_ssize_t mt_allocated ;
599+ size_t mt_mask ;
600+ size_t mt_used ;
601+ size_t mt_allocated ;
602602 PyMemoEntry * mt_table ;
603603} PyMemoTable ;
604604
@@ -644,8 +644,8 @@ typedef struct UnpicklerObject {
644644 /* The unpickler memo is just an array of PyObject *s. Using a dict
645645 is unnecessary, since the keys are contiguous ints. */
646646 PyObject * * memo ;
647- Py_ssize_t memo_size ; /* Capacity of the memo array */
648- Py_ssize_t memo_len ; /* Number of objects in the memo */
647+ size_t memo_size ; /* Capacity of the memo array */
648+ size_t memo_len ; /* Number of objects in the memo */
649649
650650 PyObject * pers_func ; /* persistent_load() method, can be NULL. */
651651 PyObject * pers_func_self ; /* borrowed reference to self if pers_func
@@ -731,7 +731,6 @@ PyMemoTable_New(void)
731731static PyMemoTable *
732732PyMemoTable_Copy (PyMemoTable * self )
733733{
734- Py_ssize_t i ;
735734 PyMemoTable * new = PyMemoTable_New ();
736735 if (new == NULL )
737736 return NULL ;
@@ -748,7 +747,7 @@ PyMemoTable_Copy(PyMemoTable *self)
748747 PyErr_NoMemory ();
749748 return NULL ;
750749 }
751- for (i = 0 ; i < self -> mt_allocated ; i ++ ) {
750+ for (size_t i = 0 ; i < self -> mt_allocated ; i ++ ) {
752751 Py_XINCREF (self -> mt_table [i ].me_key );
753752 }
754753 memcpy (new -> mt_table , self -> mt_table ,
@@ -794,7 +793,7 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
794793{
795794 size_t i ;
796795 size_t perturb ;
797- size_t mask = ( size_t ) self -> mt_mask ;
796+ size_t mask = self -> mt_mask ;
798797 PyMemoEntry * table = self -> mt_table ;
799798 PyMemoEntry * entry ;
800799 Py_hash_t hash = (Py_hash_t )key >> 3 ;
@@ -816,22 +815,24 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
816815
817816/* Returns -1 on failure, 0 on success. */
818817static int
819- _PyMemoTable_ResizeTable (PyMemoTable * self , Py_ssize_t min_size )
818+ _PyMemoTable_ResizeTable (PyMemoTable * self , size_t min_size )
820819{
821820 PyMemoEntry * oldtable = NULL ;
822821 PyMemoEntry * oldentry , * newentry ;
823- Py_ssize_t new_size = MT_MINSIZE ;
824- Py_ssize_t to_process ;
822+ size_t new_size = MT_MINSIZE ;
823+ size_t to_process ;
825824
826825 assert (min_size > 0 );
827826
828- /* Find the smallest valid table size >= min_size. */
829- while (new_size < min_size && new_size > 0 )
830- new_size <<= 1 ;
831- if (new_size <= 0 ) {
827+ if (min_size > PY_SSIZE_T_MAX ) {
832828 PyErr_NoMemory ();
833829 return -1 ;
834830 }
831+
832+ /* Find the smallest valid table size >= min_size. */
833+ while (new_size < min_size ) {
834+ new_size <<= 1 ;
835+ }
835836 /* new_size needs to be a power of two. */
836837 assert ((new_size & (new_size - 1 )) == 0 );
837838
@@ -904,10 +905,12 @@ PyMemoTable_Set(PyMemoTable *self, PyObject *key, Py_ssize_t value)
904905 * Very large memo tables (over 50K items) use doubling instead.
905906 * This may help applications with severe memory constraints.
906907 */
907- if (!( self -> mt_used * 3 >= ( self -> mt_mask + 1 ) * 2 ))
908+ if (SIZE_MAX / 3 >= self -> mt_used && self -> mt_used * 3 < self -> mt_allocated * 2 ) {
908909 return 0 ;
909- return _PyMemoTable_ResizeTable (self ,
910- (self -> mt_used > 50000 ? 2 : 4 ) * self -> mt_used );
910+ }
911+ // self->mt_used is always < PY_SSIZE_T_MAX, so this can't overflow.
912+ size_t desired_size = (self -> mt_used > 50000 ? 2 : 4 ) * self -> mt_used ;
913+ return _PyMemoTable_ResizeTable (self , desired_size );
911914}
912915
913916#undef MT_MINSIZE
@@ -1352,9 +1355,9 @@ _Unpickler_Readline(UnpicklerObject *self, char **result)
13521355/* Returns -1 (with an exception set) on failure, 0 on success. The memo array
13531356 will be modified in place. */
13541357static int
1355- _Unpickler_ResizeMemoList (UnpicklerObject * self , Py_ssize_t new_size )
1358+ _Unpickler_ResizeMemoList (UnpicklerObject * self , size_t new_size )
13561359{
1357- Py_ssize_t i ;
1360+ size_t i ;
13581361
13591362 assert (new_size > self -> memo_size );
13601363
@@ -1373,9 +1376,9 @@ _Unpickler_ResizeMemoList(UnpicklerObject *self, Py_ssize_t new_size)
13731376
13741377/* Returns NULL if idx is out of bounds. */
13751378static PyObject *
1376- _Unpickler_MemoGet (UnpicklerObject * self , Py_ssize_t idx )
1379+ _Unpickler_MemoGet (UnpicklerObject * self , size_t idx )
13771380{
1378- if (idx < 0 || idx >= self -> memo_size )
1381+ if (idx >= self -> memo_size )
13791382 return NULL ;
13801383
13811384 return self -> memo [idx ];
@@ -1384,7 +1387,7 @@ _Unpickler_MemoGet(UnpicklerObject *self, Py_ssize_t idx)
13841387/* Returns -1 (with an exception set) on failure, 0 on success.
13851388 This takes its own reference to `value`. */
13861389static int
1387- _Unpickler_MemoPut (UnpicklerObject * self , Py_ssize_t idx , PyObject * value )
1390+ _Unpickler_MemoPut (UnpicklerObject * self , size_t idx , PyObject * value )
13881391{
13891392 PyObject * old_item ;
13901393
@@ -4328,14 +4331,13 @@ static PyObject *
43284331_pickle_PicklerMemoProxy_copy_impl (PicklerMemoProxyObject * self )
43294332/*[clinic end generated code: output=bb83a919d29225ef input=b73043485ac30b36]*/
43304333{
4331- Py_ssize_t i ;
43324334 PyMemoTable * memo ;
43334335 PyObject * new_memo = PyDict_New ();
43344336 if (new_memo == NULL )
43354337 return NULL ;
43364338
43374339 memo = self -> pickler -> memo ;
4338- for (i = 0 ; i < memo -> mt_allocated ; ++ i ) {
4340+ for (size_t i = 0 ; i < memo -> mt_allocated ; ++ i ) {
43394341 PyMemoEntry entry = memo -> mt_table [i ];
43404342 if (entry .me_key != NULL ) {
43414343 int status ;
@@ -6764,7 +6766,7 @@ static PyObject *
67646766_pickle_UnpicklerMemoProxy_copy_impl (UnpicklerMemoProxyObject * self )
67656767/*[clinic end generated code: output=e12af7e9bc1e4c77 input=97769247ce032c1d]*/
67666768{
6767- Py_ssize_t i ;
6769+ size_t i ;
67686770 PyObject * new_memo = PyDict_New ();
67696771 if (new_memo == NULL )
67706772 return NULL ;
@@ -6915,8 +6917,7 @@ static int
69156917Unpickler_set_memo (UnpicklerObject * self , PyObject * obj )
69166918{
69176919 PyObject * * new_memo ;
6918- Py_ssize_t new_memo_size = 0 ;
6919- Py_ssize_t i ;
6920+ size_t new_memo_size = 0 ;
69206921
69216922 if (obj == NULL ) {
69226923 PyErr_SetString (PyExc_TypeError ,
@@ -6933,7 +6934,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
69336934 if (new_memo == NULL )
69346935 return -1 ;
69356936
6936- for (i = 0 ; i < new_memo_size ; i ++ ) {
6937+ for (size_t i = 0 ; i < new_memo_size ; i ++ ) {
69376938 Py_XINCREF (unpickler -> memo [i ]);
69386939 new_memo [i ] = unpickler -> memo [i ];
69396940 }
@@ -6981,8 +6982,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
69816982
69826983 error :
69836984 if (new_memo_size ) {
6984- i = new_memo_size ;
6985- while (-- i >= 0 ) {
6985+ for (size_t i = new_memo_size - 1 ; i != SIZE_MAX ; i -- ) {
69866986 Py_XDECREF (new_memo [i ]);
69876987 }
69886988 PyMem_FREE (new_memo );
0 commit comments