Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(33239)

Side by Side Diff: Objects/sliceobject.c

Issue 14794: slice.indices raises OverflowError
Patch Set: Created 6 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« Lib/test/test_slice.py ('K') | « Lib/test/test_slice.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 Written by Jim Hugunin and Chris Chase. 2 Written by Jim Hugunin and Chris Chase.
3 3
4 This includes both the singular ellipsis object and slice objects. 4 This includes both the singular ellipsis object and slice objects.
5 5
6 Guido, feel free to do whatever you want in the way of copyrights 6 Guido, feel free to do whatever you want in the way of copyrights
7 for this file. 7 for this file.
8 */ 8 */
9 9
10 /* 10 /*
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 static PyMemberDef slice_members[] = { 295 static PyMemberDef slice_members[] = {
296 {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY}, 296 {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
297 {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY}, 297 {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
298 {"step", T_OBJECT, offsetof(PySliceObject, step), READONLY}, 298 {"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
299 {0} 299 {0}
300 }; 300 };
301 301
302 static PyObject* 302 static PyObject*
303 slice_indices(PySliceObject* self, PyObject* len) 303 slice_indices(PySliceObject* self, PyObject* len)
304 { 304 {
305 Py_ssize_t ilen, start, stop, step, slicelength; 305 /* Version that works for arbitrarily large start, stop, step and
306 * length. */
307 /* To do: reinstate old version as an optimization for the small-int case.
308 (And do some timings to find out if it's even worth keeping that
309 optimization.) */
310 /* To do: error case for negative length. */
306 311
307 ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError); 312 PyObject *start=NULL, *stop=NULL, *step=NULL;
313 PyObject *length=NULL, *upper=NULL, *lower=NULL, *zero=NULL;
314 int step_is_negative, stop_is_negative, start_is_negative, cmp;
308 315
storchaka 2012/11/03 21:56:32 You can move start_is_negative and stop_is_negativ
mark.dickinson 2012/11/03 23:14:48 Thanks. Will do.
309 if (ilen == -1 && PyErr_Occurred()) { 316 /* We'll need 0 later to determine whether start and stop are negative. */
317 zero = PyLong_FromLong(0L);
318 if (zero == NULL)
310 return NULL; 319 return NULL;
320
321 /* Compute step and length as integers. */
322 length = PyNumber_Index(len);
323 if (length == NULL)
324 goto error;
325
326 if (self->step == Py_None)
327 step = PyLong_FromLong(1L);
328 else
329 step = PyNumber_Index(self->step);
330 if (step == NULL)
331 goto error;
332
333 /* Raise ValueError for negative length or zero step. */
334 cmp = PyObject_RichCompareBool(length, zero, Py_LT);
335 if (cmp < 0) {
336 goto error;
337 }
338 else if (cmp) {
339 PyErr_SetString(PyExc_ValueError,
340 "length should not be negative");
341 goto error;
311 } 342 }
312 343
313 if (PySlice_GetIndicesEx((PyObject*)self, ilen, &start, &stop, 344 cmp = PyObject_RichCompareBool(step, zero, Py_EQ);
314 &step, &slicelength) < 0) { 345 if (cmp < 0) {
315 return NULL; 346 goto error;
347 }
348 else if (cmp) {
349 PyErr_SetString(PyExc_ValueError,
350 "slice step cannot be zero");
351 goto error;
316 } 352 }
317 353
318 return Py_BuildValue("(nnn)", start, stop, step); 354 /* Find lower and upper bounds for start and stop. */
355 step_is_negative = PyObject_RichCompareBool(step, zero, Py_LT);
356 if (step_is_negative < 0) {
357 goto error;
358 }
359 else if (step_is_negative) {
360 lower = PyLong_FromLong(-1L);
361 if (lower == NULL)
362 goto error;
363
364 upper = PyNumber_Add(length, lower);
365 if (upper == NULL)
366 goto error;
367 }
368 else {
369 lower = zero;
370 Py_INCREF(lower);
371 upper = length;
372 Py_INCREF(upper);
373 }
374
375 /* Compute start. */
376 if (self->start == Py_None) {
377 start = step_is_negative ? upper : lower;
378 Py_INCREF(start);
379 }
380 else {
381 PyObject *start_as_int = PyNumber_Index(self->start);
382 if (start_as_int == NULL)
383 goto error;
384
storchaka 2012/11/03 21:56:32 There is a suggestion. Add "start = start_as_int;
mark.dickinson 2012/11/03 23:14:48 Ah, good suggestion. I'll update the patch; than
385 start_is_negative = PyObject_RichCompareBool(start_as_int, zero, Py_LT);
386 if (start_is_negative < 0) {
387 Py_DECREF(start_as_int);
388 goto error;
389 }
390 else if (start_is_negative) {
391 PyObject *tmp = PyNumber_Add(start_as_int, length);
392 Py_DECREF(start_as_int);
393 start_as_int = tmp;
394 if (start_as_int == NULL)
395 goto error;
396
397 cmp = PyObject_RichCompareBool(start_as_int, lower, Py_LE);
398 if (cmp < 0)
399 goto error;
storchaka 2012/11/03 21:56:32 Py_DECREF(start_as_int);
mark.dickinson 2012/11/03 23:14:48 Got it (and the other missing DECREFs below). Tha
400 else if (cmp)
401 start = lower;
402 else
403 start = start_as_int;
404 }
405 else {
406 cmp = PyObject_RichCompareBool(start_as_int, upper, Py_GE);
407 if (cmp < 0)
408 goto error;
storchaka 2012/11/03 21:56:32 Py_DECREF(start_as_int);
409 else if (cmp)
410 start = upper;
411 else
412 start = start_as_int;
413 }
414 Py_INCREF(start);
415 Py_DECREF(start_as_int);
416 }
417
418 /* Compute stop. */
419 if (self->stop == Py_None) {
420 stop = step_is_negative ? lower : upper;
421 Py_INCREF(stop);
422 }
423 else {
424 PyObject *stop_as_int = PyNumber_Index(self->stop);
425 if (stop_as_int == NULL)
426 goto error;
427
storchaka 2012/11/03 21:56:32 Same suggestion as for start_as_int.
428 stop_is_negative = PyObject_RichCompareBool(stop_as_int, zero, Py_LT);
429 if (stop_is_negative < 0) {
430 Py_DECREF(stop_as_int);
431 goto error;
432 }
433 else if (stop_is_negative) {
434 PyObject *tmp = PyNumber_Add(stop_as_int, length);
435 Py_DECREF(stop_as_int);
436 stop_as_int = tmp;
437 if (stop_as_int == NULL)
438 goto error;
439
440 cmp = PyObject_RichCompareBool(stop_as_int, lower, Py_LE);
441 if (cmp < 0)
442 goto error;
storchaka 2012/11/03 21:56:32 Py_DECREF(stop_as_int);
443 else if (cmp)
444 stop = lower;
445 else
446 stop = stop_as_int;
447 }
448 else {
449 cmp = PyObject_RichCompareBool(stop_as_int, upper, Py_GE);
450 if (cmp < 0)
451 goto error;
storchaka 2012/11/03 21:56:32 Py_DECREF(stop_as_int);
452 else if (cmp)
453 stop = upper;
454 else
455 stop = stop_as_int;
456 }
457 Py_INCREF(stop);
458 Py_DECREF(stop_as_int);
459 }
460 Py_DECREF(upper);
461 Py_DECREF(lower);
462 Py_DECREF(length);
463 Py_DECREF(zero);
464 return Py_BuildValue("(NNN)", start, stop, step);
465
466 error:
467 Py_XDECREF(start);
468 Py_XDECREF(stop);
469 Py_XDECREF(step);
470 Py_XDECREF(upper);
471 Py_XDECREF(lower);
472 Py_XDECREF(length);
473 Py_XDECREF(zero);
474 return NULL;
319 } 475 }
476
320 477
321 PyDoc_STRVAR(slice_indices_doc, 478 PyDoc_STRVAR(slice_indices_doc,
322 "S.indices(len) -> (start, stop, stride)\n\ 479 "S.indices(len) -> (start, stop, stride)\n\
323 \n\ 480 \n\
324 Assuming a sequence of length len, calculate the start and stop\n\ 481 Assuming a sequence of length len, calculate the start and stop\n\
325 indices, and the stride length of the extended slice described by\n\ 482 indices, and the stride length of the extended slice described by\n\
326 S. Out of bounds indices are clipped in a manner consistent with the\n\ 483 S. Out of bounds indices are clipped in a manner consistent with the\n\
327 handling of normal slices."); 484 handling of normal slices.");
328 485
329 static PyObject * 486 static PyObject *
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 0, /* tp_getset */ 590 0, /* tp_getset */
434 0, /* tp_base */ 591 0, /* tp_base */
435 0, /* tp_dict */ 592 0, /* tp_dict */
436 0, /* tp_descr_get */ 593 0, /* tp_descr_get */
437 0, /* tp_descr_set */ 594 0, /* tp_descr_set */
438 0, /* tp_dictoffset */ 595 0, /* tp_dictoffset */
439 0, /* tp_init */ 596 0, /* tp_init */
440 0, /* tp_alloc */ 597 0, /* tp_alloc */
441 slice_new, /* tp_new */ 598 slice_new, /* tp_new */
442 }; 599 };
OLDNEW
« Lib/test/test_slice.py ('K') | « Lib/test/test_slice.py ('k') | no next file » | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+