Skip to content

Commit b2a5be0

Browse files
Issue python#27867: Function PySlice_GetIndicesEx() is replaced with a macro if
Py_LIMITED_API is not set or set to the value between 0x03050400 and 0x03060000 (not including) or 0x03060100 or higher.
1 parent 07a1f65 commit b2a5be0

4 files changed

Lines changed: 74 additions & 26 deletions

File tree

Include/sliceobject.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,20 @@ PyAPI_FUNC(int) _PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
4141
PyAPI_FUNC(int) PySlice_GetIndices(PyObject *r, Py_ssize_t length,
4242
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step);
4343
PyAPI_FUNC(int) PySlice_GetIndicesEx(PyObject *r, Py_ssize_t length,
44-
Py_ssize_t *start, Py_ssize_t *stop,
45-
Py_ssize_t *step, Py_ssize_t *slicelength);
44+
Py_ssize_t *start, Py_ssize_t *stop,
45+
Py_ssize_t *step, Py_ssize_t *slicelength);
46+
47+
#if !defined(Py_LIMITED_API) || (Py_LIMITED_API+0 >= 0x03050400 && Py_LIMITED_API+0 < 0x03060000) || Py_LIMITED_API+0 >= 0x03060100
48+
#define PySlice_GetIndicesEx(slice, length, start, stop, step, slicelen) ( \
49+
PySlice_Unpack((slice), (start), (stop), (step)) < 0 ? -1 : \
50+
((*slicelen = PySlice_AdjustIndices((length), (start), (stop), *(step))), \
51+
0))
52+
PyAPI_FUNC(int) PySlice_Unpack(PyObject *slice,
53+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step);
54+
PyAPI_FUNC(Py_ssize_t) PySlice_AdjustIndices(Py_ssize_t length,
55+
Py_ssize_t *start, Py_ssize_t *stop,
56+
Py_ssize_t step);
57+
#endif
4658

4759
#ifdef __cplusplus
4860
}

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ Library
4040
C API
4141
-----
4242

43+
- Issue #27867: Function PySlice_GetIndicesEx() is replaced with a macro if
44+
Py_LIMITED_API is not set or set to the value between 0x03050400
45+
and 0x03060000 (not including) or 0x03060100 or higher.
46+
4347
- Issue #29083: Fixed the declaration of some public API functions.
4448
PyArg_VaParse() and PyArg_VaParseTupleAndKeywords() were not available in
4549
limited API. PyArg_ValidateKeywordArguments(), PyArg_UnpackTuple() and

Objects/sliceobject.c

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -191,15 +191,12 @@ PySlice_GetIndices(PyObject *_r, Py_ssize_t length,
191191
}
192192

193193
int
194-
PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
195-
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
196-
Py_ssize_t *slicelength)
194+
PySlice_Unpack(PyObject *_r,
195+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
197196
{
198197
PySliceObject *r = (PySliceObject*)_r;
199198
/* this is harder to get right than you might think */
200199

201-
Py_ssize_t defstart, defstop;
202-
203200
if (r->step == Py_None) {
204201
*step = 1;
205202
}
@@ -219,42 +216,75 @@ PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
219216
*step = -PY_SSIZE_T_MAX;
220217
}
221218

222-
defstart = *step < 0 ? length-1 : 0;
223-
defstop = *step < 0 ? -1 : length;
224-
225219
if (r->start == Py_None) {
226-
*start = defstart;
220+
*start = *step < 0 ? PY_SSIZE_T_MAX-1 : 0;;
227221
}
228222
else {
229223
if (!_PyEval_SliceIndex(r->start, start)) return -1;
230-
if (*start < 0) *start += length;
231-
if (*start < 0) *start = (*step < 0) ? -1 : 0;
232-
if (*start >= length)
233-
*start = (*step < 0) ? length - 1 : length;
234224
}
235225

236226
if (r->stop == Py_None) {
237-
*stop = defstop;
227+
*stop = *step < 0 ? -PY_SSIZE_T_MAX : PY_SSIZE_T_MAX;
238228
}
239229
else {
240230
if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
241-
if (*stop < 0) *stop += length;
242-
if (*stop < 0) *stop = (*step < 0) ? -1 : 0;
243-
if (*stop >= length)
244-
*stop = (*step < 0) ? length - 1 : length;
245231
}
246232

247-
if ((*step < 0 && *stop >= *start)
248-
|| (*step > 0 && *start >= *stop)) {
249-
*slicelength = 0;
233+
return 0;
234+
}
235+
236+
Py_ssize_t
237+
PySlice_AdjustIndices(Py_ssize_t length,
238+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step)
239+
{
240+
/* this is harder to get right than you might think */
241+
242+
assert(step != 0);
243+
assert(step >= -PY_SSIZE_T_MAX);
244+
245+
if (*start < 0) {
246+
*start += length;
247+
if (*start < 0) {
248+
*start = (step < 0) ? -1 : 0;
249+
}
250250
}
251-
else if (*step < 0) {
252-
*slicelength = (*stop-*start+1)/(*step)+1;
251+
else if (*start >= length) {
252+
*start = (step < 0) ? length - 1 : length;
253+
}
254+
255+
if (*stop < 0) {
256+
*stop += length;
257+
if (*stop < 0) {
258+
*stop = (step < 0) ? -1 : 0;
259+
}
260+
}
261+
else if (*stop >= length) {
262+
*stop = (step < 0) ? length - 1 : length;
263+
}
264+
265+
if (step < 0) {
266+
if (*stop < *start) {
267+
return (*start - *stop - 1) / (-step) + 1;
268+
}
253269
}
254270
else {
255-
*slicelength = (*stop-*start-1)/(*step)+1;
271+
if (*start < *stop) {
272+
return (*stop - *start - 1) / step + 1;
273+
}
256274
}
275+
return 0;
276+
}
277+
278+
#undef PySlice_GetIndicesEx
257279

280+
int
281+
PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
282+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
283+
Py_ssize_t *slicelength)
284+
{
285+
if (PySlice_Unpack(_r, start, stop, step) < 0)
286+
return -1;
287+
*slicelength = PySlice_AdjustIndices(length, start, stop, *step);
258288
return 0;
259289
}
260290

PC/python3.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,10 +527,12 @@ EXPORTS
527527
PySet_Pop=python35.PySet_Pop
528528
PySet_Size=python35.PySet_Size
529529
PySet_Type=python35.PySet_Type DATA
530+
PySlice_AdjustIndices=python35.PySlice_AdjustIndices
530531
PySlice_GetIndices=python35.PySlice_GetIndices
531532
PySlice_GetIndicesEx=python35.PySlice_GetIndicesEx
532533
PySlice_New=python35.PySlice_New
533534
PySlice_Type=python35.PySlice_Type DATA
535+
PySlice_Unpack=python35.PySlice_Unpack
534536
PySortWrapper_Type=python35.PySortWrapper_Type DATA
535537
PyState_AddModule=python35.PyState_AddModule
536538
PyState_FindModule=python35.PyState_FindModule

0 commit comments

Comments
 (0)