@@ -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 )
0 commit comments