Issue #25678: Copy buffer objects to null-terminated strings.

Avoid buffer overreads when int(), long(), float(), and compile()
are passed buffer objects.  Similar code is removed from the
complex() constructor, where it was not reachable.

Patch backported from issue #24802 by Eryk Sun.
diff --git a/Objects/abstract.c b/Objects/abstract.c
index ad7889e..3a50b73 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1666,8 +1666,17 @@
                                  PyUnicode_GET_SIZE(o),
                                  10);
 #endif
-    if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
-        return int_from_string((char*)buffer, buffer_len);
+    if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len)) {
+        PyObject *result, *str;
+
+        /* Copy to NUL-terminated buffer. */
+        str = PyString_FromStringAndSize((const char *)buffer, buffer_len);
+        if (str == NULL)
+            return NULL;
+        result = int_from_string(PyString_AS_STRING(str), buffer_len);
+        Py_DECREF(str);
+        return result;
+    }
 
     return type_error("int() argument must be a string or a "
                       "number, not '%.200s'", o);
@@ -1765,9 +1774,17 @@
                                   PyUnicode_GET_SIZE(o),
                                   10);
 #endif
-    if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
-        return long_from_string(buffer, buffer_len);
+    if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len)) {
+        PyObject *result, *str;
 
+        /* Copy to NUL-terminated buffer. */
+        str = PyString_FromStringAndSize((const char *)buffer, buffer_len);
+        if (str == NULL)
+            return NULL;
+        result = long_from_string(PyString_AS_STRING(str), buffer_len);
+        Py_DECREF(str);
+        return result;
+    }
     return type_error("long() argument must be a string or a "
                       "number, not '%.200s'", o);
 }
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index 2659a23..9e97d1b 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -1000,7 +1000,7 @@
         len = strlen(s);
     }
 #endif
-    else if (PyObject_AsCharBuffer(v, &s, &len)) {
+    else {
         PyErr_SetString(PyExc_TypeError,
                         "complex() arg is not a string");
         return NULL;
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 0ce7f6c..1143fab 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -180,6 +180,7 @@
     char *s_buffer = NULL;
 #endif
     Py_ssize_t len;
+    PyObject *str = NULL;
     PyObject *result = NULL;
 
     if (pend)
@@ -202,7 +203,14 @@
         len = strlen(s);
     }
 #endif
-    else if (PyObject_AsCharBuffer(v, &s, &len)) {
+    else if (!PyObject_AsCharBuffer(v, &s, &len)) {
+        /* Copy to NUL-terminated buffer. */
+        str = PyString_FromStringAndSize(s, len);
+        if (str == NULL)
+            return NULL;
+        s = PyString_AS_STRING(str);
+    }
+    else {
         PyErr_SetString(PyExc_TypeError,
             "float() argument must be a string or a number");
         return NULL;
@@ -233,6 +241,7 @@
     if (s_buffer)
         PyMem_FREE(s_buffer);
 #endif
+    Py_XDECREF(str);
     return result;
 }