@@ -596,9 +596,9 @@ typedef struct {
596
596
} PyMemoEntry ;
597
597
598
598
typedef 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 ;
602
602
PyMemoEntry * mt_table ;
603
603
} PyMemoTable ;
604
604
@@ -644,8 +644,8 @@ typedef struct UnpicklerObject {
644
644
/* The unpickler memo is just an array of PyObject *s. Using a dict
645
645
is unnecessary, since the keys are contiguous ints. */
646
646
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 */
649
649
650
650
PyObject * pers_func ; /* persistent_load() method, can be NULL. */
651
651
PyObject * pers_func_self ; /* borrowed reference to self if pers_func
@@ -731,7 +731,6 @@ PyMemoTable_New(void)
731
731
static PyMemoTable *
732
732
PyMemoTable_Copy (PyMemoTable * self )
733
733
{
734
- Py_ssize_t i ;
735
734
PyMemoTable * new = PyMemoTable_New ();
736
735
if (new == NULL )
737
736
return NULL ;
@@ -748,7 +747,7 @@ PyMemoTable_Copy(PyMemoTable *self)
748
747
PyErr_NoMemory ();
749
748
return NULL ;
750
749
}
751
- for (i = 0 ; i < self -> mt_allocated ; i ++ ) {
750
+ for (size_t i = 0 ; i < self -> mt_allocated ; i ++ ) {
752
751
Py_XINCREF (self -> mt_table [i ].me_key );
753
752
}
754
753
memcpy (new -> mt_table , self -> mt_table ,
@@ -794,7 +793,7 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
794
793
{
795
794
size_t i ;
796
795
size_t perturb ;
797
- size_t mask = ( size_t ) self -> mt_mask ;
796
+ size_t mask = self -> mt_mask ;
798
797
PyMemoEntry * table = self -> mt_table ;
799
798
PyMemoEntry * entry ;
800
799
Py_hash_t hash = (Py_hash_t )key >> 3 ;
@@ -816,22 +815,24 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
816
815
817
816
/* Returns -1 on failure, 0 on success. */
818
817
static int
819
- _PyMemoTable_ResizeTable (PyMemoTable * self , Py_ssize_t min_size )
818
+ _PyMemoTable_ResizeTable (PyMemoTable * self , size_t min_size )
820
819
{
821
820
PyMemoEntry * oldtable = NULL ;
822
821
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 ;
825
824
826
825
assert (min_size > 0 );
827
826
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 ) {
832
828
PyErr_NoMemory ();
833
829
return -1 ;
834
830
}
831
+
832
+ /* Find the smallest valid table size >= min_size. */
833
+ while (new_size < min_size ) {
834
+ new_size <<= 1 ;
835
+ }
835
836
/* new_size needs to be a power of two. */
836
837
assert ((new_size & (new_size - 1 )) == 0 );
837
838
@@ -904,10 +905,12 @@ PyMemoTable_Set(PyMemoTable *self, PyObject *key, Py_ssize_t value)
904
905
* Very large memo tables (over 50K items) use doubling instead.
905
906
* This may help applications with severe memory constraints.
906
907
*/
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 ) {
908
909
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 );
911
914
}
912
915
913
916
#undef MT_MINSIZE
@@ -1352,9 +1355,9 @@ _Unpickler_Readline(UnpicklerObject *self, char **result)
1352
1355
/* Returns -1 (with an exception set) on failure, 0 on success. The memo array
1353
1356
will be modified in place. */
1354
1357
static int
1355
- _Unpickler_ResizeMemoList (UnpicklerObject * self , Py_ssize_t new_size )
1358
+ _Unpickler_ResizeMemoList (UnpicklerObject * self , size_t new_size )
1356
1359
{
1357
- Py_ssize_t i ;
1360
+ size_t i ;
1358
1361
1359
1362
assert (new_size > self -> memo_size );
1360
1363
@@ -1373,9 +1376,9 @@ _Unpickler_ResizeMemoList(UnpicklerObject *self, Py_ssize_t new_size)
1373
1376
1374
1377
/* Returns NULL if idx is out of bounds. */
1375
1378
static PyObject *
1376
- _Unpickler_MemoGet (UnpicklerObject * self , Py_ssize_t idx )
1379
+ _Unpickler_MemoGet (UnpicklerObject * self , size_t idx )
1377
1380
{
1378
- if (idx < 0 || idx >= self -> memo_size )
1381
+ if (idx >= self -> memo_size )
1379
1382
return NULL ;
1380
1383
1381
1384
return self -> memo [idx ];
@@ -1384,7 +1387,7 @@ _Unpickler_MemoGet(UnpicklerObject *self, Py_ssize_t idx)
1384
1387
/* Returns -1 (with an exception set) on failure, 0 on success.
1385
1388
This takes its own reference to `value`. */
1386
1389
static int
1387
- _Unpickler_MemoPut (UnpicklerObject * self , Py_ssize_t idx , PyObject * value )
1390
+ _Unpickler_MemoPut (UnpicklerObject * self , size_t idx , PyObject * value )
1388
1391
{
1389
1392
PyObject * old_item ;
1390
1393
@@ -4328,14 +4331,13 @@ static PyObject *
4328
4331
_pickle_PicklerMemoProxy_copy_impl (PicklerMemoProxyObject * self )
4329
4332
/*[clinic end generated code: output=bb83a919d29225ef input=b73043485ac30b36]*/
4330
4333
{
4331
- Py_ssize_t i ;
4332
4334
PyMemoTable * memo ;
4333
4335
PyObject * new_memo = PyDict_New ();
4334
4336
if (new_memo == NULL )
4335
4337
return NULL ;
4336
4338
4337
4339
memo = self -> pickler -> memo ;
4338
- for (i = 0 ; i < memo -> mt_allocated ; ++ i ) {
4340
+ for (size_t i = 0 ; i < memo -> mt_allocated ; ++ i ) {
4339
4341
PyMemoEntry entry = memo -> mt_table [i ];
4340
4342
if (entry .me_key != NULL ) {
4341
4343
int status ;
@@ -6764,7 +6766,7 @@ static PyObject *
6764
6766
_pickle_UnpicklerMemoProxy_copy_impl (UnpicklerMemoProxyObject * self )
6765
6767
/*[clinic end generated code: output=e12af7e9bc1e4c77 input=97769247ce032c1d]*/
6766
6768
{
6767
- Py_ssize_t i ;
6769
+ size_t i ;
6768
6770
PyObject * new_memo = PyDict_New ();
6769
6771
if (new_memo == NULL )
6770
6772
return NULL ;
@@ -6915,8 +6917,7 @@ static int
6915
6917
Unpickler_set_memo (UnpicklerObject * self , PyObject * obj )
6916
6918
{
6917
6919
PyObject * * new_memo ;
6918
- Py_ssize_t new_memo_size = 0 ;
6919
- Py_ssize_t i ;
6920
+ size_t new_memo_size = 0 ;
6920
6921
6921
6922
if (obj == NULL ) {
6922
6923
PyErr_SetString (PyExc_TypeError ,
@@ -6933,7 +6934,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
6933
6934
if (new_memo == NULL )
6934
6935
return -1 ;
6935
6936
6936
- for (i = 0 ; i < new_memo_size ; i ++ ) {
6937
+ for (size_t i = 0 ; i < new_memo_size ; i ++ ) {
6937
6938
Py_XINCREF (unpickler -> memo [i ]);
6938
6939
new_memo [i ] = unpickler -> memo [i ];
6939
6940
}
@@ -6981,8 +6982,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
6981
6982
6982
6983
error :
6983
6984
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 -- ) {
6986
6986
Py_XDECREF (new_memo [i ]);
6987
6987
}
6988
6988
PyMem_FREE (new_memo );
0 commit comments