@@ -527,9 +527,9 @@ typedef struct {
527
527
} PyMemoEntry ;
528
528
529
529
typedef 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 ;
533
533
PyMemoEntry * mt_table ;
534
534
} PyMemoTable ;
535
535
@@ -573,8 +573,8 @@ typedef struct UnpicklerObject {
573
573
/* The unpickler memo is just an array of PyObject *s. Using a dict
574
574
is unnecessary, since the keys are contiguous ints. */
575
575
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 */
578
578
579
579
PyObject * pers_func ; /* persistent_load() method, can be NULL. */
580
580
@@ -658,7 +658,6 @@ PyMemoTable_New(void)
658
658
static PyMemoTable *
659
659
PyMemoTable_Copy (PyMemoTable * self )
660
660
{
661
- Py_ssize_t i ;
662
661
PyMemoTable * new = PyMemoTable_New ();
663
662
if (new == NULL )
664
663
return NULL ;
@@ -675,7 +674,7 @@ PyMemoTable_Copy(PyMemoTable *self)
675
674
PyErr_NoMemory ();
676
675
return NULL ;
677
676
}
678
- for (i = 0 ; i < self -> mt_allocated ; i ++ ) {
677
+ for (size_t i = 0 ; i < self -> mt_allocated ; i ++ ) {
679
678
Py_XINCREF (self -> mt_table [i ].me_key );
680
679
}
681
680
memcpy (new -> mt_table , self -> mt_table ,
@@ -721,7 +720,7 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
721
720
{
722
721
size_t i ;
723
722
size_t perturb ;
724
- size_t mask = ( size_t ) self -> mt_mask ;
723
+ size_t mask = self -> mt_mask ;
725
724
PyMemoEntry * table = self -> mt_table ;
726
725
PyMemoEntry * entry ;
727
726
Py_hash_t hash = (Py_hash_t )key >> 3 ;
@@ -743,22 +742,24 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
743
742
744
743
/* Returns -1 on failure, 0 on success. */
745
744
static int
746
- _PyMemoTable_ResizeTable (PyMemoTable * self , Py_ssize_t min_size )
745
+ _PyMemoTable_ResizeTable (PyMemoTable * self , size_t min_size )
747
746
{
748
747
PyMemoEntry * oldtable = NULL ;
749
748
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 ;
752
751
753
752
assert (min_size > 0 );
754
753
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 ) {
759
755
PyErr_NoMemory ();
760
756
return -1 ;
761
757
}
758
+
759
+ /* Find the smallest valid table size >= min_size. */
760
+ while (new_size < min_size ) {
761
+ new_size <<= 1 ;
762
+ }
762
763
/* new_size needs to be a power of two. */
763
764
assert ((new_size & (new_size - 1 )) == 0 );
764
765
@@ -808,6 +809,7 @@ static int
808
809
PyMemoTable_Set (PyMemoTable * self , PyObject * key , Py_ssize_t value )
809
810
{
810
811
PyMemoEntry * entry ;
812
+ size_t desired_size ;
811
813
812
814
assert (key != NULL );
813
815
@@ -831,10 +833,12 @@ PyMemoTable_Set(PyMemoTable *self, PyObject *key, Py_ssize_t value)
831
833
* Very large memo tables (over 50K items) use doubling instead.
832
834
* This may help applications with severe memory constraints.
833
835
*/
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 ) {
835
837
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 );
838
842
}
839
843
840
844
#undef MT_MINSIZE
@@ -1273,9 +1277,9 @@ _Unpickler_Readline(UnpicklerObject *self, char **result)
1273
1277
/* Returns -1 (with an exception set) on failure, 0 on success. The memo array
1274
1278
will be modified in place. */
1275
1279
static int
1276
- _Unpickler_ResizeMemoList (UnpicklerObject * self , Py_ssize_t new_size )
1280
+ _Unpickler_ResizeMemoList (UnpicklerObject * self , size_t new_size )
1277
1281
{
1278
- Py_ssize_t i ;
1282
+ size_t i ;
1279
1283
1280
1284
assert (new_size > self -> memo_size );
1281
1285
@@ -1292,9 +1296,9 @@ _Unpickler_ResizeMemoList(UnpicklerObject *self, Py_ssize_t new_size)
1292
1296
1293
1297
/* Returns NULL if idx is out of bounds. */
1294
1298
static PyObject *
1295
- _Unpickler_MemoGet (UnpicklerObject * self , Py_ssize_t idx )
1299
+ _Unpickler_MemoGet (UnpicklerObject * self , size_t idx )
1296
1300
{
1297
- if (idx < 0 || idx >= self -> memo_size )
1301
+ if (idx >= self -> memo_size )
1298
1302
return NULL ;
1299
1303
1300
1304
return self -> memo [idx ];
@@ -1303,7 +1307,7 @@ _Unpickler_MemoGet(UnpicklerObject *self, Py_ssize_t idx)
1303
1307
/* Returns -1 (with an exception set) on failure, 0 on success.
1304
1308
This takes its own reference to `value`. */
1305
1309
static int
1306
- _Unpickler_MemoPut (UnpicklerObject * self , Py_ssize_t idx , PyObject * value )
1310
+ _Unpickler_MemoPut (UnpicklerObject * self , size_t idx , PyObject * value )
1307
1311
{
1308
1312
PyObject * old_item ;
1309
1313
@@ -4194,14 +4198,13 @@ static PyObject *
4194
4198
_pickle_PicklerMemoProxy_copy_impl (PicklerMemoProxyObject * self )
4195
4199
/*[clinic end generated code: output=bb83a919d29225ef input=b73043485ac30b36]*/
4196
4200
{
4197
- Py_ssize_t i ;
4198
4201
PyMemoTable * memo ;
4199
4202
PyObject * new_memo = PyDict_New ();
4200
4203
if (new_memo == NULL )
4201
4204
return NULL ;
4202
4205
4203
4206
memo = self -> pickler -> memo ;
4204
- for (i = 0 ; i < memo -> mt_allocated ; ++ i ) {
4207
+ for (size_t i = 0 ; i < memo -> mt_allocated ; ++ i ) {
4205
4208
PyMemoEntry entry = memo -> mt_table [i ];
4206
4209
if (entry .me_key != NULL ) {
4207
4210
int status ;
@@ -6620,7 +6623,7 @@ static PyObject *
6620
6623
_pickle_UnpicklerMemoProxy_copy_impl (UnpicklerMemoProxyObject * self )
6621
6624
/*[clinic end generated code: output=e12af7e9bc1e4c77 input=97769247ce032c1d]*/
6622
6625
{
6623
- Py_ssize_t i ;
6626
+ size_t i ;
6624
6627
PyObject * new_memo = PyDict_New ();
6625
6628
if (new_memo == NULL )
6626
6629
return NULL ;
@@ -6771,8 +6774,7 @@ static int
6771
6774
Unpickler_set_memo (UnpicklerObject * self , PyObject * obj )
6772
6775
{
6773
6776
PyObject * * new_memo ;
6774
- Py_ssize_t new_memo_size = 0 ;
6775
- Py_ssize_t i ;
6777
+ size_t new_memo_size = 0 ;
6776
6778
6777
6779
if (obj == NULL ) {
6778
6780
PyErr_SetString (PyExc_TypeError ,
@@ -6789,7 +6791,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
6789
6791
if (new_memo == NULL )
6790
6792
return -1 ;
6791
6793
6792
- for (i = 0 ; i < new_memo_size ; i ++ ) {
6794
+ for (size_t i = 0 ; i < new_memo_size ; i ++ ) {
6793
6795
Py_XINCREF (unpickler -> memo [i ]);
6794
6796
new_memo [i ] = unpickler -> memo [i ];
6795
6797
}
@@ -6837,8 +6839,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
6837
6839
6838
6840
error :
6839
6841
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 -- ) {
6842
6843
Py_XDECREF (new_memo [i ]);
6843
6844
}
6844
6845
PyMem_FREE (new_memo );
0 commit comments