bpo-40792: Make the result of PyNumber_Index() always having exact type int. (GH-20443)

Previously, the result could have been an instance of a subclass of int.

Also revert bpo-26202 and make attributes start, stop and step of the range
object having exact type int.

Add private function _PyNumber_Index() which preserves the old behavior
of PyNumber_Index() for performance to use it in the conversion functions
like PyLong_AsLong().
diff --git a/Objects/abstract.c b/Objects/abstract.c
index e819849..973c43f 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1317,11 +1317,12 @@
 
 
 /* Return a Python int from the object item.
+   Can return an instance of int subclass.
    Raise TypeError if the result is not an int
    or if the object cannot be interpreted as an index.
 */
 PyObject *
-PyNumber_Index(PyObject *item)
+_PyNumber_Index(PyObject *item)
 {
     PyObject *result = NULL;
     if (item == NULL) {
@@ -1360,6 +1361,20 @@
     return result;
 }
 
+/* Return an exact Python int from the object item.
+   Raise TypeError if the result is not an int
+   or if the object cannot be interpreted as an index.
+*/
+PyObject *
+PyNumber_Index(PyObject *item)
+{
+    PyObject *result = _PyNumber_Index(item);
+    if (result != NULL && !PyLong_CheckExact(result)) {
+        Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
+    }
+    return result;
+}
+
 /* Return an error on Overflow only if err is not NULL*/
 
 Py_ssize_t
@@ -1367,7 +1382,7 @@
 {
     Py_ssize_t result;
     PyObject *runerr;
-    PyObject *value = PyNumber_Index(item);
+    PyObject *value = _PyNumber_Index(item);
     if (value == NULL)
         return -1;
 
@@ -1451,11 +1466,7 @@
         return result;
     }
     if (m && m->nb_index) {
-        result = PyNumber_Index(o);
-        if (result != NULL && !PyLong_CheckExact(result)) {
-            Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
-        }
-        return result;
+        return PyNumber_Index(o);
     }
     trunc_func = _PyObject_LookupSpecial(o, &PyId___trunc__);
     if (trunc_func) {
@@ -1479,9 +1490,6 @@
             return NULL;
         }
         Py_SETREF(result, PyNumber_Index(result));
-        if (result != NULL && !PyLong_CheckExact(result)) {
-            Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
-        }
         return result;
     }
     if (PyErr_Occurred())
@@ -1564,7 +1572,7 @@
         return PyFloat_FromDouble(val);
     }
     if (m && m->nb_index) {
-        PyObject *res = PyNumber_Index(o);
+        PyObject *res = _PyNumber_Index(o);
         if (!res) {
             return NULL;
         }
@@ -1590,7 +1598,7 @@
                         "PyNumber_ToBase: base must be 2, 8, 10 or 16");
         return NULL;
     }
-    PyObject *index = PyNumber_Index(n);
+    PyObject *index = _PyNumber_Index(n);
     if (!index)
         return NULL;
     PyObject *res = _PyLong_Format(index, base);
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 25d9814..8d64540 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -455,7 +455,7 @@
     if (PyNumber_Check(v)) {
         /* make sure number is a type of integer for o, x, and X */
         if (type == 'o' || type == 'x' || type == 'X')
-            iobj = PyNumber_Index(v);
+            iobj = _PyNumber_Index(v);
         else
             iobj = PyNumber_Long(v);
         if (iobj == NULL) {
diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h
index 83b0d03..cbe6f20 100644
--- a/Objects/clinic/bytearrayobject.c.h
+++ b/Objects/clinic/bytearrayobject.c.h
@@ -270,7 +270,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[2]);
+        PyObject *iobj = _PyNumber_Index(args[2]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -343,7 +343,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[1]);
+        PyObject *iobj = _PyNumber_Index(args[1]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -442,7 +442,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[1]);
+        PyObject *iobj = _PyNumber_Index(args[1]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -506,7 +506,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[0]);
+        PyObject *iobj = _PyNumber_Index(args[0]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -599,7 +599,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[0]);
+        PyObject *iobj = _PyNumber_Index(args[0]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -1051,4 +1051,4 @@
 {
     return bytearray_sizeof_impl(self);
 }
-/*[clinic end generated code: output=920748990279fb9d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=0cd59180c7d5dce5 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h
index c4a2d0c..201627e 100644
--- a/Objects/clinic/bytesobject.c.h
+++ b/Objects/clinic/bytesobject.c.h
@@ -48,7 +48,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[1]);
+        PyObject *iobj = _PyNumber_Index(args[1]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -199,7 +199,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[1]);
+        PyObject *iobj = _PyNumber_Index(args[1]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -485,7 +485,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[2]);
+        PyObject *iobj = _PyNumber_Index(args[2]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -809,4 +809,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=a0c31faea2671a8c input=a9049054013a1b77]*/
+/*[clinic end generated code: output=dc1bc13e6990e452 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/listobject.c.h b/Objects/clinic/listobject.c.h
index 82884a4..01e31d7 100644
--- a/Objects/clinic/listobject.c.h
+++ b/Objects/clinic/listobject.c.h
@@ -26,7 +26,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[0]);
+        PyObject *iobj = _PyNumber_Index(args[0]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -125,7 +125,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[0]);
+        PyObject *iobj = _PyNumber_Index(args[0]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -352,4 +352,4 @@
 {
     return list___reversed___impl(self);
 }
-/*[clinic end generated code: output=137db7b11196b581 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=0063aad535edf62d input=a9049054013a1b77]*/
diff --git a/Objects/clinic/longobject.c.h b/Objects/clinic/longobject.c.h
index d3d5c19..7db8965 100644
--- a/Objects/clinic/longobject.c.h
+++ b/Objects/clinic/longobject.c.h
@@ -211,7 +211,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[0]);
+        PyObject *iobj = _PyNumber_Index(args[0]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -308,4 +308,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=46d40c8aa6d420b7 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=63b8274fc784d617 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/unicodeobject.c.h b/Objects/clinic/unicodeobject.c.h
index 2d81730..ecd409e 100644
--- a/Objects/clinic/unicodeobject.c.h
+++ b/Objects/clinic/unicodeobject.c.h
@@ -88,7 +88,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[0]);
+        PyObject *iobj = _PyNumber_Index(args[0]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -522,7 +522,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[0]);
+        PyObject *iobj = _PyNumber_Index(args[0]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -717,7 +717,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[2]);
+        PyObject *iobj = _PyNumber_Index(args[2]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -831,7 +831,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[0]);
+        PyObject *iobj = _PyNumber_Index(args[0]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -900,7 +900,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[1]);
+        PyObject *iobj = _PyNumber_Index(args[1]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -997,7 +997,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[1]);
+        PyObject *iobj = _PyNumber_Index(args[1]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -1193,7 +1193,7 @@
 
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(arg);
+        PyObject *iobj = _PyNumber_Index(arg);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -1258,4 +1258,4 @@
 {
     return unicode_sizeof_impl(self);
 }
-/*[clinic end generated code: output=ea1aff10c743be14 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=c5eb21e314da78b8 input=a9049054013a1b77]*/
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index cc0ae8c..868b729 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -250,7 +250,7 @@
     nb = Py_TYPE(op)->tp_as_number;
     if (nb == NULL || nb->nb_float == NULL) {
         if (nb && nb->nb_index) {
-            PyObject *res = PyNumber_Index(op);
+            PyObject *res = _PyNumber_Index(op);
             if (!res) {
                 return -1;
             }
diff --git a/Objects/longobject.c b/Objects/longobject.c
index e040d6c..4ae17c9 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -394,7 +394,7 @@
         v = (PyLongObject *)vv;
     }
     else {
-        v = (PyLongObject *)PyNumber_Index(vv);
+        v = (PyLongObject *)_PyNumber_Index(vv);
         if (v == NULL)
             return -1;
         do_decref = 1;
@@ -674,7 +674,7 @@
         return _PyLong_AsUnsignedLongMask(op);
     }
 
-    lo = (PyLongObject *)PyNumber_Index(op);
+    lo = (PyLongObject *)_PyNumber_Index(op);
     if (lo == NULL)
         return (unsigned long)-1;
 
@@ -1132,7 +1132,7 @@
         v = (PyLongObject *)vv;
     }
     else {
-        v = (PyLongObject *)PyNumber_Index(vv);
+        v = (PyLongObject *)_PyNumber_Index(vv);
         if (v == NULL)
             return -1;
         do_decref = 1;
@@ -1247,7 +1247,7 @@
         return _PyLong_AsUnsignedLongLongMask(op);
     }
 
-    lo = (PyLongObject *)PyNumber_Index(op);
+    lo = (PyLongObject *)_PyNumber_Index(op);
     if (lo == NULL)
         return (unsigned long long)-1;
 
@@ -1287,7 +1287,7 @@
         v = (PyLongObject *)vv;
     }
     else {
-        v = (PyLongObject *)PyNumber_Index(vv);
+        v = (PyLongObject *)_PyNumber_Index(vv);
         if (v == NULL)
             return -1;
         do_decref = 1;
@@ -5180,7 +5180,7 @@
     if (o_ndigits == NULL)
         return long_long(self);
 
-    ndigits = PyNumber_Index(o_ndigits);
+    ndigits = _PyNumber_Index(o_ndigits);
     if (ndigits == NULL)
         return NULL;
 
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
index 682bbe8..e3d3bd6a 100644
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -1578,7 +1578,7 @@
     PyObject *tmp;
     long ld;
 
-    tmp = PyNumber_Index(item);
+    tmp = _PyNumber_Index(item);
     if (tmp == NULL)
         return -1;
 
@@ -1593,7 +1593,7 @@
     PyObject *tmp;
     unsigned long lu;
 
-    tmp = PyNumber_Index(item);
+    tmp = _PyNumber_Index(item);
     if (tmp == NULL)
         return (unsigned long)-1;
 
@@ -1608,7 +1608,7 @@
     PyObject *tmp;
     long long lld;
 
-    tmp = PyNumber_Index(item);
+    tmp = _PyNumber_Index(item);
     if (tmp == NULL)
         return -1;
 
@@ -1623,7 +1623,7 @@
     PyObject *tmp;
     unsigned long long llu;
 
-    tmp = PyNumber_Index(item);
+    tmp = _PyNumber_Index(item);
     if (tmp == NULL)
         return (unsigned long long)-1;
 
@@ -1638,7 +1638,7 @@
     PyObject *tmp;
     Py_ssize_t zd;
 
-    tmp = PyNumber_Index(item);
+    tmp = _PyNumber_Index(item);
     if (tmp == NULL)
         return -1;
 
@@ -1653,7 +1653,7 @@
     PyObject *tmp;
     size_t zu;
 
-    tmp = PyNumber_Index(item);
+    tmp = _PyNumber_Index(item);
     if (tmp == NULL)
         return (size_t)-1;
 
diff --git a/Objects/stringlib/clinic/transmogrify.h.h b/Objects/stringlib/clinic/transmogrify.h.h
index 8dd7e6b..a5135a0 100644
--- a/Objects/stringlib/clinic/transmogrify.h.h
+++ b/Objects/stringlib/clinic/transmogrify.h.h
@@ -70,7 +70,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[0]);
+        PyObject *iobj = _PyNumber_Index(args[0]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -126,7 +126,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[0]);
+        PyObject *iobj = _PyNumber_Index(args[0]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -182,7 +182,7 @@
     }
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(args[0]);
+        PyObject *iobj = _PyNumber_Index(args[0]);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -234,7 +234,7 @@
 
     {
         Py_ssize_t ival = -1;
-        PyObject *iobj = PyNumber_Index(arg);
+        PyObject *iobj = _PyNumber_Index(arg);
         if (iobj != NULL) {
             ival = PyLong_AsSsize_t(iobj);
             Py_DECREF(iobj);
@@ -249,4 +249,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=cd5ecdbf1d9e849a input=a9049054013a1b77]*/
+/*[clinic end generated code: output=2d9abc7b1cffeca6 input=a9049054013a1b77]*/
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index ba2a852..1d556e9 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -6334,7 +6334,7 @@
     if (res == NULL)
         return -1;
 
-    Py_SETREF(res, PyNumber_Index(res));
+    Py_SETREF(res, _PyNumber_Index(res));
     if (res == NULL)
         return -1;
 
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index ea46a44..5116404 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -14617,7 +14617,7 @@
     /* make sure number is a type of integer for o, x, and X */
     if (!PyLong_Check(v)) {
         if (type == 'o' || type == 'x' || type == 'X') {
-            iobj = PyNumber_Index(v);
+            iobj = _PyNumber_Index(v);
             if (iobj == NULL) {
                 if (PyErr_ExceptionMatches(PyExc_TypeError))
                     goto wrongtype;