Skip to content

Commit 4246fe9

Browse files
authored
gh-99845: Change _PyDict_KeysSize() return type to size_t (#99848)
* Change _PyDict_KeysSize() and shared_keys_usable_size() return type from signed (Py_ssize_t) to unsigned (size_t) type. * new_values() argument type is now unsigned (size_t). * init_inline_values() now uses size_t rather than int for the 'i' iterator variable. * type.__sizeof__() implementation now uses unsigned (size_t) type.
1 parent 4cfc1b8 commit 4246fe9

File tree

3 files changed

+31
-35
lines changed

3 files changed

+31
-35
lines changed

Include/internal/pycore_dict.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ extern PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *);
3939
* Returns the version number, or zero if it was not possible to get a version number. */
4040
extern uint32_t _PyDictKeys_GetVersionForCurrentState(PyDictKeysObject *dictkeys);
4141

42-
extern Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys);
42+
extern size_t _PyDict_KeysSize(PyDictKeysObject *keys);
4343

4444
/* _Py_dict_lookup() returns index of entry which can be used like DK_ENTRIES(dk)[index].
4545
* -1 when no entry found, -3 when compare raises error.

Objects/dictobject.c

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -685,9 +685,9 @@ free_keys_object(PyDictKeysObject *keys)
685685
}
686686

687687
static inline PyDictValues*
688-
new_values(Py_ssize_t size)
688+
new_values(size_t size)
689689
{
690-
assert(size > 0);
690+
assert(size >= 1);
691691
size_t prefix_size = _Py_SIZE_ROUND_UP(size+2, sizeof(PyObject *));
692692
assert(prefix_size < 256);
693693
size_t n = prefix_size + size * sizeof(PyObject *);
@@ -746,27 +746,24 @@ new_dict(PyDictKeysObject *keys, PyDictValues *values, Py_ssize_t used, int free
746746
return (PyObject *)mp;
747747
}
748748

749-
static inline Py_ssize_t
749+
static inline size_t
750750
shared_keys_usable_size(PyDictKeysObject *keys)
751751
{
752-
return keys->dk_nentries + keys->dk_usable;
752+
return (size_t)keys->dk_nentries + (size_t)keys->dk_usable;
753753
}
754754

755755
/* Consumes a reference to the keys object */
756756
static PyObject *
757757
new_dict_with_shared_keys(PyDictKeysObject *keys)
758758
{
759-
PyDictValues *values;
760-
Py_ssize_t i, size;
761-
762-
size = shared_keys_usable_size(keys);
763-
values = new_values(size);
759+
size_t size = shared_keys_usable_size(keys);
760+
PyDictValues *values = new_values(size);
764761
if (values == NULL) {
765762
dictkeys_decref(keys);
766763
return PyErr_NoMemory();
767764
}
768765
((char *)values)[-2] = 0;
769-
for (i = 0; i < size; i++) {
766+
for (size_t i = 0; i < size; i++) {
770767
values->values[i] = NULL;
771768
}
772769
return new_dict(keys, values, 0, 1);
@@ -781,7 +778,7 @@ clone_combined_dict_keys(PyDictObject *orig)
781778
assert(orig->ma_values == NULL);
782779
assert(orig->ma_keys->dk_refcnt == 1);
783780

784-
Py_ssize_t keys_size = _PyDict_KeysSize(orig->ma_keys);
781+
size_t keys_size = _PyDict_KeysSize(orig->ma_keys);
785782
PyDictKeysObject *keys = PyObject_Malloc(keys_size);
786783
if (keys == NULL) {
787784
PyErr_NoMemory();
@@ -2959,7 +2956,6 @@ PyDict_Copy(PyObject *o)
29592956
{
29602957
PyObject *copy;
29612958
PyDictObject *mp;
2962-
Py_ssize_t i, n;
29632959

29642960
if (o == NULL || !PyDict_Check(o)) {
29652961
PyErr_BadInternalCall();
@@ -2974,9 +2970,8 @@ PyDict_Copy(PyObject *o)
29742970

29752971
if (_PyDict_HasSplitTable(mp)) {
29762972
PyDictObject *split_copy;
2977-
Py_ssize_t size = shared_keys_usable_size(mp->ma_keys);
2978-
PyDictValues *newvalues;
2979-
newvalues = new_values(size);
2973+
size_t size = shared_keys_usable_size(mp->ma_keys);
2974+
PyDictValues *newvalues = new_values(size);
29802975
if (newvalues == NULL)
29812976
return PyErr_NoMemory();
29822977
split_copy = PyObject_GC_New(PyDictObject, &PyDict_Type);
@@ -2991,7 +2986,7 @@ PyDict_Copy(PyObject *o)
29912986
split_copy->ma_used = mp->ma_used;
29922987
split_copy->ma_version_tag = DICT_NEXT_VERSION();
29932988
dictkeys_incref(mp->ma_keys);
2994-
for (i = 0, n = size; i < n; i++) {
2989+
for (size_t i = 0; i < size; i++) {
29952990
PyObject *value = mp->ma_values->values[i];
29962991
split_copy->ma_values->values[i] = Py_XNewRef(value);
29972992
}
@@ -3514,9 +3509,7 @@ static PyObject *dictiter_new(PyDictObject *, PyTypeObject *);
35143509
Py_ssize_t
35153510
_PyDict_SizeOf(PyDictObject *mp)
35163511
{
3517-
Py_ssize_t res;
3518-
3519-
res = _PyObject_SIZE(Py_TYPE(mp));
3512+
size_t res = _PyObject_SIZE(Py_TYPE(mp));
35203513
if (mp->ma_values) {
35213514
res += shared_keys_usable_size(mp->ma_keys) * sizeof(PyObject*);
35223515
}
@@ -3525,17 +3518,19 @@ _PyDict_SizeOf(PyDictObject *mp)
35253518
if (mp->ma_keys->dk_refcnt == 1) {
35263519
res += _PyDict_KeysSize(mp->ma_keys);
35273520
}
3528-
return res;
3521+
assert(res <= (size_t)PY_SSIZE_T_MAX);
3522+
return (Py_ssize_t)res;
35293523
}
35303524

3531-
Py_ssize_t
3525+
size_t
35323526
_PyDict_KeysSize(PyDictKeysObject *keys)
35333527
{
3534-
size_t es = keys->dk_kind == DICT_KEYS_GENERAL
3535-
? sizeof(PyDictKeyEntry) : sizeof(PyDictUnicodeEntry);
3536-
return (sizeof(PyDictKeysObject)
3537-
+ ((size_t)1 << keys->dk_log2_index_bytes)
3538-
+ USABLE_FRACTION(DK_SIZE(keys)) * es);
3528+
size_t es = (keys->dk_kind == DICT_KEYS_GENERAL
3529+
? sizeof(PyDictKeyEntry) : sizeof(PyDictUnicodeEntry));
3530+
size_t size = sizeof(PyDictKeysObject);
3531+
size += (size_t)1 << keys->dk_log2_index_bytes;
3532+
size += USABLE_FRACTION((size_t)DK_SIZE(keys)) * es;
3533+
return size;
35393534
}
35403535

35413536
static PyObject *
@@ -5286,16 +5281,15 @@ init_inline_values(PyObject *obj, PyTypeObject *tp)
52865281
if (keys->dk_usable > 1) {
52875282
keys->dk_usable--;
52885283
}
5289-
Py_ssize_t size = shared_keys_usable_size(keys);
5290-
assert(size > 0);
5284+
size_t size = shared_keys_usable_size(keys);
52915285
PyDictValues *values = new_values(size);
52925286
if (values == NULL) {
52935287
PyErr_NoMemory();
52945288
return -1;
52955289
}
5296-
assert(((uint8_t *)values)[-1] >= size+2);
5290+
assert(((uint8_t *)values)[-1] >= (size + 2));
52975291
((uint8_t *)values)[-2] = 0;
5298-
for (int i = 0; i < size; i++) {
5292+
for (size_t i = 0; i < size; i++) {
52995293
values->values[i] = NULL;
53005294
}
53015295
_PyDictOrValues_SetValues(_PyObject_DictOrValuesPointer(obj), values);
@@ -5335,7 +5329,8 @@ make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
53355329
dictkeys_incref(keys);
53365330
Py_ssize_t used = 0;
53375331
Py_ssize_t track = 0;
5338-
for (Py_ssize_t i = 0; i < shared_keys_usable_size(keys); i++) {
5332+
size_t size = shared_keys_usable_size(keys);
5333+
for (size_t i = 0; i < size; i++) {
53395334
PyObject *val = values->values[i];
53405335
if (val != NULL) {
53415336
used += 1;

Objects/typeobject.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4680,16 +4680,17 @@ static PyObject *
46804680
type___sizeof___impl(PyTypeObject *self)
46814681
/*[clinic end generated code: output=766f4f16cd3b1854 input=99398f24b9cf45d6]*/
46824682
{
4683-
Py_ssize_t size;
4683+
size_t size;
46844684
if (self->tp_flags & Py_TPFLAGS_HEAPTYPE) {
46854685
PyHeapTypeObject* et = (PyHeapTypeObject*)self;
46864686
size = sizeof(PyHeapTypeObject);
46874687
if (et->ht_cached_keys)
46884688
size += _PyDict_KeysSize(et->ht_cached_keys);
46894689
}
4690-
else
4690+
else {
46914691
size = sizeof(PyTypeObject);
4692-
return PyLong_FromSsize_t(size);
4692+
}
4693+
return PyLong_FromSize_t(size);
46934694
}
46944695

46954696
static PyMethodDef type_methods[] = {

0 commit comments

Comments
 (0)