]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Revert "gh-143050: Remove redundant decref in _PyLong_Negate (gh-143051)" (#145891)
authorStan Ulbrych <89152624+StanFromIreland@users.noreply.github.com>
Fri, 13 Mar 2026 01:53:29 +0000 (01:53 +0000)
committerGitHub <noreply@github.com>
Fri, 13 Mar 2026 01:53:29 +0000 (21:53 -0400)
OSS Fuzzer caught an assertion failure.

This reverts commit 5197ecb5e4df30ba0f6792d8bc0e36846154f58a.

Objects/longobject.c

index 185226db43a92a2ceaaf217156a7e5de885e4f24..7ce5d0535b884ea639784d8547555bee2e3a5a52 100644 (file)
@@ -48,17 +48,6 @@ _Py_DECREF_INT(PyLongObject *op)
     _Py_DECREF_SPECIALIZED((PyObject *)op, _PyLong_ExactDealloc);
 }
 
-static inline int
-/// Return 1 if the object is one of the immortal small ints
-_long_is_small_int(PyObject *op)
-{
-    assert(PyLong_Check(op));
-    PyLongObject *long_object = (PyLongObject *)op;
-    int is_small_int = (long_object->long_value.lv_tag & IMMORTALITY_BIT_MASK) != 0;
-    assert((!is_small_int) || PyLong_CheckExact(op));
-    return is_small_int;
-}
-
 static inline int
 is_medium_int(stwodigits x)
 {
@@ -355,6 +344,8 @@ medium_from_stwodigits(stwodigits x)
 }
 
 
+/* If a freshly-allocated int is already shared, it must
+   be a small integer, so negating it must go to PyLong_FromLong */
 Py_LOCAL_INLINE(void)
 _PyLong_Negate(PyLongObject **x_p)
 {
@@ -366,10 +357,8 @@ _PyLong_Negate(PyLongObject **x_p)
         return;
     }
 
-    /* If a freshly-allocated int is already shared, it must
-    be a small integer, so negating it will fit a single digit */
-    assert(_long_is_small_int((PyObject *)x));
-    *x_p = (PyLongObject *)_PyLong_FromSTwoDigits(-medium_value(x));
+    *x_p = _PyLong_FromSTwoDigits(-medium_value(x));
+    Py_DECREF(x);
 }
 
 #define PYLONG_FROM_INT(UINT_TYPE, INT_TYPE, ival)                                  \
@@ -3633,6 +3622,16 @@ long_richcompare(PyObject *self, PyObject *other, int op)
     Py_RETURN_RICHCOMPARE(result, 0, op);
 }
 
+static inline int
+/// Return 1 if the object is one of the immortal small ints
+_long_is_small_int(PyObject *op)
+{
+    PyLongObject *long_object = (PyLongObject *)op;
+    int is_small_int = (long_object->long_value.lv_tag & IMMORTALITY_BIT_MASK) != 0;
+    assert((!is_small_int) || PyLong_CheckExact(op));
+    return is_small_int;
+}
+
 void
 _PyLong_ExactDealloc(PyObject *self)
 {