diff --git a/swig-python-Add-li_std_string-runtime-test.patch b/swig-python-Add-li_std_string-runtime-test.patch new file mode 100644 index 0000000..fbd7c86 --- /dev/null +++ b/swig-python-Add-li_std_string-runtime-test.patch @@ -0,0 +1,140 @@ +From 32afafda3366841a2c3610f4ad87774881eef3ae Mon Sep 17 00:00:00 2001 +From: William S Fulton +Date: Sun, 20 Oct 2024 12:43:43 +0100 +Subject: [PATCH] Add li_std_string runtime test + +--- + .../test-suite/python/li_std_string_runme.py | 121 ++++++++++++++++++ + 1 file changed, 121 insertions(+) + create mode 100644 Examples/test-suite/python/li_std_string_runme.py + +diff --git a/Examples/test-suite/python/li_std_string_runme.py b/Examples/test-suite/python/li_std_string_runme.py +new file mode 100644 +index 000000000..70f428193 +--- /dev/null ++++ b/Examples/test-suite/python/li_std_string_runme.py +@@ -0,0 +1,121 @@ ++from li_std_string import * ++ ++def check(condition): ++ if not condition: ++ raise RuntimeError ++ ++# Checking expected use of %typemap(in) std::string {} ++test_value("Fee") ++ ++# Checking expected result of %typemap(out) std::string {} ++check(test_value("Fi") == "Fi") ++ ++# Verify type-checking for %typemap(in) std::string {} ++exceptionRaised = False ++try: ++ test_value(0) ++except TypeError: ++ exceptionRaised = True ++check(exceptionRaised) ++ ++# Checking expected use of %typemap(in) const std::string & {} ++test_const_reference("Fo") ++ ++# Checking expected result of %typemap(out) const std::string& {} ++check(test_const_reference("Fum") == "Fum") ++ ++# Verify type-checking for %typemap(in) const std::string & {} ++exceptionRaised = False ++try: ++ test_const_reference(0) ++except TypeError: ++ exceptionRaised = True ++check(exceptionRaised) ++ ++# ++# Input and output typemaps for pointers and non-const references to ++# std::string are *not* supported; the following tests confirm ++# that none of these cases are slipping through. ++# ++ ++exceptionRaised = False ++try: ++ test_pointer("foo") ++except TypeError: ++ exceptionRaised = True ++check(exceptionRaised) ++ ++result = test_pointer_out() ++check(not isinstance(result, str)) ++ ++exceptionRaised = False ++try: ++ test_const_pointer("bar") ++except TypeError: ++ exceptionRaised = True ++check(exceptionRaised) ++ ++result = test_const_pointer_out() ++check(not isinstance(result, str)) ++ ++exceptionRaised = False ++try: ++ test_reference("foo") ++except TypeError: ++ exceptionRaised = True ++check(exceptionRaised) ++ ++result = test_reference_out() ++check(not isinstance(result, str)) ++ ++ ++# Member Strings ++myStructure = Structure() ++if myStructure.MemberString2 != "member string 2": ++ raise RuntimeError ++s = "Hello" ++myStructure.MemberString2 = s ++if myStructure.MemberString2 != s: ++ raise RuntimeError ++if myStructure.ConstMemberString != "const member string": ++ raise RuntimeError ++ ++ ++if cvar.Structure_StaticMemberString2 != "static member string 2": ++ raise RuntimeError ++cvar.Structure_StaticMemberString2 = s ++if cvar.Structure_StaticMemberString2 != s: ++ raise RuntimeError ++if Structure.ConstStaticMemberString != "const static member string": ++ raise RuntimeError ++ ++ ++if test_reference_input("hello") != "hello": ++ raise RuntimeError ++s = test_reference_inout("hello") ++if s != "hellohello": ++ raise RuntimeError ++if test_reference_output() != "output": ++ raise RuntimeError ++ ++ ++if stdstring_empty() != "": ++ raise RuntimeError ++ ++if c_empty() != "": ++ raise RuntimeError ++ ++ ++if c_null() != None: ++ raise RuntimeError ++ ++ ++if get_null(c_null()) != None: ++ raise RuntimeError ++ ++ ++if get_null(c_empty()) != "non-null": ++ raise RuntimeError ++ ++if get_null(stdstring_empty()) != "non-null": ++ raise RuntimeError +-- +2.47.0 + diff --git a/swig-python-Fix-seg-fault-passing-invalid-unicode-values-to-std-.patch b/swig-python-Fix-seg-fault-passing-invalid-unicode-values-to-std-.patch new file mode 100644 index 0000000..b78c04e --- /dev/null +++ b/swig-python-Fix-seg-fault-passing-invalid-unicode-values-to-std-.patch @@ -0,0 +1,244 @@ +From d06382ec2a48b9e93a06c7cef1f09bc6fa344fca Mon Sep 17 00:00:00 2001 +From: William S Fulton +Date: Sun, 20 Oct 2024 13:39:11 +0100 +Subject: [PATCH] Fix seg fault passing invalid unicode values to std::string + +Problem reported as starting with python-3.13. +Due to error not being cleared before calling Python C APIs. + +The alternative could have been to ensure SWIG_AsCharPtrAndSize +never returns with a pending error (not that easy). + +Closes #3051 +--- +# CHANGES.current | 4 ++ + .../test-suite/python/li_std_string_runme.py | 66 ++++++++++++------- + Lib/python/pytypemaps.swg | 3 + + Lib/typemaps/std_strings.swg | 8 +-- + Lib/typemaps/swigtypemaps.swg | 6 ++ + 5 files changed, 56 insertions(+), 31 deletions(-) + +#diff --git a/CHANGES.current b/CHANGES.current +#index 96a299fa6..568f88086 100644 +#--- a/CHANGES.current +#+++ b/CHANGES.current +#@@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ +# Version 4.3.0 (in progress) +# =========================== +# +#+2024-10-20: wsfulton +#+ #3051 Fix seg fault passing invalid unicode values when expecting a +#+ std::string type - fix for python-3.13. +#+ +# 2024-10-19: olly +# [ruby] Documentation comments now use `true` and `false` for bool +# parameter default values, instead of `True` and `False` (which are +diff --git a/Examples/test-suite/python/li_std_string_runme.py b/Examples/test-suite/python/li_std_string_runme.py +index 70f428193..1a57529e1 100644 +--- a/Examples/test-suite/python/li_std_string_runme.py ++++ b/Examples/test-suite/python/li_std_string_runme.py +@@ -1,9 +1,25 @@ ++import sys + from li_std_string import * + + def check(condition): + if not condition: + raise RuntimeError + ++# Bad Unicode input check ++# This check is run first to check that %error_clear is called the first time SWIG_AsPtr_std_string() ++# is called setting the descriptor singleton (by calling SWIG_TypeQuery()). ++# Bug https://github.com/swig/swig/issues/3051. ++exceptionRaised = False ++try: ++ if sys.version_info[0:2] < (3, 0): ++ v = u"./\uDCFC.conf" ++ else: ++ v = "./\uDCFC.conf" ++ test_value(v) ++except TypeError: ++ exceptionRaised = True ++check(exceptionRaised) ++ + # Checking expected use of %typemap(in) std::string {} + test_value("Fee") + +@@ -13,9 +29,9 @@ check(test_value("Fi") == "Fi") + # Verify type-checking for %typemap(in) std::string {} + exceptionRaised = False + try: +- test_value(0) ++ test_value(0) + except TypeError: +- exceptionRaised = True ++ exceptionRaised = True + check(exceptionRaised) + + # Checking expected use of %typemap(in) const std::string & {} +@@ -27,9 +43,9 @@ check(test_const_reference("Fum") == "Fum") + # Verify type-checking for %typemap(in) const std::string & {} + exceptionRaised = False + try: +- test_const_reference(0) ++ test_const_reference(0) + except TypeError: +- exceptionRaised = True ++ exceptionRaised = True + check(exceptionRaised) + + # +@@ -40,9 +56,9 @@ check(exceptionRaised) + + exceptionRaised = False + try: +- test_pointer("foo") ++ test_pointer("foo") + except TypeError: +- exceptionRaised = True ++ exceptionRaised = True + check(exceptionRaised) + + result = test_pointer_out() +@@ -50,9 +66,9 @@ check(not isinstance(result, str)) + + exceptionRaised = False + try: +- test_const_pointer("bar") ++ test_const_pointer("bar") + except TypeError: +- exceptionRaised = True ++ exceptionRaised = True + check(exceptionRaised) + + result = test_const_pointer_out() +@@ -60,9 +76,9 @@ check(not isinstance(result, str)) + + exceptionRaised = False + try: +- test_reference("foo") ++ test_reference("foo") + except TypeError: +- exceptionRaised = True ++ exceptionRaised = True + check(exceptionRaised) + + result = test_reference_out() +@@ -72,50 +88,50 @@ check(not isinstance(result, str)) + # Member Strings + myStructure = Structure() + if myStructure.MemberString2 != "member string 2": +- raise RuntimeError ++ raise RuntimeError + s = "Hello" + myStructure.MemberString2 = s + if myStructure.MemberString2 != s: +- raise RuntimeError ++ raise RuntimeError + if myStructure.ConstMemberString != "const member string": +- raise RuntimeError ++ raise RuntimeError + + + if cvar.Structure_StaticMemberString2 != "static member string 2": +- raise RuntimeError ++ raise RuntimeError + cvar.Structure_StaticMemberString2 = s + if cvar.Structure_StaticMemberString2 != s: +- raise RuntimeError ++ raise RuntimeError + if Structure.ConstStaticMemberString != "const static member string": +- raise RuntimeError ++ raise RuntimeError + + + if test_reference_input("hello") != "hello": +- raise RuntimeError ++ raise RuntimeError + s = test_reference_inout("hello") + if s != "hellohello": +- raise RuntimeError ++ raise RuntimeError + if test_reference_output() != "output": +- raise RuntimeError ++ raise RuntimeError + + + if stdstring_empty() != "": +- raise RuntimeError ++ raise RuntimeError + + if c_empty() != "": +- raise RuntimeError ++ raise RuntimeError + + + if c_null() != None: +- raise RuntimeError ++ raise RuntimeError + + + if get_null(c_null()) != None: +- raise RuntimeError ++ raise RuntimeError + + + if get_null(c_empty()) != "non-null": +- raise RuntimeError ++ raise RuntimeError + + if get_null(stdstring_empty()) != "non-null": +- raise RuntimeError ++ raise RuntimeError +diff --git a/Lib/python/pytypemaps.swg b/Lib/python/pytypemaps.swg +index 923c0e251..f4a6e4577 100644 +--- a/Lib/python/pytypemaps.swg ++++ b/Lib/python/pytypemaps.swg +@@ -57,6 +57,9 @@ + /* raise */ + #define SWIG_Raise(obj, type, desc) SWIG_Python_Raise(obj, type, desc) + ++/* clear errors */ ++#define %error_clear PyErr_Clear() ++ + /* Include the unified typemap library */ + %include + +diff --git a/Lib/typemaps/std_strings.swg b/Lib/typemaps/std_strings.swg +index 842545826..28ef5e48d 100644 +--- a/Lib/typemaps/std_strings.swg ++++ b/Lib/typemaps/std_strings.swg +@@ -17,12 +17,8 @@ SWIG_AsPtr_dec(String)(SWIG_Object obj, String **val) + return SWIG_OLDOBJ; + } + } else { +- static int init = 0; +- static swig_type_info* descriptor = 0; +- if (!init) { +- descriptor = SWIG_TypeQuery(#String " *"); +- init = 1; +- } ++ %error_clear; ++ static swig_type_info *descriptor = SWIG_TypeQuery(#String " *"); + if (descriptor) { + String *vptr; + int res = SWIG_ConvertPtr(obj, (void**)&vptr, descriptor, 0); +diff --git a/Lib/typemaps/swigtypemaps.swg b/Lib/typemaps/swigtypemaps.swg +index 3c3014f84..0c95c2f98 100644 +--- a/Lib/typemaps/swigtypemaps.swg ++++ b/Lib/typemaps/swigtypemaps.swg +@@ -121,6 +121,12 @@ + #endif + #endif + ++/*==== clear errors ====*/ ++ ++#ifndef %error_clear ++#define %error_clear ++#endif ++ + /*==== director output exception ====*/ + + #if defined(SWIG_DIRECTOR_TYPEMAPS) +-- +2.47.0 + diff --git a/swig.spec b/swig.spec index a8eb803..81e3502 100644 --- a/swig.spec +++ b/swig.spec @@ -68,7 +68,7 @@ Summary: Connects C/C++/Objective C to some high-level programming languages Name: swig Version: 4.2.1 -Release: 8%{?dist} +Release: 9%{?dist} License: GPL-3.0-or-later AND BSD-3-Clause URL: https://www.swig.org/ Source0: http://downloads.sourceforge.net/project/swig/swig/swig-%{version}/swig-%{version}.tar.gz @@ -88,6 +88,10 @@ Patch2: swig-R-Fix-gcc-s-Wformat-security-warning-in-R-Raise-functi.patch # Python 3.13 support: https://github.com/swig/swig/pull/2925 Patch3: swig-python-Python-3.13-strips-docstring-indent.patch Patch4: swig-python-Python-3.13-deprecates-PyWeakref_GET_OBJECT.patch +# Fix seg fault passing invalid unicode values to std::string +# in upstream since 4.3.0 +Patch5: swig-python-Add-li_std_string-runtime-test.patch +Patch6: swig-python-Fix-seg-fault-passing-invalid-unicode-values-to-std-.patch BuildRequires: coreutils BuildRequires: findutils @@ -371,6 +375,9 @@ install -pm 644 Tools/swig.gdb %{buildroot}%{_datadir}/%{name}/gdb %{_datadir}/%{name}/gdb %changelog +* Mon Dec 02 2024 Jitka Plesnikova - 4.2.1-9 +- Fix seg fault passing invalid unicode values to std::string (rhbz#2318762) + * Sat Jul 20 2024 Fedora Release Engineering - 4.2.1-8 - Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild