bpo-29816: Shift operation now has less opportunity to raise Overflow… · python/cpython@918403c (original) (raw)
`@@ -4277,15 +4277,54 @@ long_bool(PyLongObject *v)
`
4277
4277
`return Py_SIZE(v) != 0;
`
4278
4278
`}
`
4279
4279
``
``
4280
`+
/* wordshift, remshift = divmod(shiftby, PyLong_SHIFT) */
`
``
4281
`+
static int
`
``
4282
`+
divmod_shift(PyLongObject *shiftby, Py_ssize_t *wordshift, digit *remshift)
`
``
4283
`+
{
`
``
4284
`+
assert(PyLong_Check((PyObject *)shiftby));
`
``
4285
`+
assert(Py_SIZE(shiftby) >= 0);
`
``
4286
`+
Py_ssize_t lshiftby = PyLong_AsSsize_t((PyObject *)shiftby);
`
``
4287
`+
if (lshiftby >= 0) {
`
``
4288
`+
*wordshift = lshiftby / PyLong_SHIFT;
`
``
4289
`+
*remshift = lshiftby % PyLong_SHIFT;
`
``
4290
`+
return 0;
`
``
4291
`+
}
`
``
4292
`+
/* PyLong_Check(shiftby) is true and Py_SIZE(shiftby) >= 0, so it must
`
``
4293
`+
be that PyLong_AsSsize_t raised an OverflowError. */
`
``
4294
`+
assert(PyErr_ExceptionMatches(PyExc_OverflowError));
`
``
4295
`+
PyErr_Clear();
`
``
4296
`+
PyLongObject *wordshift_obj = divrem1(shiftby, PyLong_SHIFT, remshift);
`
``
4297
`+
if (wordshift_obj == NULL) {
`
``
4298
`+
return -1;
`
``
4299
`+
}
`
``
4300
`+
*wordshift = PyLong_AsSsize_t((PyObject *)wordshift_obj);
`
``
4301
`+
Py_DECREF(wordshift_obj);
`
``
4302
`+
if (*wordshift >= 0 && *wordshift < PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(digit)) {
`
``
4303
`+
return 0;
`
``
4304
`+
}
`
``
4305
`+
PyErr_Clear();
`
``
4306
`+
/* Clip the value. With such large wordshift the right shift
`
``
4307
`+
returns 0 and the left shift raises an error in _PyLong_New(). */
`
``
4308
`+
*wordshift = PY_SSIZE_T_MAX / sizeof(digit);
`
``
4309
`+
*remshift = 0;
`
``
4310
`+
return 0;
`
``
4311
`+
}
`
``
4312
+
4280
4313
`static PyObject *
`
4281
4314
`long_rshift(PyLongObject *a, PyLongObject *b)
`
4282
4315
`{
`
4283
4316
`PyLongObject *z = NULL;
`
4284
``
`-
Py_ssize_t shiftby, newsize, wordshift, loshift, hishift, i, j;
`
4285
``
`-
digit lomask, himask;
`
``
4317
`+
Py_ssize_t newsize, wordshift, hishift, i, j;
`
``
4318
`+
digit loshift, lomask, himask;
`
4286
4319
``
4287
4320
`CHECK_BINOP(a, b);
`
4288
4321
``
``
4322
`+
if (Py_SIZE(b) < 0) {
`
``
4323
`+
PyErr_SetString(PyExc_ValueError,
`
``
4324
`+
"negative shift count");
`
``
4325
`+
return NULL;
`
``
4326
`+
}
`
``
4327
+
4289
4328
`if (Py_SIZE(a) < 0) {
`
4290
4329
`/* Right shifting negative numbers is harder */
`
4291
4330
`PyLongObject *a1, *a2;
`
`@@ -4300,19 +4339,11 @@ long_rshift(PyLongObject *a, PyLongObject *b)
`
4300
4339
`Py_DECREF(a2);
`
4301
4340
` }
`
4302
4341
`else {
`
4303
``
`-
shiftby = PyLong_AsSsize_t((PyObject *)b);
`
4304
``
`-
if (shiftby == -1L && PyErr_Occurred())
`
4305
``
`-
return NULL;
`
4306
``
`-
if (shiftby < 0) {
`
4307
``
`-
PyErr_SetString(PyExc_ValueError,
`
4308
``
`-
"negative shift count");
`
``
4342
`+
if (divmod_shift(b, &wordshift, &loshift) < 0)
`
4309
4343
`return NULL;
`
4310
``
`-
}
`
4311
``
`-
wordshift = shiftby / PyLong_SHIFT;
`
4312
``
`-
newsize = Py_ABS(Py_SIZE(a)) - wordshift;
`
``
4344
`+
newsize = Py_SIZE(a) - wordshift;
`
4313
4345
`if (newsize <= 0)
`
4314
4346
`return PyLong_FromLong(0);
`
4315
``
`-
loshift = shiftby % PyLong_SHIFT;
`
4316
4347
`hishift = PyLong_SHIFT - loshift;
`
4317
4348
`lomask = ((digit)1 << hishift) - 1;
`
4318
4349
`himask = PyLong_MASK ^ lomask;
`
`@@ -4336,27 +4367,22 @@ long_lshift(PyObject *v, PyObject *w)
`
4336
4367
`PyLongObject a = (PyLongObject)v;
`
4337
4368
`PyLongObject b = (PyLongObject)w;
`
4338
4369
`PyLongObject *z = NULL;
`
4339
``
`-
Py_ssize_t shiftby, oldsize, newsize, wordshift, remshift, i, j;
`
``
4370
`+
Py_ssize_t oldsize, newsize, wordshift, i, j;
`
``
4371
`+
digit remshift;
`
4340
4372
`twodigits accum;
`
4341
4373
``
4342
4374
`CHECK_BINOP(a, b);
`
4343
4375
``
4344
``
`-
shiftby = PyLong_AsSsize_t((PyObject *)b);
`
4345
``
`-
if (shiftby == -1L && PyErr_Occurred())
`
4346
``
`-
return NULL;
`
4347
``
`-
if (shiftby < 0) {
`
``
4376
`+
if (Py_SIZE(b) < 0) {
`
4348
4377
`PyErr_SetString(PyExc_ValueError, "negative shift count");
`
4349
4378
`return NULL;
`
4350
4379
` }
`
4351
``
-
4352
4380
`if (Py_SIZE(a) == 0) {
`
4353
4381
`return PyLong_FromLong(0);
`
4354
4382
` }
`
4355
4383
``
4356
``
`-
/* wordshift, remshift = divmod(shiftby, PyLong_SHIFT) */
`
4357
``
`-
wordshift = shiftby / PyLong_SHIFT;
`
4358
``
`-
remshift = shiftby - wordshift * PyLong_SHIFT;
`
4359
``
-
``
4384
`+
if (divmod_shift(b, &wordshift, &remshift) < 0)
`
``
4385
`+
return NULL;
`
4360
4386
`oldsize = Py_ABS(Py_SIZE(a));
`
4361
4387
`newsize = oldsize + wordshift;
`
4362
4388
`if (remshift)
`