Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 309aa2d

Browse files
committed
Keep PyLong_AsLongAndOverflow documentation and implementation in sync
between py3k and trunk; merge new tests from trunk to py3k. (See issue #7528.)
1 parent 6193aee commit 309aa2d

3 files changed

Lines changed: 184 additions & 13 deletions

File tree

Doc/c-api/long.rst

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,13 @@ All integers are implemented as "long" integer objects of arbitrary size.
121121

122122
.. cfunction:: long PyLong_AsLongAndOverflow(PyObject *pylong, int* overflow)
123123

124-
Return a C :ctype:`long` representation of the contents of *pylong*. If
125-
*pylong* is greater than :const:`LONG_MAX`, return -1 and
126-
set `*overflow` to 1 (for overflow) or -1 (for underflow).
127-
If an exception is set because of type errors, also return -1.
124+
Return a C :ctype:`long` representation of the contents of
125+
*pylong*. If *pylong* is greater than :const:`LONG_MAX` or less
126+
than :const:`LONG_MIN`, set `*overflow` to ``1`` or ``-1``,
127+
respectively, and return ``-1``; otherwise, set `*overflow` to
128+
``0``. If any other exception occurs (for example a TypeError or
129+
MemoryError), then ``-1`` will be returned and ``*overflow`` will
130+
be ``0``.
128131

129132

130133
.. cfunction:: Py_ssize_t PyLong_AsSsize_t(PyObject *pylong)

Modules/_testcapimodule.c

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,171 @@ test_longlong_api(PyObject* self, PyObject *args)
359359
#undef F_U_TO_PY
360360
#undef F_PY_TO_U
361361

362+
/* Test the PyLong_AsLongAndOverflow API. General conversion to PY_LONG
363+
is tested by test_long_api_inner. This test will concentrate on proper
364+
handling of overflow.
365+
*/
366+
367+
static PyObject *
368+
test_long_and_overflow(PyObject *self)
369+
{
370+
PyObject *num, *one, *temp;
371+
long value;
372+
int overflow;
373+
374+
/* Test that overflow is set properly for a large value. */
375+
/* num is a number larger than LONG_MAX even on 64-bit platforms */
376+
num = PyLong_FromString("FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16);
377+
if (num == NULL)
378+
return NULL;
379+
overflow = 1234;
380+
value = PyLong_AsLongAndOverflow(num, &overflow);
381+
Py_DECREF(num);
382+
if (value == -1 && PyErr_Occurred())
383+
return NULL;
384+
if (value != -1)
385+
return raiseTestError("test_long_and_overflow",
386+
"return value was not set to -1");
387+
if (overflow != 1)
388+
return raiseTestError("test_long_and_overflow",
389+
"overflow was not set to 1");
390+
391+
/* Same again, with num = LONG_MAX + 1 */
392+
num = PyLong_FromLong(LONG_MAX);
393+
if (num == NULL)
394+
return NULL;
395+
one = PyLong_FromLong(1L);
396+
if (one == NULL) {
397+
Py_DECREF(num);
398+
return NULL;
399+
}
400+
temp = PyNumber_Add(num, one);
401+
Py_DECREF(one);
402+
Py_DECREF(num);
403+
num = temp;
404+
if (num == NULL)
405+
return NULL;
406+
overflow = 0;
407+
value = PyLong_AsLongAndOverflow(num, &overflow);
408+
Py_DECREF(num);
409+
if (value == -1 && PyErr_Occurred())
410+
return NULL;
411+
if (value != -1)
412+
return raiseTestError("test_long_and_overflow",
413+
"return value was not set to -1");
414+
if (overflow != 1)
415+
return raiseTestError("test_long_and_overflow",
416+
"overflow was not set to 1");
417+
418+
/* Test that overflow is set properly for a large negative value. */
419+
/* num is a number smaller than LONG_MIN even on 64-bit platforms */
420+
num = PyLong_FromString("-FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16);
421+
if (num == NULL)
422+
return NULL;
423+
overflow = 1234;
424+
value = PyLong_AsLongAndOverflow(num, &overflow);
425+
Py_DECREF(num);
426+
if (value == -1 && PyErr_Occurred())
427+
return NULL;
428+
if (value != -1)
429+
return raiseTestError("test_long_and_overflow",
430+
"return value was not set to -1");
431+
if (overflow != -1)
432+
return raiseTestError("test_long_and_overflow",
433+
"overflow was not set to -1");
434+
435+
/* Same again, with num = LONG_MIN - 1 */
436+
num = PyLong_FromLong(LONG_MIN);
437+
if (num == NULL)
438+
return NULL;
439+
one = PyLong_FromLong(1L);
440+
if (one == NULL) {
441+
Py_DECREF(num);
442+
return NULL;
443+
}
444+
temp = PyNumber_Subtract(num, one);
445+
Py_DECREF(one);
446+
Py_DECREF(num);
447+
num = temp;
448+
if (num == NULL)
449+
return NULL;
450+
overflow = 0;
451+
value = PyLong_AsLongAndOverflow(num, &overflow);
452+
Py_DECREF(num);
453+
if (value == -1 && PyErr_Occurred())
454+
return NULL;
455+
if (value != -1)
456+
return raiseTestError("test_long_and_overflow",
457+
"return value was not set to -1");
458+
if (overflow != -1)
459+
return raiseTestError("test_long_and_overflow",
460+
"overflow was not set to -1");
461+
462+
/* Test that overflow is cleared properly for small values. */
463+
num = PyLong_FromString("FF", NULL, 16);
464+
if (num == NULL)
465+
return NULL;
466+
overflow = 1234;
467+
value = PyLong_AsLongAndOverflow(num, &overflow);
468+
Py_DECREF(num);
469+
if (value == -1 && PyErr_Occurred())
470+
return NULL;
471+
if (value != 0xFF)
472+
return raiseTestError("test_long_and_overflow",
473+
"expected return value 0xFF");
474+
if (overflow != 0)
475+
return raiseTestError("test_long_and_overflow",
476+
"overflow was not cleared");
477+
478+
num = PyLong_FromString("-FF", NULL, 16);
479+
if (num == NULL)
480+
return NULL;
481+
overflow = 0;
482+
value = PyLong_AsLongAndOverflow(num, &overflow);
483+
Py_DECREF(num);
484+
if (value == -1 && PyErr_Occurred())
485+
return NULL;
486+
if (value != -0xFF)
487+
return raiseTestError("test_long_and_overflow",
488+
"expected return value 0xFF");
489+
if (overflow != 0)
490+
return raiseTestError("test_long_and_overflow",
491+
"overflow was set incorrectly");
492+
493+
num = PyLong_FromLong(LONG_MAX);
494+
if (num == NULL)
495+
return NULL;
496+
overflow = 1234;
497+
value = PyLong_AsLongAndOverflow(num, &overflow);
498+
Py_DECREF(num);
499+
if (value == -1 && PyErr_Occurred())
500+
return NULL;
501+
if (value != LONG_MAX)
502+
return raiseTestError("test_long_and_overflow",
503+
"expected return value LONG_MAX");
504+
if (overflow != 0)
505+
return raiseTestError("test_long_and_overflow",
506+
"overflow was not cleared");
507+
508+
num = PyLong_FromLong(LONG_MIN);
509+
if (num == NULL)
510+
return NULL;
511+
overflow = 0;
512+
value = PyLong_AsLongAndOverflow(num, &overflow);
513+
Py_DECREF(num);
514+
if (value == -1 && PyErr_Occurred())
515+
return NULL;
516+
if (value != LONG_MIN)
517+
return raiseTestError("test_long_and_overflow",
518+
"expected return value LONG_MIN");
519+
if (overflow != 0)
520+
return raiseTestError("test_long_and_overflow",
521+
"overflow was not cleared");
522+
523+
Py_INCREF(Py_None);
524+
return Py_None;
525+
}
526+
362527
/* Test the L code for PyArg_ParseTuple. This should deliver a PY_LONG_LONG
363528
for both long and int arguments. The test may leak a little memory if
364529
it fails.
@@ -1560,6 +1725,8 @@ static PyMethodDef TestMethods[] = {
15601725
{"test_dict_iteration", (PyCFunction)test_dict_iteration,METH_NOARGS},
15611726
{"test_lazy_hash_inheritance", (PyCFunction)test_lazy_hash_inheritance,METH_NOARGS},
15621727
{"test_long_api", (PyCFunction)test_long_api, METH_NOARGS},
1728+
{"test_long_and_overflow", (PyCFunction)test_long_and_overflow,
1729+
METH_NOARGS},
15631730
{"test_long_numbits", (PyCFunction)test_long_numbits, METH_NOARGS},
15641731
{"test_k_code", (PyCFunction)test_k_code, METH_NOARGS},
15651732
{"test_empty_argparse", (PyCFunction)test_empty_argparse,METH_NOARGS},

Objects/longobject.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,10 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
346346

347347
if (!PyLong_Check(vv)) {
348348
PyNumberMethods *nb;
349-
if ((nb = vv->ob_type->tp_as_number) == NULL ||
350-
nb->nb_int == NULL) {
351-
PyErr_SetString(PyExc_TypeError, "an integer is required");
349+
nb = vv->ob_type->tp_as_number;
350+
if (nb == NULL || nb->nb_int == NULL) {
351+
PyErr_SetString(PyExc_TypeError,
352+
"an integer is required");
352353
return -1;
353354
}
354355
vv = (*nb->nb_int) (vv);
@@ -388,23 +389,23 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
388389
prev = x;
389390
x = (x << PyLong_SHIFT) | v->ob_digit[i];
390391
if ((x >> PyLong_SHIFT) != prev) {
391-
*overflow = Py_SIZE(v) > 0 ? 1 : -1;
392+
*overflow = sign;
392393
goto exit;
393394
}
394395
}
395-
/* Haven't lost any bits, but casting to long requires extra care
396-
* (see comment above).
397-
*/
396+
/* Haven't lost any bits, but casting to long requires extra
397+
* care (see comment above).
398+
*/
398399
if (x <= (unsigned long)LONG_MAX) {
399400
res = (long)x * sign;
400401
}
401402
else if (sign < 0 && x == PY_ABS_LONG_MIN) {
402403
res = LONG_MIN;
403404
}
404405
else {
405-
*overflow = Py_SIZE(v) > 0 ? 1 : -1;
406+
*overflow = sign;
406407
/* res is already set to -1 */
407-
}
408+
}
408409
}
409410
exit:
410411
if (do_decref) {

0 commit comments

Comments
 (0)