From 46d379207dd2132f00f89f689284e6e18592bd33 Mon Sep 17 00:00:00 2001 From: Bernd Kuhls Date: Sat, 5 Sep 2026 14:20:35 +0200 Subject: [PATCH] package/libcec: fix build with swig >= 4.5.0 Patch 0002 fixes the build with swig >= 4.5.0. Patch 0001 is needed to cleanly apply patch 0002. Signed-off-by: Bernd Kuhls Signed-off-by: Thomas Petazzoni --- ...DeviceLanguage-accepts-3-char-ISO-co.patch | 66 ++++++++++++++++ ...Python-wrapper-against-SWIG-4.5-whic.patch | 78 +++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 package/libcec/0001-fixed-Python-strDeviceLanguage-accepts-3-char-ISO-co.patch create mode 100644 package/libcec/0002-fixed-build-the-Python-wrapper-against-SWIG-4.5-whic.patch diff --git a/package/libcec/0001-fixed-Python-strDeviceLanguage-accepts-3-char-ISO-co.patch b/package/libcec/0001-fixed-Python-strDeviceLanguage-accepts-3-char-ISO-co.patch new file mode 100644 index 0000000000..e2a86e1f7e --- /dev/null +++ b/package/libcec/0001-fixed-Python-strDeviceLanguage-accepts-3-char-ISO-co.patch @@ -0,0 +1,66 @@ +From f53490e23037f17b68043f5e1ff2f4378d227d56 Mon Sep 17 00:00:00 2001 +From: Lars Op den Kamp +Date: Mon, 13 Jul 2026 15:24:27 +0200 +Subject: [PATCH] fixed: Python strDeviceLanguage accepts 3-char ISO codes + (SWIG char[3] typemap) + +The SWIG default char[ANY] setter uses SWIG_AsCharArray, which reserves a +byte for a NUL terminator. strDeviceLanguage is a raw, non-terminated +char[3] holding a 3-character ISO 639-2 code, so a valid 3-char value needs +4 bytes and overflowed the buffer, raising a TypeError; only 2-char codes +fit. Add member-name-scoped in/memberin typemaps that copy the raw bytes +(str or bytes) so 3-char codes assign correctly. Scoped by name so the +NUL-terminated strDeviceName keeps the default behaviour. + +Upstream: https://github.com/Pulse-Eight/libcec/commit/f53490e23037f17b68043f5e1ff2f4378d227d56 + +Signed-off-by: Bernd Kuhls +--- + src/libcec/libcec.i | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/src/libcec/libcec.i b/src/libcec/libcec.i +index a01f9afc..520ff7af 100644 +--- a/src/libcec/libcec.i ++++ b/src/libcec/libcec.i +@@ -15,6 +15,37 @@ + $result = PyString_FromString($1.name); + } + ++/////// libcec_configuration::strDeviceLanguage /////// ++// strDeviceLanguage is a raw, fixed-size char[3] that is NOT NUL-terminated (a ++// 3-character ISO 639-2 code). SWIG's default char[ANY] setter reserves a byte ++// for a terminator, so a valid 3-char code needs 4 bytes and overflows the ++// buffer, raising a TypeError; only 2-char codes fit. Copy the raw bytes ++// instead (accepting str or bytes), scoped to this member by name so the ++// NUL-terminated strDeviceName keeps the default behaviour. ++%typemap(in) char strDeviceLanguage[ANY] (char temp[$1_dim0]) { ++ char *cptr = 0; size_t csize = 0; int alloc = SWIG_OLDOBJ; ++ int res = SWIG_AsCharPtrAndSize($input, &cptr, &csize, &alloc); ++ if (!SWIG_IsOK(res)) { ++ %argument_fail(res, "char [$1_dim0]", $symname, $argnum); ++ } ++ { ++ /* csize counts the trailing NUL; strDeviceLanguage stores no terminator */ ++ size_t slen = (csize > 0) ? csize - 1 : 0; ++ if (slen > (size_t)($1_dim0)) { ++ if (alloc == SWIG_NEWOBJ) %delete_array(cptr); ++ %argument_fail(SWIG_ValueError, "char [$1_dim0]", $symname, $argnum); ++ } ++ memset(temp, 0, $1_dim0); ++ if (slen) memcpy(temp, cptr, slen); ++ } ++ $1 = temp; ++ if (alloc == SWIG_NEWOBJ) %delete_array(cptr); ++} ++ ++%typemap(memberin) char strDeviceLanguage[ANY] { ++ memcpy($1, $input, $1_dim0 * sizeof(char)); ++} ++ + /////// replace operator[]() /////// + + // CEC::cec_datapacket::operator[]() +-- +2.47.3 + diff --git a/package/libcec/0002-fixed-build-the-Python-wrapper-against-SWIG-4.5-whic.patch b/package/libcec/0002-fixed-build-the-Python-wrapper-against-SWIG-4.5-whic.patch new file mode 100644 index 0000000000..351091e17d --- /dev/null +++ b/package/libcec/0002-fixed-build-the-Python-wrapper-against-SWIG-4.5-whic.patch @@ -0,0 +1,78 @@ +From 55f3443559b0b32a1d7194e424727575faf6f7d4 Mon Sep 17 00:00:00 2001 +From: Lars Op den Kamp +Date: Fri, 31 Jul 2026 14:46:27 +0200 +Subject: [PATCH] fixed: build the Python wrapper against SWIG 4.5, which + removed the Python 2 compatibility macros + +SWIG 4.5 dropped the PyInt_*/PyString_* macros that pyhead.swg used to define +for user typemaps. Two places here relied on them. + +The callback return handling keeps a PY_MAJOR_VERSION guard rather than moving +to the Python 3 API outright, because the x86 Windows build still targets +Python 2 for the EventGhost plugin. A Python 2 int is a PyIntObject, not a +PyLongObject, so an unguarded PyLong_Check would compile there and then +silently read every commandHandler and menuStateChanged return value as 0 - the +one thing those callbacks exist to report. SWIG never reads SwigHelper.h, so +the C preprocessor makes the choice and the file is SWIG-version independent. + +The cec_osd_name out-typemap is deleted rather than fixed, because it is dead: +GetDeviceOSDName returns std::string, and cec_osd_name only survives as an out +parameter in the C API, which is not wrapped. It could not have compiled if it +ever did fire - cec_osd_name is a typedef for char[14], so the $1.name it +dereferences has no member to name. Removing it leaves the generated wrapper +byte-for-byte identical. + +Verified by preprocessing SwigHelper.h against both Python 3.10 and Python 2.7: +Python 3 resolves to PyObject_CallObject/PyLong_AsLong with no removed macro +surviving anywhere, Python 2 to PyEval_CallObject/PyInt_AsLong. + +closes #726 + +Upstream: https://github.com/Pulse-Eight/libcec/commit/55f3443559b0b32a1d7194e424727575faf6f7d4 + +Signed-off-by: Bernd Kuhls +--- + src/libcec/SwigHelper.h | 9 +++++++++ + src/libcec/libcec.i | 4 ---- + 2 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/src/libcec/SwigHelper.h b/src/libcec/SwigHelper.h +index 3c40fc87..0752acb2 100644 +--- a/src/libcec/SwigHelper.h ++++ b/src/libcec/SwigHelper.h +@@ -137,8 +137,17 @@ namespace CEC + Py_DECREF(arglist); + if (!!result) + { ++ /** SWIG 4.5 removed the PyInt_* compatibility macros it used to define ++ for Python 3, so call the version-appropriate API directly. Note that ++ a Python 2 int is a PyIntObject, not a PyLongObject, so PyLong_Check ++ would silently reject it there. */ ++ #if (PY_MAJOR_VERSION < 3) + if (PyInt_Check(result)) + retval = (int)PyInt_AsLong(result); ++ #else // (PY_MAJOR_VERSION >= 3) ++ if (PyLong_Check(result)) ++ retval = (int)PyLong_AsLong(result); ++ #endif + Py_XDECREF(result); + } + } +diff --git a/src/libcec/libcec.i b/src/libcec/libcec.i +index 520ff7af..0d757aa1 100644 +--- a/src/libcec/libcec.i ++++ b/src/libcec/libcec.i +@@ -11,10 +11,6 @@ + + %ignore *::operator=; + +-%typemap(out) CEC::cec_osd_name { +- $result = PyString_FromString($1.name); +-} +- + /////// libcec_configuration::strDeviceLanguage /////// + // strDeviceLanguage is a raw, fixed-size char[3] that is NOT NUL-terminated (a + // 3-character ISO 639-2 code). SWIG's default char[ANY] setter reserves a byte +-- +2.47.3 +