]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-109617: fix ncurses incompatibility on macOS with Xcode 15 (#111258)
authorDavide Rizzo <sorcio@gmail.com>
Sat, 4 May 2024 21:41:47 +0000 (23:41 +0200)
committerGitHub <noreply@github.com>
Sat, 4 May 2024 21:41:47 +0000 (23:41 +0200)
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Co-authored-by: Ɓukasz Langa <lukasz@langa.pl>
Include/py_curses.h
Misc/NEWS.d/next/Library/2023-10-24-12-39-04.gh-issue-109617.YoI8TV.rst [new file with mode: 0644]
Modules/_cursesmodule.c
configure
configure.ac

index e46b08e9cc414e722b2c4da7f83c41237f8dee96..a51d9980eee401bb449d43bbf698c1325b1a7acb 100644 (file)
 # endif
 #endif
 
-#if !defined(HAVE_CURSES_IS_PAD) && defined(WINDOW_HAS_FLAGS)
-/* The following definition is necessary for ncurses 5.7; without it,
-   some of [n]curses.h set NCURSES_OPAQUE to 1, and then Python
-   can't get at the WINDOW flags field. */
+#if defined(WINDOW_HAS_FLAGS) && defined(__APPLE__)
+/* gh-109617, gh-115383: we can rely on the default value for NCURSES_OPAQUE on
+   most platforms, but not on macOS. This is because, starting with Xcode 15,
+   Apple-provided ncurses.h comes from ncurses 6 (which defaults to opaque
+   structs) but can still be linked to older versions of ncurses dynamic
+   libraries which don't provide functions such as is_pad() to deal with opaque
+   structs. Setting NCURSES_OPAQUE to 0 is harmless in all ncurses releases to
+   this date (provided that a thread-safe implementation is not required), but
+   this might change in the future. This fix might become irrelevant once
+   support for macOS 13 or earlier is dropped. */
 #define NCURSES_OPAQUE 0
 #endif
 
 #ifdef HAVE_NCURSES_H
 /* configure was checking <curses.h>, but we will
    use <ncurses.h>, which has some or all these features. */
-#if !defined(WINDOW_HAS_FLAGS) && !(NCURSES_OPAQUE+0)
+#if !defined(WINDOW_HAS_FLAGS) && \
+    (NCURSES_VERSION_PATCH+0 < 20070303 || !(NCURSES_OPAQUE+0))
+/* the WINDOW flags field was always accessible in ncurses prior to 20070303;
+   after that, it depends on the value of NCURSES_OPAQUE. */
 #define WINDOW_HAS_FLAGS 1
 #endif
 #if !defined(HAVE_CURSES_IS_PAD) && NCURSES_VERSION_PATCH+0 >= 20090906
diff --git a/Misc/NEWS.d/next/Library/2023-10-24-12-39-04.gh-issue-109617.YoI8TV.rst b/Misc/NEWS.d/next/Library/2023-10-24-12-39-04.gh-issue-109617.YoI8TV.rst
new file mode 100644 (file)
index 0000000..4fda69d
--- /dev/null
@@ -0,0 +1,2 @@
+:mod:`ncurses`: fixed a crash that could occur on macOS 13 or earlier when
+Python was built with Apple Xcode 15's SDK.
index 8bf6824b6d83ffa8f19a6a580c95845f24e5c604..69b97042b89dc771793bca1e00977b033aab6b21 100644 (file)
@@ -1156,8 +1156,10 @@ int py_mvwdelch(WINDOW *w, int y, int x)
 #endif
 
 #if defined(HAVE_CURSES_IS_PAD)
+// is_pad() is defined, either as a macro or as a function
 #define py_is_pad(win)      is_pad(win)
 #elif defined(WINDOW_HAS_FLAGS)
+// is_pad() is not defined, but we can inspect WINDOW structure members
 #define py_is_pad(win)      ((win) ? ((win)->_flags & _ISPAD) != 0 : FALSE)
 #endif
 
@@ -4586,7 +4588,14 @@ make_ncurses_version(PyTypeObject *type)
     if (ncurses_version == NULL) {
         return NULL;
     }
-
+    const char *str = curses_version();
+    unsigned long major = 0, minor = 0, patch = 0;
+    if (!str || sscanf(str, "%*[^0-9]%lu.%lu.%lu", &major, &minor, &patch) < 3) {
+        // Fallback to header version, which cannot be that wrong
+        major = NCURSES_VERSION_MAJOR;
+        minor = NCURSES_VERSION_MINOR;
+        patch = NCURSES_VERSION_PATCH;
+    }
 #define SetIntItem(flag) \
     PyStructSequence_SET_ITEM(ncurses_version, pos++, PyLong_FromLong(flag)); \
     if (PyErr_Occurred()) { \
@@ -4594,9 +4603,9 @@ make_ncurses_version(PyTypeObject *type)
         return NULL; \
     }
 
-    SetIntItem(NCURSES_VERSION_MAJOR)
-    SetIntItem(NCURSES_VERSION_MINOR)
-    SetIntItem(NCURSES_VERSION_PATCH)
+    SetIntItem(major)
+    SetIntItem(minor)
+    SetIntItem(patch)
 #undef SetIntItem
 
     return ncurses_version;
index cc85aed2aa51c2f4fb89d3dcbaf91313abe4bfc1..0cd137198d0bb71a8abdd78d4b1a3dc65e4ccd83 100755 (executable)
--- a/configure
+++ b/configure
@@ -26781,7 +26781,10 @@ then :
 else $as_nop
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <curses.h>
+
+        #define NCURSES_OPAQUE 0
+        #include <curses.h>
+
 int
 main (void)
 {
@@ -26824,7 +26827,10 @@ then :
 else $as_nop
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <curses.h>
+
+        #define NCURSES_OPAQUE 0
+        #include <curses.h>
+
 int
 main (void)
 {
@@ -26867,7 +26873,10 @@ then :
 else $as_nop
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <curses.h>
+
+        #define NCURSES_OPAQUE 0
+        #include <curses.h>
+
 int
 main (void)
 {
@@ -26910,7 +26919,10 @@ then :
 else $as_nop
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <curses.h>
+
+        #define NCURSES_OPAQUE 0
+        #include <curses.h>
+
 int
 main (void)
 {
@@ -26953,7 +26965,10 @@ then :
 else $as_nop
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <curses.h>
+
+        #define NCURSES_OPAQUE 0
+        #include <curses.h>
+
 int
 main (void)
 {
@@ -26996,7 +27011,10 @@ then :
 else $as_nop
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <curses.h>
+
+        #define NCURSES_OPAQUE 0
+        #include <curses.h>
+
 int
 main (void)
 {
@@ -27039,7 +27057,10 @@ then :
 else $as_nop
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <curses.h>
+
+        #define NCURSES_OPAQUE 0
+        #include <curses.h>
+
 int
 main (void)
 {
@@ -27082,7 +27103,10 @@ then :
 else $as_nop
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <curses.h>
+
+        #define NCURSES_OPAQUE 0
+        #include <curses.h>
+
 int
 main (void)
 {
@@ -27125,7 +27149,10 @@ then :
 else $as_nop
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <curses.h>
+
+        #define NCURSES_OPAQUE 0
+        #include <curses.h>
+
 int
 main (void)
 {
@@ -27168,7 +27195,10 @@ then :
 else $as_nop
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <curses.h>
+
+        #define NCURSES_OPAQUE 0
+        #include <curses.h>
+
 int
 main (void)
 {
@@ -27211,7 +27241,10 @@ then :
 else $as_nop
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <curses.h>
+
+        #define NCURSES_OPAQUE 0
+        #include <curses.h>
+
 int
 main (void)
 {
index c55e33add20fdecef1f85fb905c9a7ff2fcb3746..ae594517df5365bda6ff2bc495a095f106d641e0 100644 (file)
@@ -6713,7 +6713,10 @@ AC_DEFUN([PY_CHECK_CURSES_FUNC],
     [py_var],
     [AC_COMPILE_IFELSE(
       [AC_LANG_PROGRAM(
-        [@%:@include <curses.h>], [
+        [
+        #define NCURSES_OPAQUE 0
+        #include <curses.h>
+        ], [
         #ifndef $1
         void *x=$1
         #endif