https://github.com/python/cpython/commit/ba91215ca677246e8344ccfc69a6c6698c8ac7cc
commit: ba91215ca677246e8344ccfc69a6c6698c8ac7cc
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-09-16T18:44:55+02:00
summary:

gh-157495: Avoid Py_MIN()/Py_MAX() side effects (#157591)

Avoid calling Py_MIN() or Py_MAX() with non-trivial
functions/expressions since these macros evaluate their arguments
twice.

files:
M Modules/_posixsubprocess.c
M Modules/_threadmodule.c
M Objects/dictobject.c
M Objects/longobject.c
M Objects/unicode_formatter.c

diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
index 07cfba8c8be74b..2291280ec117f2 100644
--- a/Modules/_posixsubprocess.c
+++ b/Modules/_posixsubprocess.c
@@ -352,7 +352,8 @@ _close_range_except(int start_fd,
                     int (*closer)(int, int))
 {
     if (end_fd == -1) {
-        end_fd = Py_MIN(safe_get_max_fd(), INT_MAX);
+        end_fd = safe_get_max_fd();
+        end_fd = Py_MIN(end_fd, INT_MAX);
     }
     Py_ssize_t keep_seq_idx;
     /* As fds_to_keep is sorted we can loop through the list closing
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index 199e4ac3db723b..a79ea5728e72d6 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -571,7 +571,8 @@ ThreadHandle_join(ThreadHandle *self, PyTime_t timeout_ns)
         if (deadline) {
             // _PyDeadline_Get will return a negative value if the deadline has
             // been exceeded.
-            timeout_ns = Py_MAX(_PyDeadline_Get(deadline), 0);
+            timeout_ns = _PyDeadline_Get(deadline);
+            timeout_ns = Py_MAX(timeout_ns, 0);
         }
 
         if (timeout_ns) {
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index f0feea4b717ec9..9a469f88230f8b 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -3412,9 +3412,8 @@ dict_dict_fromkeys(PyDictObject *mp, PyObject *iterable, 
PyObject *value)
     PyObject *key;
     Py_hash_t hash;
     int unicode = DK_IS_UNICODE(((PyDictObject*)iterable)->ma_keys);
-    uint8_t new_size = Py_MAX(
-        estimate_log2_keysize(PyDict_GET_SIZE(iterable)),
-        DK_LOG_SIZE(mp->ma_keys));
+    uint8_t log2_keysize = estimate_log2_keysize(PyDict_GET_SIZE(iterable));
+    uint8_t new_size = Py_MAX(log2_keysize, DK_LOG_SIZE(mp->ma_keys));
     if (dictresize(mp, new_size, unicode)) {
         Py_DECREF(mp);
         return NULL;
@@ -3437,9 +3436,8 @@ dict_set_fromkeys(PyDictObject *mp, PyObject *iterable, 
PyObject *value)
     Py_ssize_t pos = 0;
     PyObject *key;
     Py_hash_t hash;
-    uint8_t new_size = Py_MAX(
-        estimate_log2_keysize(PySet_GET_SIZE(iterable)),
-        DK_LOG_SIZE(mp->ma_keys));
+    uint8_t log2_keysize = estimate_log2_keysize(PySet_GET_SIZE(iterable));
+    uint8_t new_size = Py_MAX(log2_keysize, DK_LOG_SIZE(mp->ma_keys));
     if (dictresize(mp, new_size, 0)) {
         Py_DECREF(mp);
         return NULL;
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 6454565aebf6a1..e35f938629326a 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -6269,9 +6269,10 @@ static Py_ssize_t
 int___sizeof___impl(PyObject *self)
 /*[clinic end generated code: output=3303f008eaa6a0a5 input=9b51620c76fc4507]*/
 {
+    Py_ssize_t ndigits = _PyLong_DigitCount((PyLongObject *)self);
     /* using Py_MAX(..., 1) because we always allocate space for at least
        one digit, even though the integer zero has a digit count of 0 */
-    Py_ssize_t ndigits = Py_MAX(_PyLong_DigitCount((PyLongObject *)self), 1);
+    ndigits = Py_MAX(ndigits, 1);
     return Py_TYPE(self)->tp_basicsize + Py_TYPE(self)->tp_itemsize * ndigits;
 }
 
diff --git a/Objects/unicode_formatter.c b/Objects/unicode_formatter.c
index b8604d1355940a..2b7681f7ff3ce9 100644
--- a/Objects/unicode_formatter.c
+++ b/Objects/unicode_formatter.c
@@ -892,8 +892,10 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t 
n_prefix,
     if (spec->n_lpadding || spec->n_spadding || spec->n_rpadding)
         *maxchar = Py_MAX(*maxchar, format->fill_char);
 
-    if (spec->n_decimal)
-        *maxchar = Py_MAX(*maxchar, 
PyUnicode_MAX_CHAR_VALUE(locale->decimal_point));
+    if (spec->n_decimal) {
+        Py_UCS4 point_maxchar = 
PyUnicode_MAX_CHAR_VALUE(locale->decimal_point);
+        *maxchar = Py_MAX(*maxchar, point_maxchar);
+    }
 
     return spec->n_lpadding + spec->n_sign + spec->n_prefix +
         spec->n_spadding + spec->n_grouped_digits + spec->n_decimal +

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to