diff --git a/Objects/longobject.c b/Objects/longobject.c
index 95661a4022..001c5c5ffe 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -4289,11 +4289,19 @@ static PyObject *
long_rshift(PyLongObject *a, PyLongObject *b)
{
PyLongObject *z = NULL;
+ digit loshift_d;
+ PyLongObject *wordshift_obj;
Py_ssize_t shiftby, newsize, wordshift, loshift, hishift, i, j;
digit lomask, himask;
CHECK_BINOP(a, b);
+ if (Py_SIZE(b) < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "negative shift count");
+ return NULL;
+ }
+
if (Py_SIZE(a) < 0) {
/* Right shifting negative numbers is harder */
PyLongObject *a1, *a2;
@@ -4309,18 +4317,44 @@ long_rshift(PyLongObject *a, PyLongObject *b)
}
else {
shiftby = PyLong_AsSsize_t((PyObject *)b);
- if (shiftby == -1L && PyErr_Occurred())
- return NULL;
- if (shiftby < 0) {
- PyErr_SetString(PyExc_ValueError,
- "negative shift count");
- return NULL;
+ if (shiftby == -1L) {
+ /* PyLong_Check(b) and Py_SIZE(b) >= 0, so it must be that
+ PyLong_AsSsize_t raised an OverflowError because b is too large
+ to convert to C Py_ssize_t. */
+ assert(PyErr_Occurred());
+ PyErr_Clear();
+
+ wordshift_obj = divrem1(b, PyLong_SHIFT, &loshift_d);
+ if (wordshift_obj == NULL) {
+ return NULL;
+ }
+ wordshift = PyLong_AsSsize_t((PyObject *)wordshift_obj);
+ if (wordshift == -1L) {
+ /* PyLong_Check(wordshift_obj) and Py_SIZE(wordshift_obj) > 0,
+ so it must be that PyLong_AsSsize_t raised an OverflowError
+ because wordshift_obj is too large to convert to C
+ Py_ssize_t. Thus, wordshift must be bigger than
+ Py_SIZE(a). */
+ assert(PyErr_Occurred());
+ PyErr_Clear();
+ Py_DECREF(wordshift_obj);
+ return PyLong_FromLong(0);
+ }
+ Py_DECREF(wordshift_obj);
+
+ newsize = Py_ABS(Py_SIZE(a)) - wordshift;
+ if (newsize <= 0)
+ return PyLong_FromLong(0);
+ /* The cast is safe because 0 <= loshift_d < PyLong_SHIFT */
+ loshift = (Py_ssize_t)loshift_d;
+ }
+ else {
+ wordshift = shiftby / PyLong_SHIFT;
+ newsize = Py_ABS(Py_SIZE(a)) - wordshift;
+ if (newsize <= 0)
+ return PyLong_FromLong(0);
+ loshift = shiftby % PyLong_SHIFT;
}
- wordshift = shiftby / PyLong_SHIFT;
- newsize = Py_ABS(Py_SIZE(a)) - wordshift;
- if (newsize <= 0)
- return PyLong_FromLong(0);
- loshift = shiftby % PyLong_SHIFT;
hishift = PyLong_SHIFT - loshift;
lomask = ((digit)1 << hishift) - 1;
himask = PyLong_MASK ^ lomask;