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

Side by Side Diff: Objects/sliceobject.c

Issue 14794: slice.indices raises OverflowError
Patch Set: Created 6 years, 11 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
« no previous file with comments | « 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 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 { 291 {
292 return PyUnicode_FromFormat("slice(%R, %R, %R)", r->start, r->stop, r->step) ; 292 return PyUnicode_FromFormat("slice(%R, %R, %R)", r->start, r->stop, r->step) ;
293 } 293 }
294 294
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
302 /* Helper function to convert a slice argument to a PyLong, and raise TypeError
303 with a suitable message on failure. */
304
305 static PyObject*
306 evaluate_slice_index(PyObject *v)
307 {
308 if (PyIndex_Check(v)) {
storchaka 2012/11/04 12:29:34 Why not EAFP? PyObject *index = PyNumber_Index(v)
309 return PyNumber_Index(v);
310 }
311 else {
312 PyErr_SetString(PyExc_TypeError,
313 "slice indices must be integers or "
314 "None or have an __index__ method");
315 return NULL;
316 }
317 }
318
319 /* Implementation of slice.indices. */
301 320
302 static PyObject* 321 static PyObject*
303 slice_indices(PySliceObject* self, PyObject* len) 322 slice_indices(PySliceObject* self, PyObject* len)
304 { 323 {
305 Py_ssize_t ilen, start, stop, step, slicelength; 324 PyObject *start=NULL, *stop=NULL, *step=NULL;
325 PyObject *length=NULL, *upper=NULL, *lower=NULL, *zero=NULL;
326 int step_is_negative, cmp;
306 327
307 ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError); 328 zero = PyLong_FromLong(0L);
329 if (zero == NULL)
330 return NULL;
308 331
309 if (ilen == -1 && PyErr_Occurred()) { 332 /* Compute step and length as integers. */
310 return NULL; 333 length = PyNumber_Index(len);
334 if (length == NULL)
335 goto error;
336
337 if (self->step == Py_None)
338 step = PyLong_FromLong(1L);
339 else
340 step = evaluate_slice_index(self->step);
341 if (step == NULL)
342 goto error;
343
344 /* Raise ValueError for negative length or zero step. */
345 cmp = PyObject_RichCompareBool(length, zero, Py_LT);
346 if (cmp < 0) {
347 goto error;
348 }
349 if (cmp) {
350 PyErr_SetString(PyExc_ValueError,
351 "length should not be negative");
352 goto error;
311 } 353 }
312 354
313 if (PySlice_GetIndicesEx((PyObject*)self, ilen, &start, &stop, 355 cmp = PyObject_RichCompareBool(step, zero, Py_EQ);
314 &step, &slicelength) < 0) { 356 if (cmp < 0) {
315 return NULL; 357 goto error;
358 }
359 if (cmp) {
360 PyErr_SetString(PyExc_ValueError,
361 "slice step cannot be zero");
362 goto error;
316 } 363 }
317 364
318 return Py_BuildValue("(nnn)", start, stop, step); 365 /* Find lower and upper bounds for start and stop. */
366 step_is_negative = PyObject_RichCompareBool(step, zero, Py_LT);
367 if (step_is_negative < 0) {
368 goto error;
369 }
370 if (step_is_negative) {
371 lower = PyLong_FromLong(-1L);
372 if (lower == NULL)
373 goto error;
374
375 upper = PyNumber_Add(length, lower);
376 if (upper == NULL)
377 goto error;
378 }
379 else {
380 lower = zero;
381 Py_INCREF(lower);
382 upper = length;
383 Py_INCREF(upper);
384 }
385
386 /* Compute start. */
387 if (self->start == Py_None) {
388 start = step_is_negative ? upper : lower;
389 Py_INCREF(start);
390 }
391 else {
392 start = evaluate_slice_index(self->start);
393 if (start == NULL)
394 goto error;
395
396 cmp = PyObject_RichCompareBool(start, zero, Py_LT);
397 if (cmp < 0)
398 goto error;
399 if (cmp) {
400 /* start += length */
401 PyObject *tmp = PyNumber_Add(start, length);
402 Py_DECREF(start);
403 start = tmp;
404 if (start == NULL)
405 goto error;
406
407 cmp = PyObject_RichCompareBool(start, lower, Py_LT);
408 if (cmp < 0)
409 goto error;
410 if (cmp) {
411 Py_INCREF(lower);
412 Py_DECREF(start);
413 start = lower;
414 }
415 }
416 else {
417 cmp = PyObject_RichCompareBool(start, upper, Py_GT);
418 if (cmp < 0)
419 goto error;
420 if (cmp) {
421 Py_INCREF(upper);
422 Py_DECREF(start);
423 start = upper;
424 }
425 }
426 }
427
428 /* Compute stop. */
429 if (self->stop == Py_None) {
430 stop = step_is_negative ? lower : upper;
431 Py_INCREF(stop);
432 }
433 else {
434 stop = evaluate_slice_index(self->stop);
435 if (stop == NULL)
436 goto error;
437
438 cmp = PyObject_RichCompareBool(stop, zero, Py_LT);
439 if (cmp < 0)
440 goto error;
441 if (cmp) {
442 /* stop += length */
443 PyObject *tmp = PyNumber_Add(stop, length);
444 Py_DECREF(stop);
445 stop = tmp;
446 if (stop == NULL)
447 goto error;
448
449 cmp = PyObject_RichCompareBool(stop, lower, Py_LT);
450 if (cmp < 0)
451 goto error;
452 if (cmp) {
453 Py_INCREF(lower);
454 Py_DECREF(stop);
455 stop = lower;
456 }
457 }
458 else {
459 cmp = PyObject_RichCompareBool(stop, upper, Py_GT);
460 if (cmp < 0)
461 goto error;
462 if (cmp) {
463 Py_INCREF(upper);
464 Py_DECREF(stop);
465 stop = upper;
466 }
467 }
468 }
469
470 Py_DECREF(upper);
471 Py_DECREF(lower);
472 Py_DECREF(length);
473 Py_DECREF(zero);
474 return Py_BuildValue("(NNN)", start, stop, step);
475
476 error:
477 Py_XDECREF(start);
478 Py_XDECREF(stop);
479 Py_XDECREF(step);
480 Py_XDECREF(upper);
481 Py_XDECREF(lower);
482 Py_XDECREF(length);
483 Py_XDECREF(zero);
484 return NULL;
319 } 485 }
486
320 487
321 PyDoc_STRVAR(slice_indices_doc, 488 PyDoc_STRVAR(slice_indices_doc,
322 "S.indices(len) -> (start, stop, stride)\n\ 489 "S.indices(len) -> (start, stop, stride)\n\
323 \n\ 490 \n\
324 Assuming a sequence of length len, calculate the start and stop\n\ 491 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\ 492 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\ 493 S. Out of bounds indices are clipped in a manner consistent with the\n\
327 handling of normal slices."); 494 handling of normal slices.");
328 495
329 static PyObject * 496 static PyObject *
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 0, /* tp_getset */ 600 0, /* tp_getset */
434 0, /* tp_base */ 601 0, /* tp_base */
435 0, /* tp_dict */ 602 0, /* tp_dict */
436 0, /* tp_descr_get */ 603 0, /* tp_descr_get */
437 0, /* tp_descr_set */ 604 0, /* tp_descr_set */
438 0, /* tp_dictoffset */ 605 0, /* tp_dictoffset */
439 0, /* tp_init */ 606 0, /* tp_init */
440 0, /* tp_alloc */ 607 0, /* tp_alloc */
441 slice_new, /* tp_new */ 608 slice_new, /* tp_new */
442 }; 609 };
OLDNEW
« no previous file with comments | « Lib/test/test_slice.py ('k') | no next file » | no next file with comments »

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