Issue #15989: Fix several occurrences of integer overflow
when result of PyInt_AsLong() or PyLong_AsLong() narrowed
to int without checks.

This is a backport of changesets 13e2e44db99d and 525407d89277.
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index ece2370..76cdf74 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -2659,10 +2659,10 @@
     PyObject *meth;
 
     if (PyInt_Check(o)) {
-        fd = PyInt_AsLong(o);
+        fd = _PyInt_AsInt(o);
     }
     else if (PyLong_Check(o)) {
-        fd = PyLong_AsLong(o);
+        fd = _PyLong_AsInt(o);
     }
     else if ((meth = PyObject_GetAttrString(o, "fileno")) != NULL)
     {
@@ -2672,11 +2672,11 @@
             return -1;
 
         if (PyInt_Check(fno)) {
-            fd = PyInt_AsLong(fno);
+            fd = _PyInt_AsInt(fno);
             Py_DECREF(fno);
         }
         else if (PyLong_Check(fno)) {
-            fd = PyLong_AsLong(fno);
+            fd = _PyLong_AsInt(fno);
             Py_DECREF(fno);
         }
         else {
diff --git a/Objects/intobject.c b/Objects/intobject.c
index 1ae8006..28182f9 100644
--- a/Objects/intobject.c
+++ b/Objects/intobject.c
@@ -189,6 +189,20 @@
     return val;
 }
 
+int
+_PyInt_AsInt(PyObject *obj)
+{
+    long result = PyInt_AsLong(obj);
+    if (result == -1 && PyErr_Occurred())
+        return -1;
+    if (result > INT_MAX || result < INT_MIN) {
+        PyErr_SetString(PyExc_OverflowError,
+                        "Python int too large to convert to C int");
+        return -1;
+    }
+    return (int)result;
+}
+
 Py_ssize_t
 PyInt_AsSsize_t(register PyObject *op)
 {
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 5a6338f..fb740dc 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -339,6 +339,24 @@
     return result;
 }
 
+/* Get a C int from a long int object or any object that has an __int__
+   method.  Return -1 and set an error if overflow occurs. */
+
+int
+_PyLong_AsInt(PyObject *obj)
+{
+    int overflow;
+    long result = PyLong_AsLongAndOverflow(obj, &overflow);
+    if (overflow || result > INT_MAX || result < INT_MIN) {
+        /* XXX: could be cute and give a different
+           message for overflow == -1 */
+        PyErr_SetString(PyExc_OverflowError,
+                        "Python int too large to convert to C int");
+        return -1;
+    }
+    return (int)result;
+}
+
 /* Get a Py_ssize_t from a long int object.
    Returns -1 and sets an error condition if overflow occurs. */
 
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 79e1b60..46bfe2b 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -8411,7 +8411,9 @@
                                     "* wants int");
                     goto onError;
                 }
-                width = PyInt_AsLong(v);
+                width = PyInt_AsSsize_t(v);
+                if (width == -1 && PyErr_Occurred())
+                    goto onError;
                 if (width < 0) {
                     flags |= F_LJUST;
                     width = -width;
@@ -8446,7 +8448,9 @@
                                         "* wants int");
                         goto onError;
                     }
-                    prec = PyInt_AsLong(v);
+                    prec = _PyInt_AsInt(v);
+                    if (prec == -1 && PyErr_Occurred())
+                        goto onError;
                     if (prec < 0)
                         prec = 0;
                     if (--fmtcnt >= 0)