mirror of
https://github.com/beard7n/bsdports.git
synced 2026-04-14 20:41:20 +02:00
create bsd12 branch
This commit is contained in:
51
lang/python34/Makefile
Normal file
51
lang/python34/Makefile
Normal file
@@ -0,0 +1,51 @@
|
||||
#
|
||||
# $Id: Makefile 2493 2009-09-19 15:10:11Z root $
|
||||
# $URL: file:///usr2/svn/ports5/lang/python25/Makefile $
|
||||
#
|
||||
|
||||
PORTNAME= python
|
||||
PORTVERSION= 3.4.10
|
||||
CATEGORIES= lang python
|
||||
MASTER_SITES= PYTHON
|
||||
MASTER_SITE_SUBDIR= ftp/python/${PORTVERSION}
|
||||
DISTNAME= Python-${PORTVERSION}
|
||||
DIST_SUBDIR= python
|
||||
PKGNAMESUFFIX= 34
|
||||
|
||||
MAINTAINER= onborodin@gmail.com
|
||||
COMMENT= An interpreted object-oriented programming language
|
||||
|
||||
#LIB_DEPENDS+= libsqlite3.so:data/sqlite3
|
||||
LIB_DEPENDS+= libexpat.so:text/libexpat
|
||||
|
||||
|
||||
USES+= tar:xz
|
||||
GNU_CONFIGURE= yes
|
||||
INSTALLS_SHLIB= yes
|
||||
USES+= gmake
|
||||
CONFIGURE_ENV= OPT="${CFLAGS}" SVNVERSION="echo freebsd"
|
||||
MAKE_ENV= VPATH="${PYTHON_WRKSRC}"
|
||||
|
||||
CONFIGURE_ARGS+= --enable-ipv6
|
||||
CONFIGURE_ARGS+= --with-system-expat
|
||||
|
||||
CONFIGURE_ARGS+= --with-threads
|
||||
CONFIGURE_ARGS+= --enable-shared
|
||||
CONFIGURE_ARGS+= --mandir=${PREFIX}/man
|
||||
CPPFLAGS= -pthread
|
||||
LDFLAGS+= -pthread
|
||||
|
||||
DISABLED_EXTENSIONS= _sqlite3 _tkinter _gdbm nis
|
||||
CONFIGURE_ARGS+= --without-ensurepip
|
||||
CONFIGURE_ENV+= OPT="" DISABLED_EXTENSIONS="${DISABLED_EXTENSIONS}"
|
||||
INSTALL_TARGET= altinstall
|
||||
|
||||
PLIST_SUB= VERSION=${PORTVERSION:R}
|
||||
VERSION_SHORT= ${PORTVERSION:R}
|
||||
|
||||
PLIST_SUB+= OSMAJOR=${OSVERSION:C/([0-9]*)[0-9]{5}/\1/}
|
||||
|
||||
|
||||
.include <bsd.port.mk>
|
||||
#EOF
|
||||
|
||||
3
lang/python34/distinfo
Normal file
3
lang/python34/distinfo
Normal file
@@ -0,0 +1,3 @@
|
||||
TIMESTAMP = 1577282567
|
||||
SHA256 (python/Python-3.4.10.tar.xz) = d46a8f6fe91679e199c671b1b0a30aaf172d2acb5bcab25beb35f16c3d195b4e
|
||||
SIZE (python/Python-3.4.10.tar.xz) = 14559088
|
||||
822
lang/python34/files/00055-systemtap.patch
Normal file
822
lang/python34/files/00055-systemtap.patch
Normal file
@@ -0,0 +1,822 @@
|
||||
diff -up Python-3.3.0rc2/configure.ac.systemtap Python-3.3.0rc2/configure.ac
|
||||
--- Python-3.3.0rc2/configure.ac.systemtap 2012-09-09 05:11:14.000000000 -0400
|
||||
+++ Python-3.3.0rc2/configure.ac 2012-09-10 09:17:21.114511781 -0400
|
||||
@@ -2678,6 +2678,23 @@ if test "$with_valgrind" != no; then
|
||||
OPT="-DDYNAMIC_ANNOTATIONS_ENABLED=1 $OPT"
|
||||
fi
|
||||
|
||||
+# Check for systemtap support
|
||||
+# On Linux, /usr/bin/dtrace is in fact a shim to SystemTap
|
||||
+AC_MSG_CHECKING([for --with-systemtap])
|
||||
+AC_ARG_WITH([systemtap],
|
||||
+ AC_HELP_STRING([--with(out)-systemtap], [disable/enable SystemTap support]),,
|
||||
+ with_systemtap=no)
|
||||
+AC_MSG_RESULT([$with_systemtap])
|
||||
+if test "$with_systemtap" != no; then
|
||||
+ AC_DEFINE(WITH_SYSTEMTAP, 1,
|
||||
+ [Define if you want to compile in SystemTap support])
|
||||
+ SYSTEMTAPOBJS="Python/pysystemtap.o"
|
||||
+ SYSTEMTAPDEPS="\$(srcdir)/Python/pysystemtap.h"
|
||||
+fi
|
||||
+
|
||||
+AC_SUBST(SYSTEMTAPOBJS)
|
||||
+AC_SUBST(SYSTEMTAPDEPS)
|
||||
+
|
||||
# -I${DLINCLDIR} is added to the compile rule for importdl.o
|
||||
AC_SUBST(DLINCLDIR)
|
||||
DLINCLDIR=.
|
||||
diff -up Python-3.3.0rc2/configure.systemtap Python-3.3.0rc2/configure
|
||||
--- Python-3.3.0rc2/configure.systemtap 2012-09-09 05:11:14.000000000 -0400
|
||||
+++ Python-3.3.0rc2/configure 2012-09-10 09:17:21.116511780 -0400
|
||||
@@ -618,6 +618,8 @@ TRUE
|
||||
MACHDEP_OBJS
|
||||
DYNLOADFILE
|
||||
DLINCLDIR
|
||||
+SYSTEMTAPDEPS
|
||||
+SYSTEMTAPOBJS
|
||||
THREADOBJ
|
||||
LDLAST
|
||||
USE_THREAD_MODULE
|
||||
@@ -779,6 +781,7 @@ with_doc_strings
|
||||
with_tsc
|
||||
with_pymalloc
|
||||
with_valgrind
|
||||
+with_systemtap
|
||||
with_fpectl
|
||||
with_libm
|
||||
with_libc
|
||||
@@ -1456,6 +1459,7 @@ Optional Packages:
|
||||
--with(out)-tsc enable/disable timestamp counter profile
|
||||
--with(out)-pymalloc disable/enable specialized mallocs
|
||||
--with-valgrind Enable Valgrind support
|
||||
+ --with(out)-systemtap disable/enable SystemTap support
|
||||
--with-fpectl enable SIGFPE catching
|
||||
--with-libm=STRING math library
|
||||
--with-libc=STRING C library
|
||||
@@ -10065,6 +10069,31 @@ fi
|
||||
OPT="-DDYNAMIC_ANNOTATIONS_ENABLED=1 $OPT"
|
||||
fi
|
||||
|
||||
+# Check for systemtap support
|
||||
+# On Linux, /usr/bin/dtrace is in fact a shim to SystemTap
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-systemtap" >&5
|
||||
+$as_echo_n "checking for --with-systemtap... " >&6; }
|
||||
+
|
||||
+# Check whether --with-systemtap was given.
|
||||
+if test "${with_systemtap+set}" = set; then :
|
||||
+ withval=$with_systemtap;
|
||||
+else
|
||||
+ with_systemtap=no
|
||||
+fi
|
||||
+
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_systemtap" >&5
|
||||
+$as_echo "$with_systemtap" >&6; }
|
||||
+if test "$with_systemtap" != no; then
|
||||
+
|
||||
+$as_echo "#define WITH_SYSTEMTAP 1" >>confdefs.h
|
||||
+
|
||||
+ SYSTEMTAPOBJS="Python/pysystemtap.o"
|
||||
+ SYSTEMTAPDEPS="\$(srcdir)/Python/pysystemtap.h"
|
||||
+fi
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
# -I${DLINCLDIR} is added to the compile rule for importdl.o
|
||||
|
||||
DLINCLDIR=.
|
||||
diff -up Python-3.3.0rc2/Doc/howto/index.rst.systemtap Python-3.3.0rc2/Doc/howto/index.rst
|
||||
--- Python-3.3.0rc2/Doc/howto/index.rst.systemtap 2012-09-09 05:10:51.000000000 -0400
|
||||
+++ Python-3.3.0rc2/Doc/howto/index.rst 2012-09-10 09:17:21.117511779 -0400
|
||||
@@ -29,4 +29,5 @@ Currently, the HOWTOs are:
|
||||
argparse.rst
|
||||
ipaddress.rst
|
||||
clinic.rst
|
||||
+ instrumentation.rst
|
||||
|
||||
diff -up Python-3.3.0rc2/Doc/howto/instrumentation.rst.systemtap Python-3.3.0rc2/Doc/howto/instrumentation.rst
|
||||
--- Python-3.3.0rc2/Doc/howto/instrumentation.rst.systemtap 2012-09-10 09:17:21.117511779 -0400
|
||||
+++ Python-3.3.0rc2/Doc/howto/instrumentation.rst 2012-09-10 09:17:21.117511779 -0400
|
||||
@@ -0,0 +1,295 @@
|
||||
+.. _instrumentation:
|
||||
+
|
||||
+====================================
|
||||
+Instrumenting CPython with SystemTap
|
||||
+====================================
|
||||
+
|
||||
+:author: David Malcolm <dmalcolm@redhat.com>
|
||||
+
|
||||
+DTrace and SystemTap are monitoring tools, each providing a way to inspect
|
||||
+what the processes on a computer system are doing. They both use
|
||||
+domain-specific languages allowing a user to write scripts which:
|
||||
+
|
||||
+ - filter which processes are to be observed
|
||||
+ - gather data from the processes of interest
|
||||
+ - generate reports on the data
|
||||
+
|
||||
+As of Python 3.3, CPython can be built with embedded "markers" that can be
|
||||
+observed by a SystemTap script, making it easier to monitor what the CPython
|
||||
+processes on a system are doing.
|
||||
+
|
||||
+.. Potentially this document could be expanded to also cover DTrace markers.
|
||||
+ However, I'm not a DTrace expert.
|
||||
+
|
||||
+.. I'm using ".. code-block:: c" for SystemTap scripts, as "c" is syntactically
|
||||
+ the closest match that Sphinx supports
|
||||
+
|
||||
+
|
||||
+Enabling the static markers
|
||||
+---------------------------
|
||||
+
|
||||
+In order to build CPython with the embedded markers for SystemTap, the
|
||||
+SystemTap development tools must be installed.
|
||||
+
|
||||
+On a Fedora or Red Hat Enterprise Linux machine, this can be done via::
|
||||
+
|
||||
+ yum install systemtap-sdt-devel
|
||||
+
|
||||
+CPython must then be configured `--with-systemtap`::
|
||||
+
|
||||
+ checking for --with-systemtap... yes
|
||||
+
|
||||
+You can verify if the SystemTap static markers are present in the built
|
||||
+binary by seeing if it contains a ".note.stapsdt" section.
|
||||
+
|
||||
+.. code-block:: bash
|
||||
+
|
||||
+ $ eu-readelf -S ./python | grep .note.stapsdt
|
||||
+ [29] .note.stapsdt NOTE 0000000000000000 00308d78 000000b8 0 0 0 4
|
||||
+
|
||||
+If you've built python as a shared library (with --enable-shared), you need
|
||||
+to look instead within the shared library. For example:
|
||||
+
|
||||
+.. code-block:: bash
|
||||
+
|
||||
+ $ eu-readelf -S libpython3.3dm.so.1.0 | grep .note.stapsdt
|
||||
+ [28] .note.stapsdt NOTE 0000000000000000 00365b68 000000b8 0 0 0 4
|
||||
+
|
||||
+Earlier versions of SystemTap stored the markers in a ".probes" section.
|
||||
+
|
||||
+For the curious, you can see the metadata for the static markers using this
|
||||
+invocation.
|
||||
+
|
||||
+.. code-block:: bash
|
||||
+
|
||||
+ $ eu-readelf -x .note.stapsdt ./python
|
||||
+
|
||||
+ Hex dump of section [29] '.note.stapsdt', 184 bytes at offset 0x308d78:
|
||||
+ 0x00000000 08000000 45000000 03000000 73746170 ....E.......stap
|
||||
+ 0x00000010 73647400 d4664b00 00000000 4fc36600 sdt..fK.....O.f.
|
||||
+ 0x00000020 00000000 488d9000 00000000 70797468 ....H.......pyth
|
||||
+ 0x00000030 6f6e0066 756e6374 696f6e5f 5f656e74 on.function__ent
|
||||
+ 0x00000040 72790038 40257261 78203840 25726478 ry.8@%rax 8@%rdx
|
||||
+ 0x00000050 202d3440 25656378 00000000 08000000 -4@%ecx........
|
||||
+ 0x00000060 46000000 03000000 73746170 73647400 F.......stapsdt.
|
||||
+ 0x00000070 0d674b00 00000000 4fc36600 00000000 .gK.....O.f.....
|
||||
+ 0x00000080 4a8d9000 00000000 70797468 6f6e0066 J.......python.f
|
||||
+ 0x00000090 756e6374 696f6e5f 5f726574 75726e00 unction__return.
|
||||
+ 0x000000a0 38402572 61782038 40257264 78202d34 8@%rax 8@%rdx -4
|
||||
+ 0x000000b0 40256563 78000000 @%ecx...
|
||||
+
|
||||
+and a sufficiently modern eu-readelf can print the metadata:
|
||||
+
|
||||
+.. code-block:: bash
|
||||
+
|
||||
+ $ eu-readelf -n ./python
|
||||
+
|
||||
+ Note section [ 1] '.note.gnu.build-id' of 36 bytes at offset 0x190:
|
||||
+ Owner Data size Type
|
||||
+ GNU 20 GNU_BUILD_ID
|
||||
+ Build ID: a28f8db1b224530b0d38ad7b82a249cf7c3f18d6
|
||||
+
|
||||
+ Note section [27] '.note.stapsdt' of 184 bytes at offset 0x1ae884:
|
||||
+ Owner Data size Type
|
||||
+ stapsdt 70 Version: 3
|
||||
+ PC: 0xe0d3a, Base: 0x14b150, Semaphore: 0x3ae882
|
||||
+ Provider: python, Name: function__return, Args: '8@%rbx 8@%r13 -4@%eax'
|
||||
+ stapsdt 69 Version: 3
|
||||
+ PC: 0xe0f37, Base: 0x14b150, Semaphore: 0x3ae880
|
||||
+ Provider: python, Name: function__entry, Args: '8@%rbx 8@%r13 -4@%eax'
|
||||
+
|
||||
+The above metadata contains information for SystemTap describing how it can
|
||||
+patch strategically-placed machine code instructions to enable the tracing
|
||||
+hooks used by a SystemTap script.
|
||||
+
|
||||
+
|
||||
+Static markers
|
||||
+--------------
|
||||
+
|
||||
+The low-level way to use the SystemTap integration is to use the static
|
||||
+markers directly. This requires you to explicitly state the binary file
|
||||
+containing them.
|
||||
+
|
||||
+For example, this script can be used to show the call/return hierarchy of a
|
||||
+Python script:
|
||||
+
|
||||
+.. code-block:: c
|
||||
+
|
||||
+ probe process('python').mark("function__entry") {
|
||||
+ filename = user_string($arg1);
|
||||
+ funcname = user_string($arg2);
|
||||
+ lineno = $arg3;
|
||||
+
|
||||
+ printf("%s => %s in %s:%d\\n",
|
||||
+ thread_indent(1), funcname, filename, lineno);
|
||||
+ }
|
||||
+
|
||||
+ probe process('python').mark("function__return") {
|
||||
+ filename = user_string($arg1);
|
||||
+ funcname = user_string($arg2);
|
||||
+ lineno = $arg3;
|
||||
+
|
||||
+ printf("%s <= %s in %s:%d\\n",
|
||||
+ thread_indent(-1), funcname, filename, lineno);
|
||||
+ }
|
||||
+
|
||||
+It can be invoked like this:
|
||||
+
|
||||
+.. code-block:: bash
|
||||
+
|
||||
+ $ stap \
|
||||
+ show-call-hierarchy.stp \
|
||||
+ -c ./python test.py
|
||||
+
|
||||
+The output looks like this::
|
||||
+
|
||||
+ 11408 python(8274): => __contains__ in Lib/_abcoll.py:362
|
||||
+ 11414 python(8274): => __getitem__ in Lib/os.py:425
|
||||
+ 11418 python(8274): => encode in Lib/os.py:490
|
||||
+ 11424 python(8274): <= encode in Lib/os.py:493
|
||||
+ 11428 python(8274): <= __getitem__ in Lib/os.py:426
|
||||
+ 11433 python(8274): <= __contains__ in Lib/_abcoll.py:366
|
||||
+
|
||||
+where the columns are:
|
||||
+
|
||||
+ - time in microseconds since start of script
|
||||
+
|
||||
+ - name of executable
|
||||
+
|
||||
+ - PID of process
|
||||
+
|
||||
+and the remainder indicates the call/return hierarchy as the script executes.
|
||||
+
|
||||
+For a `--enable-shared` build of CPython, the markers are contained within the
|
||||
+libpython shared library, and the probe's dotted path needs to reflect this. For
|
||||
+example, this line from the above example::
|
||||
+
|
||||
+ probe process('python').mark("function__entry") {
|
||||
+
|
||||
+should instead read::
|
||||
+
|
||||
+ probe process('python').library("libpython3.3dm.so.1.0").mark("function__entry") {
|
||||
+
|
||||
+(assuming a debug build of CPython 3.3)
|
||||
+
|
||||
+.. I'm reusing the "c:function" type for markers
|
||||
+
|
||||
+.. c:function:: function__entry(str filename, str funcname, int lineno)
|
||||
+
|
||||
+ This marker indicates that execution of a Python function has begun. It is
|
||||
+ only triggered for pure-python (bytecode) functions.
|
||||
+
|
||||
+ The filename, function name, and line number are provided back to the
|
||||
+ tracing script as positional arguments, which must be accessed using
|
||||
+ `$arg1`, `$arg2`:
|
||||
+
|
||||
+ * `$arg1` : `(const char *)` filename, accessible using `user_string($arg1)`
|
||||
+
|
||||
+ * `$arg2` : `(const char *)` function name, accessible using
|
||||
+ `user_string($arg2)`
|
||||
+
|
||||
+ * `$arg3` : `int` line number
|
||||
+
|
||||
+ * `$arg4` : `(PyFrameObject *)`, the frame being executed
|
||||
+
|
||||
+.. c:function:: function__return(str filename, str funcname, int lineno)
|
||||
+
|
||||
+ This marker is the converse of `function__entry`, and indicates that
|
||||
+ execution of a Python function has ended (either via ``return``, or via an
|
||||
+ exception). It is only triggered for pure-python (bytecode) functions.
|
||||
+
|
||||
+ The arguments are the same as for `function__entry`
|
||||
+
|
||||
+
|
||||
+Tapsets
|
||||
+-------
|
||||
+
|
||||
+The higher-level way to use the SystemTap integration is to use a "tapset":
|
||||
+SystemTap's equivalent of a library, which hides some of the lower-level
|
||||
+details of the static markers.
|
||||
+
|
||||
+Here is a tapset file, based on a non-shared build of CPython:
|
||||
+
|
||||
+.. code-block:: c
|
||||
+
|
||||
+ /*
|
||||
+ Provide a higher-level wrapping around the function__entry and
|
||||
+ function__return markers:
|
||||
+ */
|
||||
+ probe python.function.entry = process("python").mark("function__entry")
|
||||
+ {
|
||||
+ filename = user_string($arg1);
|
||||
+ funcname = user_string($arg2);
|
||||
+ lineno = $arg3;
|
||||
+ frameptr = $arg4
|
||||
+ }
|
||||
+ probe python.function.return = process("python").mark("function__return")
|
||||
+ {
|
||||
+ filename = user_string($arg1);
|
||||
+ funcname = user_string($arg2);
|
||||
+ lineno = $arg3;
|
||||
+ frameptr = $arg4
|
||||
+ }
|
||||
+
|
||||
+If this file is installed in SystemTap's tapset directory (e.g.
|
||||
+`/usr/share/systemtap/tapset`), then these additional probepoints become
|
||||
+available:
|
||||
+
|
||||
+.. c:function:: python.function.entry(str filename, str funcname, int lineno, frameptr)
|
||||
+
|
||||
+ This probe point indicates that execution of a Python function has begun.
|
||||
+ It is only triggered for pure-python (bytecode) functions.
|
||||
+
|
||||
+.. c:function:: python.function.return(str filename, str funcname, int lineno, frameptr)
|
||||
+
|
||||
+ This probe point is the converse of `python.function.return`, and indicates
|
||||
+ that execution of a Python function has ended (either via ``return``, or
|
||||
+ via an exception). It is only triggered for pure-python (bytecode) functions.
|
||||
+
|
||||
+
|
||||
+Examples
|
||||
+--------
|
||||
+This SystemTap script uses the tapset above to more cleanly implement the
|
||||
+example given above of tracing the Python function-call hierarchy, without
|
||||
+needing to directly name the static markers:
|
||||
+
|
||||
+.. code-block:: c
|
||||
+
|
||||
+ probe python.function.entry
|
||||
+ {
|
||||
+ printf("%s => %s in %s:%d\n",
|
||||
+ thread_indent(1), funcname, filename, lineno);
|
||||
+ }
|
||||
+
|
||||
+ probe python.function.return
|
||||
+ {
|
||||
+ printf("%s <= %s in %s:%d\n",
|
||||
+ thread_indent(-1), funcname, filename, lineno);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+The following script uses the tapset above to provide a top-like view of all
|
||||
+running CPython code, showing the top 20 most frequently-entered bytecode
|
||||
+frames, each second, across the whole system:
|
||||
+
|
||||
+.. code-block:: c
|
||||
+
|
||||
+ global fn_calls;
|
||||
+
|
||||
+ probe python.function.entry
|
||||
+ {
|
||||
+ fn_calls[pid(), filename, funcname, lineno] += 1;
|
||||
+ }
|
||||
+
|
||||
+ probe timer.ms(1000) {
|
||||
+ printf("\033[2J\033[1;1H") /* clear screen */
|
||||
+ printf("%6s %80s %6s %30s %6s\n",
|
||||
+ "PID", "FILENAME", "LINE", "FUNCTION", "CALLS")
|
||||
+ foreach ([pid, filename, funcname, lineno] in fn_calls- limit 20) {
|
||||
+ printf("%6d %80s %6d %30s %6d\n",
|
||||
+ pid, filename, lineno, funcname,
|
||||
+ fn_calls[pid, filename, funcname, lineno]);
|
||||
+ }
|
||||
+ delete fn_calls;
|
||||
+ }
|
||||
+
|
||||
diff -up Python-3.3.0rc2/Lib/test/test_systemtap.py.systemtap Python-3.3.0rc2/Lib/test/test_systemtap.py
|
||||
--- Python-3.3.0rc2/Lib/test/test_systemtap.py.systemtap 2012-09-10 09:17:21.117511779 -0400
|
||||
+++ Python-3.3.0rc2/Lib/test/test_systemtap.py 2012-09-10 09:17:21.117511779 -0400
|
||||
@@ -0,0 +1,234 @@
|
||||
+# Verify that systemtap static probes work
|
||||
+#
|
||||
+import subprocess
|
||||
+import sys
|
||||
+import sysconfig
|
||||
+import os
|
||||
+import unittest
|
||||
+
|
||||
+from test.support import run_unittest, TESTFN, unlink
|
||||
+
|
||||
+if '--with-systemtap' not in sysconfig.get_config_var('CONFIG_ARGS'):
|
||||
+ raise unittest.SkipTest("Python was not configured --with-systemtap")
|
||||
+
|
||||
+try:
|
||||
+ _, stap_version = subprocess.Popen(["stap", "-V"],
|
||||
+ stdout=subprocess.PIPE,
|
||||
+ stderr=subprocess.PIPE,
|
||||
+ ).communicate()
|
||||
+except OSError:
|
||||
+ # This is what "no stap" looks like. There may, however, be other
|
||||
+ # errors that manifest this way too.
|
||||
+ raise unittest.SkipTest("Couldn't find stap on the path")
|
||||
+
|
||||
+def invoke_systemtap_script(script, cmd):
|
||||
+ # Start a child process, probing with the given systemtap script
|
||||
+ # (passed as stdin to the "stap" tool)
|
||||
+ # The script should be a bytes instance
|
||||
+ # Return (stdout, stderr) pair
|
||||
+
|
||||
+ p = subprocess.Popen(["stap", "-", '-vv', '-c', cmd],
|
||||
+ stdin=subprocess.PIPE,
|
||||
+ stdout=subprocess.PIPE,
|
||||
+ stderr=subprocess.PIPE)
|
||||
+ out, err = p.communicate(input=script)
|
||||
+ return out, err
|
||||
+
|
||||
+# Verify that stap can run a simple "hello world"-style script
|
||||
+# This can fail for various reasons:
|
||||
+# - missing kernel headers
|
||||
+# - permissions (a non-root user needs to be in the "stapdev" group)
|
||||
+TRIVIAL_STAP_SCRIPT = b'probe begin { println("hello world") exit () }'
|
||||
+
|
||||
+out, err = invoke_systemtap_script(TRIVIAL_STAP_SCRIPT, 'true')
|
||||
+if out != b'hello world\n':
|
||||
+ raise unittest.SkipTest("Test systemtap script did not run; stderr was: %s" % err)
|
||||
+
|
||||
+# We don't expect stderr to be empty, since we're invoking stap with "-vv": stap
|
||||
+# will (we hope) generate debugging output on stderr.
|
||||
+
|
||||
+def invoke_python_under_systemtap(script, pythoncode=None, pythonfile=None):
|
||||
+ # Start a child python process, probing with the given systemtap script
|
||||
+ # (passed as stdin to the "stap" tool)
|
||||
+ # The script should be a bytes instance
|
||||
+ # Return (stdout, stderr) pair
|
||||
+
|
||||
+ if pythonfile:
|
||||
+ pythoncmd = '%s %s' % (sys.executable, pythonfile)
|
||||
+ else:
|
||||
+ pythoncmd = '%s -c %r' % (sys.executable, pythoncode)
|
||||
+
|
||||
+ # The process tree of a stap invocation of a command goes through
|
||||
+ # something like this:
|
||||
+ # stap ->fork/exec(staprun; exec stapio ->f/e(-c cmd); exec staprun -r)
|
||||
+ # and this trip through setuid leads to LD_LIBRARY_PATH being dropped,
|
||||
+ # which would lead to an --enable-shared build of python failing to be
|
||||
+ # find its libpython, with an error like:
|
||||
+ # error while loading shared libraries: libpython3.3dm.so.1.0: cannot
|
||||
+ # open shared object file: No such file or directory
|
||||
+ # Hence we need to jump through some hoops to expose LD_LIBRARY_PATH to
|
||||
+ # the invoked python process:
|
||||
+ LD_LIBRARY_PATH = os.environ.get('LD_LIBRARY_PATH', '')
|
||||
+ if LD_LIBRARY_PATH:
|
||||
+ pythoncmd = 'env LD_LIBRARY_PATH=%s ' % LD_LIBRARY_PATH + pythoncmd
|
||||
+
|
||||
+ return invoke_systemtap_script(script, pythoncmd)
|
||||
+
|
||||
+# When using the static markers, we need to supply the prefix of a systemtap
|
||||
+# dotted probe point that containing the marker.
|
||||
+# See http://sourceware.org/systemtap/langref/Probe_points.html
|
||||
+#
|
||||
+# We need to determine if this is a shared-library build
|
||||
+#
|
||||
+# Note that sysconfig can get this wrong; see:
|
||||
+# http://bugs.python.org/issue14774
|
||||
+#
|
||||
+if '--enable-shared' in sysconfig.get_config_var('CONFIG_ARGS'):
|
||||
+ # For a shared-library build, the markers are in library(INSTSONAME):
|
||||
+ INSTSONAME = sysconfig.get_config_var('INSTSONAME')
|
||||
+ probe_prefix = 'process("%s").library("%s")' % (sys.executable, INSTSONAME)
|
||||
+else:
|
||||
+ # For a non-shared-library build, we can simply use sys.executable:
|
||||
+ probe_prefix = 'process("%s")' % sys.executable
|
||||
+
|
||||
+# The following script ought to generate lots of lines showing recursive
|
||||
+# function entry and return, of the form:
|
||||
+# 11408 python(8274): => __contains__ in Lib/_abcoll.py:362
|
||||
+# 11414 python(8274): => __getitem__ in Lib/os.py:425
|
||||
+# 11418 python(8274): => encode in Lib/os.py:490
|
||||
+# 11424 python(8274): <= encode in Lib/os.py:493
|
||||
+# 11428 python(8274): <= __getitem__ in Lib/os.py:426
|
||||
+# 11433 python(8274): <= __contains__ in Lib/_abcoll.py:366
|
||||
+# where the column are:
|
||||
+# - time in microseconds since start of script
|
||||
+# - name of executable
|
||||
+# - PID of process
|
||||
+# and the remainder indicates the call/return hierarchy
|
||||
+
|
||||
+hierarchy_script = ('''
|
||||
+probe %s.mark("function__entry") {
|
||||
+ filename = user_string($arg1);
|
||||
+ funcname = user_string($arg2);
|
||||
+ lineno = $arg3;
|
||||
+
|
||||
+ printf("%%s => %%s in %%s:%%d\\n", thread_indent(1), funcname, filename, lineno);
|
||||
+}
|
||||
+
|
||||
+probe %s.mark("function__return") {
|
||||
+ filename = user_string($arg1);
|
||||
+ funcname = user_string($arg2);
|
||||
+ lineno = $arg3;
|
||||
+
|
||||
+ printf("%%s <= %%s in %%s:%%d\\n", thread_indent(-1), funcname, filename, lineno);
|
||||
+}
|
||||
+''' % (probe_prefix, probe_prefix)).encode('utf-8')
|
||||
+
|
||||
+
|
||||
+class ErrorDumper:
|
||||
+ # A context manager that dumps extra information if an exception is raised,
|
||||
+ # to help track down why the problem occurred
|
||||
+ def __init__(self, out, err):
|
||||
+ self.out = out
|
||||
+ self.err = err
|
||||
+
|
||||
+ def __enter__(self):
|
||||
+ pass
|
||||
+
|
||||
+ def __exit__(self, type_, value, traceback):
|
||||
+ if type_:
|
||||
+ # an exception is being raised:
|
||||
+ print('stdout: %s' % out.decode())
|
||||
+ print('stderr: %s' % err.decode())
|
||||
+
|
||||
+class SystemtapTests(unittest.TestCase):
|
||||
+
|
||||
+ def test_invoking_python(self):
|
||||
+ # Ensure that we can invoke python under stap, with a trivial stap
|
||||
+ # script:
|
||||
+ out, err = invoke_python_under_systemtap(
|
||||
+ b'probe begin { println("hello from stap") exit () }',
|
||||
+ pythoncode="print('hello from python')")
|
||||
+ with ErrorDumper(out, err):
|
||||
+ self.assertIn(b'hello from stap', out)
|
||||
+ self.assertIn(b'hello from python', out)
|
||||
+
|
||||
+ def test_function_entry(self):
|
||||
+ # Ensure that the function_entry static marker works
|
||||
+ out, err = invoke_python_under_systemtap(hierarchy_script)
|
||||
+ # stdout ought to contain various lines showing recursive function
|
||||
+ # entry and return (see above)
|
||||
+
|
||||
+ # Uncomment this for debugging purposes:
|
||||
+ # print(out.decode('utf-8'))
|
||||
+
|
||||
+ # Executing the cmdline-supplied "pass":
|
||||
+ # 0 python(8274): => <module> in <string>:1
|
||||
+ # 5 python(8274): <= <module> in <string>:1
|
||||
+ with ErrorDumper(out, err):
|
||||
+ self.assertIn(b'=> <module> in <string>:1', out,
|
||||
+ msg="stdout: %s\nstderr: %s\n" % (out, err))
|
||||
+
|
||||
+ def test_function_encoding(self):
|
||||
+ # Ensure that function names containing non-Latin 1 code
|
||||
+ # points are handled:
|
||||
+ pythonfile = TESTFN
|
||||
+ try:
|
||||
+ unlink(pythonfile)
|
||||
+ f = open(pythonfile, "wb")
|
||||
+ f.write("""
|
||||
+# Sample script with non-ASCII filename, for use by test_systemtap.py
|
||||
+# Implicitly UTF-8
|
||||
+
|
||||
+def 文字化け():
|
||||
+ '''Function with non-ASCII identifier; I believe this reads "mojibake"'''
|
||||
+ print("hello world!")
|
||||
+
|
||||
+文字化け()
|
||||
+""".encode('utf-8'))
|
||||
+ f.close()
|
||||
+
|
||||
+ out, err = invoke_python_under_systemtap(hierarchy_script,
|
||||
+ pythonfile=pythonfile)
|
||||
+ out_utf8 = out.decode('utf-8')
|
||||
+ with ErrorDumper(out, err):
|
||||
+ self.assertIn('=> <module> in %s:5' % pythonfile, out_utf8)
|
||||
+ self.assertIn(' => 文字化け in %s:5' % pythonfile, out_utf8)
|
||||
+ self.assertIn(' <= 文字化け in %s:7' % pythonfile, out_utf8)
|
||||
+ self.assertIn('<= <module> in %s:9' % pythonfile, out_utf8)
|
||||
+ finally:
|
||||
+ unlink(pythonfile)
|
||||
+
|
||||
+ @unittest.skipIf(sys.getfilesystemencoding() == 'ascii',
|
||||
+ 'the test filename is not encodable with ASCII')
|
||||
+ def test_filename_encoding(self):
|
||||
+ # Ensure that scripts names containing non-Latin 1 code
|
||||
+ # points are handled:
|
||||
+ pythonfile = TESTFN + '_☠.py'
|
||||
+ try:
|
||||
+ unlink(pythonfile)
|
||||
+ f = open(pythonfile, "wb")
|
||||
+ f.write("""
|
||||
+def foo():
|
||||
+ '''Function with non-ASCII identifier; I believe this reads "mojibake"'''
|
||||
+ print("hello world!")
|
||||
+
|
||||
+foo()
|
||||
+""".encode('utf-8'))
|
||||
+ f.close()
|
||||
+
|
||||
+ out, err = invoke_python_under_systemtap(hierarchy_script,
|
||||
+ pythonfile=pythonfile)
|
||||
+ out_utf8 = out.decode('utf-8')
|
||||
+ with ErrorDumper(out, err):
|
||||
+ self.assertIn('=> <module> in %s:2' % pythonfile, out_utf8)
|
||||
+ self.assertIn(' => foo in %s:2' % pythonfile, out_utf8)
|
||||
+ self.assertIn(' <= foo in %s:4' % pythonfile, out_utf8)
|
||||
+ self.assertIn('<= <module> in %s:6' % pythonfile, out_utf8)
|
||||
+ finally:
|
||||
+ unlink(pythonfile)
|
||||
+
|
||||
+def test_main():
|
||||
+ run_unittest(SystemtapTests)
|
||||
+
|
||||
+if __name__ == "__main__":
|
||||
+ test_main()
|
||||
diff -up Python-3.3.0rc2/Makefile.pre.in.systemtap Python-3.3.0rc2/Makefile.pre.in
|
||||
--- Python-3.3.0rc2/Makefile.pre.in.systemtap 2012-09-09 05:11:05.000000000 -0400
|
||||
+++ Python-3.3.0rc2/Makefile.pre.in 2012-09-10 09:19:51.195501518 -0400
|
||||
@@ -363,6 +363,7 @@ PYTHON_OBJS= \
|
||||
Python/formatter_unicode.o \
|
||||
Python/fileutils.o \
|
||||
Python/$(DYNLOADFILE) \
|
||||
+ @SYSTEMTAPOBJS@ \
|
||||
$(LIBOBJS) \
|
||||
$(MACHDEP_OBJS) \
|
||||
$(THREADOBJ)
|
||||
@@ -713,7 +714,8 @@ Objects/setobject.o: $(srcdir)/Objects/s
|
||||
$(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES)
|
||||
$(OPCODETARGETGEN) $(OPCODETARGETS_H)
|
||||
|
||||
-Python/ceval.o: $(OPCODETARGETS_H) $(srcdir)/Python/ceval_gil.h
|
||||
+Python/ceval.o: $(OPCODETARGETS_H) $(srcdir)/Python/ceval_gil.h \
|
||||
+ $(srcdir)/Python/ceval_systemtap.h @SYSTEMTAPDEPS@
|
||||
|
||||
Python/frozen.o: Python/importlib.h
|
||||
|
||||
@@ -724,6 +726,13 @@ Objects/typeobject.o: $(srcdir)/Objects/
|
||||
Objects/typeslots.inc: $(srcdir)/Include/typeslots.h $(srcdir)/Objects/typeslots.py
|
||||
$(PYTHON) $(srcdir)/Objects/typeslots.py < $(srcdir)/Include/typeslots.h > Objects/typeslots.inc
|
||||
|
||||
+# Only needed with --with-systemtap; not a public header:
|
||||
+$(srcdir)/Python/pysystemtap.h: $(srcdir)/Python/pysystemtap.d
|
||||
+ dtrace -o $@ $(DFLAGS) -C -h -s $(srcdir)/Python/pysystemtap.d
|
||||
+
|
||||
+Python/pysystemtap.o: $(srcdir)/Python/pysystemtap.d Python/ceval.o
|
||||
+ dtrace -o $@ $(DFLAGS) -C -G -s $(srcdir)/Python/pysystemtap.d Python/ceval.o
|
||||
+
|
||||
############################################################################
|
||||
# Header files
|
||||
|
||||
@@ -1345,6 +1354,7 @@ clean: pycremoval
|
||||
-rm -f pybuilddir.txt
|
||||
-rm -f Lib/lib2to3/*Grammar*.pickle
|
||||
-rm -f Modules/_testembed Modules/_freeze_importlib
|
||||
+ -rm -f $(srcdir)/Python/pysystemtap.h
|
||||
|
||||
profile-removal:
|
||||
find . -name '*.gc??' -exec rm -f {} ';'
|
||||
diff -up Python-3.3.0rc2/pyconfig.h.in.systemtap Python-3.3.0rc2/pyconfig.h.in
|
||||
--- Python-3.3.0rc2/pyconfig.h.in.systemtap 2012-09-09 05:11:14.000000000 -0400
|
||||
+++ Python-3.3.0rc2/pyconfig.h.in 2012-09-10 09:17:21.120511781 -0400
|
||||
@@ -1306,6 +1306,9 @@
|
||||
/* Define if you want to compile in Python-specific mallocs */
|
||||
#undef WITH_PYMALLOC
|
||||
|
||||
+/* Define if you want to compile in SystemTap support */
|
||||
+#undef WITH_SYSTEMTAP
|
||||
+
|
||||
/* Define if you want to compile in rudimentary thread support */
|
||||
#undef WITH_THREAD
|
||||
|
||||
diff -up Python-3.3.0rc2/Python/ceval.c.systemtap Python-3.3.0rc2/Python/ceval.c
|
||||
--- Python-3.3.0rc2/Python/ceval.c.systemtap 2012-09-09 05:11:12.000000000 -0400
|
||||
+++ Python-3.3.0rc2/Python/ceval.c 2012-09-10 09:17:21.122511781 -0400
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
+#include "ceval_systemtap.h"
|
||||
+
|
||||
#ifndef WITH_TSC
|
||||
|
||||
#define READ_TIMESTAMP(var)
|
||||
@@ -1160,6 +1162,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int
|
||||
}
|
||||
}
|
||||
|
||||
+ if (PYTHON_FUNCTION_ENTRY_ENABLED()) {
|
||||
+ systemtap_function_entry(f);
|
||||
+ }
|
||||
+
|
||||
co = f->f_code;
|
||||
names = co->co_names;
|
||||
consts = co->co_consts;
|
||||
@@ -3077,6 +3083,11 @@ fast_yield:
|
||||
|
||||
/* pop frame */
|
||||
exit_eval_frame:
|
||||
+
|
||||
+ if (PYTHON_FUNCTION_RETURN_ENABLED()) {
|
||||
+ systemtap_function_return(f);
|
||||
+ }
|
||||
+
|
||||
Py_LeaveRecursiveCall();
|
||||
f->f_executing = 0;
|
||||
tstate->frame = f->f_back;
|
||||
diff -up Python-3.3.0rc2/Python/ceval_systemtap.h.systemtap Python-3.3.0rc2/Python/ceval_systemtap.h
|
||||
--- Python-3.3.0rc2/Python/ceval_systemtap.h.systemtap 2012-09-10 09:17:21.122511781 -0400
|
||||
+++ Python-3.3.0rc2/Python/ceval_systemtap.h 2012-09-10 09:17:21.122511781 -0400
|
||||
@@ -0,0 +1,86 @@
|
||||
+/*
|
||||
+ Support for SystemTap static markers
|
||||
+*/
|
||||
+
|
||||
+#ifdef WITH_SYSTEMTAP
|
||||
+
|
||||
+#include "pysystemtap.h"
|
||||
+
|
||||
+/*
|
||||
+ A struct to hold all of the information gathered when one of the traceable
|
||||
+ markers is triggered
|
||||
+*/
|
||||
+struct frame_marker_info
|
||||
+{
|
||||
+ PyObject *filename_obj;
|
||||
+ PyObject *funcname_obj;
|
||||
+ const char *filename;
|
||||
+ const char *funcname;
|
||||
+ int lineno;
|
||||
+};
|
||||
+
|
||||
+static void
|
||||
+get_frame_marker_info(PyFrameObject *f, struct frame_marker_info *fmi)
|
||||
+{
|
||||
+ PyObject *ptype;
|
||||
+ PyObject *pvalue;
|
||||
+ PyObject *ptraceback;
|
||||
+
|
||||
+ PyErr_Fetch(&ptype, &pvalue, &ptraceback);
|
||||
+
|
||||
+ fmi->filename_obj = PyUnicode_EncodeFSDefault(f->f_code->co_filename);
|
||||
+ if (fmi->filename_obj) {
|
||||
+ fmi->filename = PyBytes_AsString(fmi->filename_obj);
|
||||
+ } else {
|
||||
+ fmi->filename = NULL;
|
||||
+ }
|
||||
+
|
||||
+ fmi->funcname_obj = PyUnicode_AsUTF8String(f->f_code->co_name);
|
||||
+ if (fmi->funcname_obj) {
|
||||
+ fmi->funcname = PyBytes_AsString(fmi->funcname_obj);
|
||||
+ } else {
|
||||
+ fmi->funcname = NULL;
|
||||
+ }
|
||||
+
|
||||
+ fmi->lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
|
||||
+
|
||||
+ PyErr_Restore(ptype, pvalue, ptraceback);
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+release_frame_marker_info(struct frame_marker_info *fmi)
|
||||
+{
|
||||
+ Py_XDECREF(fmi->filename_obj);
|
||||
+ Py_XDECREF(fmi->funcname_obj);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+systemtap_function_entry(PyFrameObject *f)
|
||||
+{
|
||||
+ struct frame_marker_info fmi;
|
||||
+ get_frame_marker_info(f, &fmi);
|
||||
+ PYTHON_FUNCTION_ENTRY(fmi.filename, fmi.funcname, fmi.lineno, f);
|
||||
+ release_frame_marker_info(&fmi);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+systemtap_function_return(PyFrameObject *f)
|
||||
+{
|
||||
+ struct frame_marker_info fmi;
|
||||
+ get_frame_marker_info(f, &fmi);
|
||||
+ PYTHON_FUNCTION_RETURN(fmi.filename, fmi.funcname, fmi.lineno, f);
|
||||
+ release_frame_marker_info(&fmi);
|
||||
+}
|
||||
+
|
||||
+#else /* #ifdef WITH_SYSTEMTAP */
|
||||
+
|
||||
+/*
|
||||
+ When configured --without-systemtap, everything compiles away to nothing:
|
||||
+*/
|
||||
+#define PYTHON_FUNCTION_ENTRY_ENABLED() 0
|
||||
+#define PYTHON_FUNCTION_RETURN_ENABLED() 0
|
||||
+#define systemtap_function_entry(f)
|
||||
+#define systemtap_function_return(f)
|
||||
+
|
||||
+#endif
|
||||
diff -up Python-3.3.0rc2/Python/pysystemtap.d.systemtap Python-3.3.0rc2/Python/pysystemtap.d
|
||||
--- Python-3.3.0rc2/Python/pysystemtap.d.systemtap 2012-09-10 09:17:21.122511781 -0400
|
||||
+++ Python-3.3.0rc2/Python/pysystemtap.d 2012-09-10 09:17:21.122511781 -0400
|
||||
@@ -0,0 +1,4 @@
|
||||
+provider python {
|
||||
+ probe function__entry(const char *, const char *, int, PyFrameObject *);
|
||||
+ probe function__return(const char *, const char *, int, PyFrameObject *);
|
||||
+};
|
||||
234
lang/python34/files/00102-lib64.patch
Normal file
234
lang/python34/files/00102-lib64.patch
Normal file
@@ -0,0 +1,234 @@
|
||||
diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py
|
||||
index d768dc5..a051164 100644
|
||||
--- a/Lib/distutils/command/install.py
|
||||
+++ b/Lib/distutils/command/install.py
|
||||
@@ -30,14 +30,14 @@ WINDOWS_SCHEME = {
|
||||
INSTALL_SCHEMES = {
|
||||
'unix_prefix': {
|
||||
'purelib': '$base/lib/python$py_version_short/site-packages',
|
||||
- 'platlib': '$platbase/lib/python$py_version_short/site-packages',
|
||||
+ 'platlib': '$platbase/lib64/python$py_version_short/site-packages',
|
||||
'headers': '$base/include/python$py_version_short$abiflags/$dist_name',
|
||||
'scripts': '$base/bin',
|
||||
'data' : '$base',
|
||||
},
|
||||
'unix_home': {
|
||||
'purelib': '$base/lib/python',
|
||||
- 'platlib': '$base/lib/python',
|
||||
+ 'platlib': '$base/lib64/python',
|
||||
'headers': '$base/include/python/$dist_name',
|
||||
'scripts': '$base/bin',
|
||||
'data' : '$base',
|
||||
diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
|
||||
index a1452fe..795c559 100644
|
||||
--- a/Lib/distutils/sysconfig.py
|
||||
+++ b/Lib/distutils/sysconfig.py
|
||||
@@ -141,8 +141,12 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
|
||||
prefix = plat_specific and EXEC_PREFIX or PREFIX
|
||||
|
||||
if os.name == "posix":
|
||||
+ if plat_specific or standard_lib:
|
||||
+ lib = "lib64"
|
||||
+ else:
|
||||
+ lib = "lib"
|
||||
libpython = os.path.join(prefix,
|
||||
- "lib", "python" + get_python_version())
|
||||
+ lib, "python" + get_python_version())
|
||||
if standard_lib:
|
||||
return libpython
|
||||
else:
|
||||
diff --git a/Lib/site.py b/Lib/site.py
|
||||
index 3c8584b..2e47052 100644
|
||||
--- a/Lib/site.py
|
||||
+++ b/Lib/site.py
|
||||
@@ -304,12 +304,16 @@ def getsitepackages(prefixes=None):
|
||||
seen.add(prefix)
|
||||
|
||||
if os.sep == '/':
|
||||
+ sitepackages.append(os.path.join(prefix, "lib64",
|
||||
+ "python" + sys.version[:3],
|
||||
+ "site-packages"))
|
||||
sitepackages.append(os.path.join(prefix, "lib",
|
||||
"python" + sys.version[:3],
|
||||
"site-packages"))
|
||||
sitepackages.append(os.path.join(prefix, "lib", "site-python"))
|
||||
else:
|
||||
sitepackages.append(prefix)
|
||||
+ sitepackages.append(os.path.join(prefix, "lib64", "site-packages"))
|
||||
sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
|
||||
if sys.platform == "darwin":
|
||||
# for framework builds *only* we add the standard Apple
|
||||
diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py
|
||||
index dbf7767..dba45c7 100644
|
||||
--- a/Lib/sysconfig.py
|
||||
+++ b/Lib/sysconfig.py
|
||||
@@ -20,10 +20,10 @@ __all__ = [
|
||||
|
||||
_INSTALL_SCHEMES = {
|
||||
'posix_prefix': {
|
||||
- 'stdlib': '{installed_base}/lib/python{py_version_short}',
|
||||
- 'platstdlib': '{platbase}/lib/python{py_version_short}',
|
||||
+ 'stdlib': '{installed_base}/lib64/python{py_version_short}',
|
||||
+ 'platstdlib': '{platbase}/lib64/python{py_version_short}',
|
||||
'purelib': '{base}/lib/python{py_version_short}/site-packages',
|
||||
- 'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
|
||||
+ 'platlib': '{platbase}/lib64/python{py_version_short}/site-packages',
|
||||
'include':
|
||||
'{installed_base}/include/python{py_version_short}{abiflags}',
|
||||
'platinclude':
|
||||
@@ -61,10 +61,10 @@ _INSTALL_SCHEMES = {
|
||||
'data': '{userbase}',
|
||||
},
|
||||
'posix_user': {
|
||||
- 'stdlib': '{userbase}/lib/python{py_version_short}',
|
||||
- 'platstdlib': '{userbase}/lib/python{py_version_short}',
|
||||
+ 'stdlib': '{userbase}/lib64/python{py_version_short}',
|
||||
+ 'platstdlib': '{userbase}/lib64/python{py_version_short}',
|
||||
'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
|
||||
- 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
|
||||
+ 'platlib': '{userbase}/lib64/python{py_version_short}/site-packages',
|
||||
'include': '{userbase}/include/python{py_version_short}',
|
||||
'scripts': '{userbase}/bin',
|
||||
'data': '{userbase}',
|
||||
diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py
|
||||
index f71cf73..28b5bb9 100644
|
||||
--- a/Lib/test/test_site.py
|
||||
+++ b/Lib/test/test_site.py
|
||||
@@ -243,12 +243,15 @@ class HelperFunctionsTests(unittest.TestCase):
|
||||
self.assertEqual(dirs[2], wanted)
|
||||
elif os.sep == '/':
|
||||
# OS X non-framwework builds, Linux, FreeBSD, etc
|
||||
- self.assertEqual(len(dirs), 2)
|
||||
- wanted = os.path.join('xoxo', 'lib', 'python' + sys.version[:3],
|
||||
+ self.assertEqual(len(dirs), 3)
|
||||
+ wanted = os.path.join('xoxo', 'lib64', 'python' + sys.version[:3],
|
||||
'site-packages')
|
||||
self.assertEqual(dirs[0], wanted)
|
||||
- wanted = os.path.join('xoxo', 'lib', 'site-python')
|
||||
+ wanted = os.path.join('xoxo', 'lib', 'python' + sys.version[:3],
|
||||
+ 'site-packages')
|
||||
self.assertEqual(dirs[1], wanted)
|
||||
+ wanted = os.path.join('xoxo', 'lib', 'site-python')
|
||||
+ self.assertEqual(dirs[2], wanted)
|
||||
else:
|
||||
# other platforms
|
||||
self.assertEqual(len(dirs), 2)
|
||||
diff --git a/Makefile.pre.in b/Makefile.pre.in
|
||||
index e19fc00..9a2538b 100644
|
||||
--- a/Makefile.pre.in
|
||||
+++ b/Makefile.pre.in
|
||||
@@ -120,7 +120,7 @@ LIBDIR= @libdir@
|
||||
MANDIR= @mandir@
|
||||
INCLUDEDIR= @includedir@
|
||||
CONFINCLUDEDIR= $(exec_prefix)/include
|
||||
-SCRIPTDIR= $(prefix)/lib
|
||||
+SCRIPTDIR= $(prefix)/lib64
|
||||
ABIFLAGS= @ABIFLAGS@
|
||||
|
||||
# Detailed destination directories
|
||||
diff --git a/Modules/getpath.c b/Modules/getpath.c
|
||||
index 13e3817..a31ab0c 100644
|
||||
--- a/Modules/getpath.c
|
||||
+++ b/Modules/getpath.c
|
||||
@@ -118,8 +118,8 @@
|
||||
#endif
|
||||
|
||||
#ifndef PYTHONPATH
|
||||
-#define PYTHONPATH PREFIX "/lib/python" VERSION ":" \
|
||||
- EXEC_PREFIX "/lib/python" VERSION "/lib-dynload"
|
||||
+#define PYTHONPATH PREFIX "/lib64/python" VERSION ":" \
|
||||
+ EXEC_PREFIX "/lib64/python" VERSION "/lib-dynload"
|
||||
#endif
|
||||
|
||||
#ifndef LANDMARK
|
||||
@@ -494,7 +494,7 @@ calculate_path(void)
|
||||
_pythonpath = _Py_char2wchar(PYTHONPATH, NULL);
|
||||
_prefix = _Py_char2wchar(PREFIX, NULL);
|
||||
_exec_prefix = _Py_char2wchar(EXEC_PREFIX, NULL);
|
||||
- lib_python = _Py_char2wchar("lib/python" VERSION, NULL);
|
||||
+ lib_python = _Py_char2wchar("lib64/python" VERSION, NULL);
|
||||
|
||||
if (!_pythonpath || !_prefix || !_exec_prefix || !lib_python) {
|
||||
Py_FatalError(
|
||||
@@ -683,7 +683,7 @@ calculate_path(void)
|
||||
}
|
||||
else
|
||||
wcsncpy(zip_path, _prefix, MAXPATHLEN);
|
||||
- joinpath(zip_path, L"lib/python00.zip");
|
||||
+ joinpath(zip_path, L"lib64/python00.zip");
|
||||
bufsz = wcslen(zip_path); /* Replace "00" with version */
|
||||
zip_path[bufsz - 6] = VERSION[0];
|
||||
zip_path[bufsz - 5] = VERSION[2];
|
||||
@@ -695,7 +695,7 @@ calculate_path(void)
|
||||
fprintf(stderr,
|
||||
"Could not find platform dependent libraries <exec_prefix>\n");
|
||||
wcsncpy(exec_prefix, _exec_prefix, MAXPATHLEN);
|
||||
- joinpath(exec_prefix, L"lib/lib-dynload");
|
||||
+ joinpath(exec_prefix, L"lib64/lib-dynload");
|
||||
}
|
||||
/* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index 7b91f91..9e830ed 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -14030,7 +14030,7 @@ LDVERSION='$(VERSION)$(ABIFLAGS)'
|
||||
$as_echo "$LDVERSION" >&6; }
|
||||
|
||||
|
||||
-LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}"
|
||||
+LIBPL='$(prefix)'"/lib64/python${VERSION}/config-${LDVERSION}"
|
||||
|
||||
|
||||
# Check whether right shifting a negative integer extends the sign bit
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 3394d84..1321c93 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -4115,7 +4115,7 @@ AC_MSG_RESULT($LDVERSION)
|
||||
|
||||
dnl define LIBPL after ABIFLAGS and LDVERSION is defined.
|
||||
AC_SUBST(PY_ENABLE_SHARED)
|
||||
-LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}"
|
||||
+LIBPL='$(prefix)'"/lib64/python${VERSION}/config-${LDVERSION}"
|
||||
AC_SUBST(LIBPL)
|
||||
|
||||
# Check whether right shifting a negative integer extends the sign bit
|
||||
diff --git a/setup.py b/setup.py
|
||||
index 2779658..55e0bb8 100644
|
||||
--- a/setup.py
|
||||
+++ b/setup.py
|
||||
@@ -451,7 +451,7 @@ class PyBuildExt(build_ext):
|
||||
# directories (i.e. '.' and 'Include') must be first. See issue
|
||||
# 10520.
|
||||
if not cross_compiling:
|
||||
- add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
|
||||
+ add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib64')
|
||||
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
|
||||
# only change this for cross builds for 3.3, issues on Mageia
|
||||
if cross_compiling:
|
||||
@@ -730,11 +730,11 @@ class PyBuildExt(build_ext):
|
||||
elif curses_library:
|
||||
readline_libs.append(curses_library)
|
||||
elif self.compiler.find_library_file(lib_dirs +
|
||||
- ['/usr/lib/termcap'],
|
||||
+ ['/usr/lib64/termcap'],
|
||||
'termcap'):
|
||||
readline_libs.append('termcap')
|
||||
exts.append( Extension('readline', ['readline.c'],
|
||||
- library_dirs=['/usr/lib/termcap'],
|
||||
+ library_dirs=['/usr/lib64/termcap'],
|
||||
extra_link_args=readline_extra_link_args,
|
||||
libraries=readline_libs) )
|
||||
else:
|
||||
@@ -771,8 +771,8 @@ class PyBuildExt(build_ext):
|
||||
if krb5_h:
|
||||
ssl_incs += krb5_h
|
||||
ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs,
|
||||
- ['/usr/local/ssl/lib',
|
||||
- '/usr/contrib/ssl/lib/'
|
||||
+ ['/usr/local/ssl/lib64',
|
||||
+ '/usr/contrib/ssl/lib64/'
|
||||
] )
|
||||
|
||||
if (ssl_incs is not None and
|
||||
13
lang/python34/files/00104-lib64-fix-for-test_install.patch
Normal file
13
lang/python34/files/00104-lib64-fix-for-test_install.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
--- Python-2.7.2/Lib/distutils/tests/test_install.py.lib64 2011-09-08 17:51:57.851405376 -0400
|
||||
+++ Python-2.7.2/Lib/distutils/tests/test_install.py 2011-09-08 18:40:46.754205096 -0400
|
||||
@@ -41,8 +41,9 @@ class InstallTestCase(support.TempdirMan
|
||||
self.assertEqual(got, expected)
|
||||
|
||||
libdir = os.path.join(destination, "lib", "python")
|
||||
+ platlibdir = os.path.join(destination, "lib64", "python")
|
||||
check_path(cmd.install_lib, libdir)
|
||||
- check_path(cmd.install_platlib, libdir)
|
||||
+ check_path(cmd.install_platlib, platlibdir)
|
||||
check_path(cmd.install_purelib, libdir)
|
||||
check_path(cmd.install_headers,
|
||||
os.path.join(destination, "include", "python", "foopkg"))
|
||||
59
lang/python34/files/00111-no-static-lib.patch
Normal file
59
lang/python34/files/00111-no-static-lib.patch
Normal file
@@ -0,0 +1,59 @@
|
||||
diff -up cpython-59223da36dec/Makefile.pre.in.no-static-lib cpython-59223da36dec/Makefile.pre.in
|
||||
--- cpython-59223da36dec/Makefile.pre.in.no-static-lib 2012-08-07 16:43:43.296466422 -0400
|
||||
+++ cpython-59223da36dec/Makefile.pre.in 2012-08-07 16:44:13.299464371 -0400
|
||||
@@ -464,7 +464,7 @@ coverage:
|
||||
$(RUNSHARED) $(PYTHON_FOR_BUILD) ./Tools/clinic/clinic.py --make
|
||||
|
||||
# Build the interpreter
|
||||
-$(BUILDPYTHON): Modules/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY)
|
||||
+$(BUILDPYTHON): Modules/python.o $(LDLIBRARY) $(PY3LIBRARY)
|
||||
$(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Modules/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
|
||||
|
||||
platform: $(BUILDPYTHON) pybuilddir.txt
|
||||
@@ -480,18 +480,6 @@ sharedmods: $(BUILDPYTHON) $(SYSCONFIGDA
|
||||
_TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \
|
||||
$(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build
|
||||
|
||||
-# Build static library
|
||||
-# avoid long command lines, same as LIBRARY_OBJS
|
||||
-$(LIBRARY): $(LIBRARY_OBJS)
|
||||
- -rm -f $@
|
||||
- $(AR) $(ARFLAGS) $@ Modules/getbuildinfo.o
|
||||
- $(AR) $(ARFLAGS) $@ $(PARSER_OBJS)
|
||||
- $(AR) $(ARFLAGS) $@ $(OBJECT_OBJS)
|
||||
- $(AR) $(ARFLAGS) $@ $(PYTHON_OBJS) Python/frozen.o
|
||||
- $(AR) $(ARFLAGS) $@ $(MODULE_OBJS) $(SIGNAL_OBJS)
|
||||
- $(AR) $(ARFLAGS) $@ $(MODOBJS)
|
||||
- $(RANLIB) $@
|
||||
-
|
||||
libpython$(LDVERSION).so: $(LIBRARY_OBJS)
|
||||
if test $(INSTSONAME) != $(LDLIBRARY); then \
|
||||
$(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \
|
||||
@@ -581,7 +569,7 @@ Modules/Setup: $(srcdir)/Modules/Setup.d
|
||||
echo "-----------------------------------------------"; \
|
||||
fi
|
||||
|
||||
-Modules/_testembed: Modules/_testembed.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY)
|
||||
+Modules/_testembed: Modules/_testembed.o $(LDLIBRARY) $(PY3LIBRARY)
|
||||
$(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Modules/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
|
||||
|
||||
############################################################################
|
||||
@@ -1155,18 +1143,6 @@ libainstall: all python-config
|
||||
else true; \
|
||||
fi; \
|
||||
done
|
||||
- @if test -d $(LIBRARY); then :; else \
|
||||
- if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \
|
||||
- if test "$(SHLIB_SUFFIX)" = .dll; then \
|
||||
- $(INSTALL_DATA) $(LDLIBRARY) $(DESTDIR)$(LIBPL) ; \
|
||||
- else \
|
||||
- $(INSTALL_DATA) $(LIBRARY) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \
|
||||
- $(RANLIB) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \
|
||||
- fi; \
|
||||
- else \
|
||||
- echo Skip install of $(LIBRARY) - use make frameworkinstall; \
|
||||
- fi; \
|
||||
- fi
|
||||
$(INSTALL_DATA) Modules/config.c $(DESTDIR)$(LIBPL)/config.c
|
||||
$(INSTALL_DATA) Modules/python.o $(DESTDIR)$(LIBPL)/python.o
|
||||
$(INSTALL_DATA) $(srcdir)/Modules/config.c.in $(DESTDIR)$(LIBPL)/config.c.in
|
||||
50
lang/python34/files/00113-more-configuration-flags.patch
Normal file
50
lang/python34/files/00113-more-configuration-flags.patch
Normal file
@@ -0,0 +1,50 @@
|
||||
diff -up Python-3.3.0b1/configure.ac.more-configuration-flags Python-3.3.0b1/configure.ac
|
||||
--- Python-3.3.0b1/configure.ac.more-configuration-flags 2012-07-20 13:25:33.232864839 -0400
|
||||
+++ Python-3.3.0b1/configure.ac 2012-07-20 13:25:33.314863815 -0400
|
||||
@@ -2585,6 +2585,30 @@ else AC_MSG_RESULT(no)
|
||||
fi],
|
||||
[AC_MSG_RESULT(no)])
|
||||
|
||||
+AC_MSG_CHECKING(for --with-count-allocs)
|
||||
+AC_ARG_WITH(count-allocs,
|
||||
+[ --with(out)count-allocs enable/disable per-type instance accounting], [
|
||||
+if test "$withval" != no
|
||||
+then
|
||||
+ AC_DEFINE(COUNT_ALLOCS, 1,
|
||||
+ [Define to keep records of the number of instances of each type])
|
||||
+ AC_MSG_RESULT(yes)
|
||||
+else AC_MSG_RESULT(no)
|
||||
+fi],
|
||||
+[AC_MSG_RESULT(no)])
|
||||
+
|
||||
+AC_MSG_CHECKING(for --with-call-profile)
|
||||
+AC_ARG_WITH(call-profile,
|
||||
+[ --with(out)-call-profile enable/disable statistics on function call invocation], [
|
||||
+if test "$withval" != no
|
||||
+then
|
||||
+ AC_DEFINE(CALL_PROFILE, 1,
|
||||
+ [Define to keep records on function call invocation])
|
||||
+ AC_MSG_RESULT(yes)
|
||||
+else AC_MSG_RESULT(no)
|
||||
+fi],
|
||||
+[AC_MSG_RESULT(no)])
|
||||
+
|
||||
# Check for Python-specific malloc support
|
||||
AC_MSG_CHECKING(for --with-pymalloc)
|
||||
AC_ARG_WITH(pymalloc,
|
||||
diff -up Python-3.3.0b1/pyconfig.h.in.more-configuration-flags Python-3.3.0b1/pyconfig.h.in
|
||||
--- Python-3.3.0b1/pyconfig.h.in.more-configuration-flags 2012-07-20 13:25:33.000000000 -0400
|
||||
+++ Python-3.3.0b1/pyconfig.h.in 2012-07-20 13:26:02.826494869 -0400
|
||||
@@ -12,6 +12,12 @@
|
||||
support for AIX C++ shared extension modules. */
|
||||
#undef AIX_GENUINE_CPLUSPLUS
|
||||
|
||||
+/* Define to keep records on function call invocation */
|
||||
+#undef CALL_PROFILE
|
||||
+
|
||||
+/* Define to keep records of the number of instances of each type */
|
||||
+#undef COUNT_ALLOCS
|
||||
+
|
||||
/* Define if C doubles are 64-bit IEEE 754 binary format, stored in ARM
|
||||
mixed-endian order (byte order 45670123) */
|
||||
#undef DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754
|
||||
20
lang/python34/files/00125-less-verbose-COUNT_ALLOCS.patch
Normal file
20
lang/python34/files/00125-less-verbose-COUNT_ALLOCS.patch
Normal file
@@ -0,0 +1,20 @@
|
||||
diff -up Python-2.7/Python/pythonrun.c.less-verbose-COUNT_ALLOCS Python-2.7/Python/pythonrun.c
|
||||
--- Python-2.7/Python/pythonrun.c.less-verbose-COUNT_ALLOCS 2010-08-17 14:49:33.321913909 -0400
|
||||
+++ Python-2.7/Python/pythonrun.c 2010-08-17 14:54:48.750910403 -0400
|
||||
@@ -470,7 +470,15 @@ Py_Finalize(void)
|
||||
|
||||
/* Debugging stuff */
|
||||
#ifdef COUNT_ALLOCS
|
||||
- dump_counts(stdout);
|
||||
+ /* This is a downstream Fedora modification.
|
||||
+ The upstream default with COUNT_ALLOCS is to always dump the counts to
|
||||
+ stdout on exit. For our debug builds its useful to have the info from
|
||||
+ COUNT_ALLOCS available, but the stdout info here gets in the way, so
|
||||
+ we make it optional, wrapping it in an environment variable (modelled
|
||||
+ on the other PYTHONDUMP* env variables):
|
||||
+ */
|
||||
+ if (Py_GETENV("PYTHONDUMPCOUNTS"))
|
||||
+ dump_counts(stdout);
|
||||
#endif
|
||||
/* dump hash stats */
|
||||
_PyHash_Fini();
|
||||
11
lang/python34/files/00131-disable-tests-in-test_io.patch
Normal file
11
lang/python34/files/00131-disable-tests-in-test_io.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
diff -up Python-2.7.2/Lib/test/test_io.py.disable-tests-in-test_io Python-2.7.2/Lib/test/test_io.py
|
||||
--- Python-2.7.2/Lib/test/test_io.py.disable-tests-in-test_io 2011-09-01 14:18:45.963304089 -0400
|
||||
+++ Python-2.7.2/Lib/test/test_io.py 2011-09-01 15:08:53.796098413 -0400
|
||||
@@ -2669,6 +2669,7 @@ class SignalsTest(unittest.TestCase):
|
||||
self.check_interrupted_read_retry(lambda x: x,
|
||||
mode="r")
|
||||
|
||||
+ @unittest.skip('rhbz#732998')
|
||||
@unittest.skipUnless(threading, 'Threading required for this test.')
|
||||
def check_interrupted_write_retry(self, item, **fdopen_kwargs):
|
||||
"""Check that a buffered write, when it gets interrupted (either
|
||||
@@ -0,0 +1,68 @@
|
||||
diff -up Python-3.2.2/Lib/unittest/case.py.add-rpmbuild-hooks-to-unittest Python-3.2.2/Lib/unittest/case.py
|
||||
--- Python-3.2.2/Lib/unittest/case.py.add-rpmbuild-hooks-to-unittest 2011-09-03 12:16:44.000000000 -0400
|
||||
+++ Python-3.2.2/Lib/unittest/case.py 2011-09-09 06:35:16.365568382 -0400
|
||||
@@ -3,6 +3,7 @@
|
||||
import sys
|
||||
import functools
|
||||
import difflib
|
||||
+import os
|
||||
import logging
|
||||
import pprint
|
||||
import re
|
||||
@@ -101,6 +102,43 @@ def expectedFailure(func):
|
||||
raise self.test_case.failureException(msg)
|
||||
|
||||
|
||||
+# Non-standard/downstream-only hooks for handling issues with specific test
|
||||
+# cases:
|
||||
+
|
||||
+def _skipInRpmBuild(reason):
|
||||
+ """
|
||||
+ Non-standard/downstream-only decorator for marking a specific unit test
|
||||
+ to be skipped when run within the %check of an rpmbuild.
|
||||
+
|
||||
+ Specifically, this takes effect when WITHIN_PYTHON_RPM_BUILD is set within
|
||||
+ the environment, and has no effect otherwise.
|
||||
+ """
|
||||
+ if 'WITHIN_PYTHON_RPM_BUILD' in os.environ:
|
||||
+ return skip(reason)
|
||||
+ else:
|
||||
+ return _id
|
||||
+
|
||||
+def _expectedFailureInRpmBuild(func):
|
||||
+ """
|
||||
+ Non-standard/downstream-only decorator for marking a specific unit test
|
||||
+ as expected to fail within the %check of an rpmbuild.
|
||||
+
|
||||
+ Specifically, this takes effect when WITHIN_PYTHON_RPM_BUILD is set within
|
||||
+ the environment, and has no effect otherwise.
|
||||
+ """
|
||||
+ @functools.wraps(func)
|
||||
+ def wrapper(*args, **kwargs):
|
||||
+ if 'WITHIN_PYTHON_RPM_BUILD' in os.environ:
|
||||
+ try:
|
||||
+ func(*args, **kwargs)
|
||||
+ except Exception:
|
||||
+ raise _ExpectedFailure(sys.exc_info())
|
||||
+ raise _UnexpectedSuccess
|
||||
+ else:
|
||||
+ # Call directly:
|
||||
+ func(*args, **kwargs)
|
||||
+ return wrapper
|
||||
+
|
||||
class _AssertRaisesBaseContext(_BaseTestCaseContext):
|
||||
|
||||
def __init__(self, expected, test_case, callable_obj=None,
|
||||
diff -up Python-3.2.2/Lib/unittest/__init__.py.add-rpmbuild-hooks-to-unittest Python-3.2.2/Lib/unittest/__init__.py
|
||||
--- Python-3.2.2/Lib/unittest/__init__.py.add-rpmbuild-hooks-to-unittest 2011-09-03 12:16:44.000000000 -0400
|
||||
+++ Python-3.2.2/Lib/unittest/__init__.py 2011-09-09 06:35:16.366568382 -0400
|
||||
@@ -57,7 +57,8 @@ __unittest = True
|
||||
|
||||
from .result import TestResult
|
||||
from .case import (TestCase, FunctionTestCase, SkipTest, skip, skipIf,
|
||||
- skipUnless, expectedFailure)
|
||||
+ skipUnless, expectedFailure,
|
||||
+ _skipInRpmBuild, _expectedFailureInRpmBuild)
|
||||
from .suite import BaseTestSuite, TestSuite
|
||||
from .loader import (TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,
|
||||
findTestCases)
|
||||
@@ -0,0 +1,21 @@
|
||||
diff -up Python-3.3.0b2/Lib/test/test_sys.py.fix-COUNT_ALLOCS-failure-in-test_sys Python-3.3.0b2/Lib/test/test_sys.py
|
||||
--- Python-3.3.0b2/Lib/test/test_sys.py.fix-COUNT_ALLOCS-failure-in-test_sys 2012-08-11 02:54:16.000000000 -0400
|
||||
+++ Python-3.3.0b2/Lib/test/test_sys.py 2012-08-13 14:50:15.253720597 -0400
|
||||
@@ -835,12 +835,17 @@ class SizeofTest(unittest.TestCase):
|
||||
# type
|
||||
# static type: PyTypeObject
|
||||
s = vsize('P2n15Pl4Pn9Pn11PIP')
|
||||
+ # COUNT_ALLOCS adds a further 3 Py_ssize_t and 2 pointers:
|
||||
+ if hasattr(sys, 'getcounts'):
|
||||
+ s += struct.calcsize('3P2P')
|
||||
check(int, s)
|
||||
# (PyTypeObject + PyNumberMethods + PyMappingMethods +
|
||||
# PySequenceMethods + PyBufferProcs + 4P)
|
||||
s = vsize('P2n15Pl4Pn9Pn11PIP') + struct.calcsize('34P 3P 10P 2P 4P')
|
||||
# Separate block for PyDictKeysObject with 4 entries
|
||||
s += struct.calcsize("2nPn") + 4*struct.calcsize("n2P")
|
||||
+ if hasattr(sys, 'getcounts'):
|
||||
+ s += struct.calcsize('3P2P')
|
||||
# class
|
||||
class newstyleclass(object): pass
|
||||
check(newstyleclass, s)
|
||||
@@ -0,0 +1,17 @@
|
||||
diff -up Python-3.2b2/Lib/test/test_weakref.py.test-weakref-COUNT_ALLOCS_fix Python-3.2b2/Lib/test/test_weakref.py
|
||||
--- Python-3.2b2/Lib/test/test_weakref.py.test-weakref-COUNT_ALLOCS_fix 2010-12-28 20:33:46.963364990 -0500
|
||||
+++ Python-3.2b2/Lib/test/test_weakref.py 2010-12-28 20:35:44.115935248 -0500
|
||||
@@ -583,9 +583,10 @@ class ReferencesTestCase(TestBase):
|
||||
# been cleared without their callbacks executing. OTOH, the weakref
|
||||
# to C is bound to a function local (wr), and wasn't trash, so that
|
||||
# callback should have been invoked when C went away.
|
||||
- self.assertEqual(alist, ["C went away"])
|
||||
- # The remaining weakref should be dead now (its callback ran).
|
||||
- self.assertEqual(wr(), None)
|
||||
+ if not hasattr(sys, 'getcounts'):
|
||||
+ self.assertEqual(alist, ["C went away"])
|
||||
+ # The remaining weakref should be dead now (its callback ran).
|
||||
+ self.assertEqual(wr(), None)
|
||||
|
||||
del alist[:]
|
||||
gc.collect()
|
||||
@@ -0,0 +1,12 @@
|
||||
diff -up Python-3.2.2/Lib/distutils/tests/test_bdist_rpm.py.skip-distutils-tests-that-fail-in-rpmbuild Python-3.2.2/Lib/distutils/tests/test_bdist_rpm.py
|
||||
--- Python-3.2.2/Lib/distutils/tests/test_bdist_rpm.py.skip-distutils-tests-that-fail-in-rpmbuild 2011-09-03 12:16:40.000000000 -0400
|
||||
+++ Python-3.2.2/Lib/distutils/tests/test_bdist_rpm.py 2011-09-10 05:04:56.328852558 -0400
|
||||
@@ -23,6 +23,7 @@ setup(name='foo', version='0.1', py_modu
|
||||
|
||||
"""
|
||||
|
||||
+@unittest._skipInRpmBuild("don't try to nest one rpm build inside another rpm build")
|
||||
class BuildRpmTestCase(support.TempdirManager,
|
||||
support.EnvironGuard,
|
||||
support.LoggingSilencer,
|
||||
diff -up Python-3.2.2/Lib/distutils/tests/test_build_ext.py.skip-distutils-tests-that-fail-in-rpmbuild Python-3.2.2/Lib/distutils/tests/test_build_ext.py
|
||||
@@ -0,0 +1,11 @@
|
||||
diff -up Python-2.7.2/Lib/test/test_float.py.skip-test_float-known-failure-on-arm Python-2.7.2/Lib/test/test_float.py
|
||||
--- Python-2.7.2/Lib/test/test_float.py.skip-test_float-known-failure-on-arm 2011-09-08 19:34:09.000986128 -0400
|
||||
+++ Python-2.7.2/Lib/test/test_float.py 2011-09-08 19:34:57.969982779 -0400
|
||||
@@ -1072,6 +1072,7 @@ class HexFloatTestCase(unittest.TestCase
|
||||
self.identical(got, expected)
|
||||
|
||||
|
||||
+ @unittest.skip('Known failure on ARM: http://bugs.python.org/issue8265')
|
||||
def test_from_hex(self):
|
||||
MIN = self.MIN;
|
||||
MAX = self.MAX;
|
||||
113
lang/python34/files/00141-fix-tests_with_COUNT_ALLOCS.patch
Normal file
113
lang/python34/files/00141-fix-tests_with_COUNT_ALLOCS.patch
Normal file
@@ -0,0 +1,113 @@
|
||||
diff -r e245b0d7209b Lib/test/test_gc.py
|
||||
--- a/Lib/test/test_gc.py Sun Oct 20 02:01:29 2013 -0700
|
||||
+++ b/Lib/test/test_gc.py Fri Nov 08 13:25:29 2013 +0100
|
||||
@@ -127,10 +127,16 @@
|
||||
del a
|
||||
self.assertNotEqual(gc.collect(), 0)
|
||||
del B, C
|
||||
- self.assertNotEqual(gc.collect(), 0)
|
||||
+ if hasattr(sys, 'getcounts'):
|
||||
+ self.assertEqual(gc.collect(), 0)
|
||||
+ else:
|
||||
+ self.assertNotEqual(gc.collect(), 0)
|
||||
A.a = A()
|
||||
del A
|
||||
- self.assertNotEqual(gc.collect(), 0)
|
||||
+ if hasattr(sys, 'getcounts'):
|
||||
+ self.assertEqual(gc.collect(), 0)
|
||||
+ else:
|
||||
+ self.assertNotEqual(gc.collect(), 0)
|
||||
self.assertEqual(gc.collect(), 0)
|
||||
|
||||
def test_method(self):
|
||||
@@ -618,6 +624,8 @@
|
||||
stderr = run_command(code % "gc.DEBUG_SAVEALL")
|
||||
self.assertNotIn(b"uncollectable objects at shutdown", stderr)
|
||||
|
||||
+ @unittest.skipIf(hasattr(sys, 'getcounts'),
|
||||
+ 'types are immortal if COUNT_ALLOCS is used')
|
||||
def test_gc_main_module_at_shutdown(self):
|
||||
# Create a reference cycle through the __main__ module and check
|
||||
# it gets collected at interpreter shutdown.
|
||||
@@ -632,6 +640,8 @@
|
||||
rc, out, err = assert_python_ok('-c', code)
|
||||
self.assertEqual(out.strip(), b'__del__ called')
|
||||
|
||||
+ @unittest.skipIf(hasattr(sys, 'getcounts'),
|
||||
+ 'types are immortal if COUNT_ALLOCS is used')
|
||||
def test_gc_ordinary_module_at_shutdown(self):
|
||||
# Same as above, but with a non-__main__ module.
|
||||
with temp_dir() as script_dir:
|
||||
diff -r e245b0d7209b Lib/test/test_module.py
|
||||
--- a/Lib/test/test_module.py Sun Oct 20 02:01:29 2013 -0700
|
||||
+++ b/Lib/test/test_module.py Fri Nov 08 13:25:29 2013 +0100
|
||||
@@ -81,6 +81,8 @@
|
||||
gc_collect()
|
||||
self.assertEqual(f().__dict__["bar"], 4)
|
||||
|
||||
+ @unittest.skipIf(hasattr(sys, 'getcounts'),
|
||||
+ 'types are immortal if COUNT_ALLOCS is used')
|
||||
def test_clear_dict_in_ref_cycle(self):
|
||||
destroyed = []
|
||||
m = ModuleType("foo")
|
||||
@@ -96,6 +98,8 @@
|
||||
gc_collect()
|
||||
self.assertEqual(destroyed, [1])
|
||||
|
||||
+ @unittest.skipIf(hasattr(sys, 'getcounts'),
|
||||
+ 'types are immortal if COUNT_ALLOCS is used')
|
||||
def test_weakref(self):
|
||||
m = ModuleType("foo")
|
||||
wr = weakref.ref(m)
|
||||
@@ -190,6 +194,8 @@
|
||||
self.assertEqual(r[-len(ends_with):], ends_with,
|
||||
'{!r} does not end with {!r}'.format(r, ends_with))
|
||||
|
||||
+ @unittest.skipIf(hasattr(sys, 'getcounts'),
|
||||
+ 'skipping since COUNT_ALLOCS was used, see issue19527')
|
||||
def test_module_finalization_at_shutdown(self):
|
||||
# Module globals and builtins should still be available during shutdown
|
||||
rc, out, err = assert_python_ok("-c", "from test import final_a")
|
||||
--- a/Lib/test/test_io.py.orig 2014-01-09 14:43:44.000000000 +0100
|
||||
+++ b/Lib/test/test_io.py 2014-01-09 14:50:30.839597351 +0100
|
||||
@@ -2611,6 +2611,8 @@
|
||||
""".format(iomod=iomod, kwargs=kwargs)
|
||||
return assert_python_ok("-c", code)
|
||||
|
||||
+ @unittest.skipIf(hasattr(sys, 'getrefcount'),
|
||||
+ 'types are immortal if COUNT_ALLOCS is used')
|
||||
def test_create_at_shutdown_without_encoding(self):
|
||||
rc, out, err = self._check_create_at_shutdown()
|
||||
if err:
|
||||
@@ -2621,6 +2623,8 @@
|
||||
else:
|
||||
self.assertEqual("ok", out.decode().strip())
|
||||
|
||||
+ @unittest.skipIf(hasattr(sys, 'getrefcount'),
|
||||
+ 'types are immortal if COUNT_ALLOCS is used')
|
||||
def test_create_at_shutdown_with_encoding(self):
|
||||
rc, out, err = self._check_create_at_shutdown(encoding='utf-8',
|
||||
errors='strict')
|
||||
--- a/Lib/test/test_logging.py.orig 2014-01-09 14:53:07.016388198 +0100
|
||||
+++ b/Lib/test/test_logging.py 2014-01-09 14:54:25.654282973 +0100
|
||||
@@ -3398,6 +3398,8 @@
|
||||
logging.setLoggerClass(logging.Logger)
|
||||
self.assertEqual(logging.getLoggerClass(), logging.Logger)
|
||||
|
||||
+ @unittest.skipIf(hasattr(sys, 'getcounts'),
|
||||
+ 'types are immortal if COUNT_ALLOCS is used')
|
||||
def test_logging_at_shutdown(self):
|
||||
# Issue #20037
|
||||
code = """if 1:
|
||||
|
||||
--- a/Lib/test/test_warnings.py.orig 2014-01-09 15:10:12.454997100 +0100
|
||||
+++ b/Lib/test/test_warnings.py 2014-01-09 15:11:14.028913478 +0100
|
||||
@@ -780,6 +780,8 @@
|
||||
assert_python_ok('-c', 'pass', '-W', 'always', PYTHONPATH=cwd)
|
||||
|
||||
class FinalizationTest(unittest.TestCase):
|
||||
+ @unittest.skipIf(hasattr(sys, 'getcounts'),
|
||||
+ 'types are immortal if COUNT_ALLOCS is used')
|
||||
def test_finalization(self):
|
||||
# Issue #19421: warnings.warn() should not crash
|
||||
# during Python finalization
|
||||
58
lang/python34/files/00143-tsc-on-ppc.patch
Normal file
58
lang/python34/files/00143-tsc-on-ppc.patch
Normal file
@@ -0,0 +1,58 @@
|
||||
diff -up Python-2.7.2/Python/ceval.c.tsc-on-ppc Python-2.7.2/Python/ceval.c
|
||||
--- Python-2.7.2/Python/ceval.c.tsc-on-ppc 2011-08-23 14:59:48.051300849 -0400
|
||||
+++ Python-2.7.2/Python/ceval.c 2011-08-23 15:33:25.412162902 -0400
|
||||
@@ -37,24 +37,42 @@ typedef unsigned long long uint64;
|
||||
*/
|
||||
#if defined(__ppc__) || defined (__powerpc__)
|
||||
|
||||
-#define READ_TIMESTAMP(var) ppc_getcounter(&var)
|
||||
+#if defined( __powerpc64__) || defined(__LP64__)
|
||||
+/* 64-bit PowerPC */
|
||||
+#define READ_TIMESTAMP(var) ppc64_getcounter(&var)
|
||||
+static void
|
||||
+ppc64_getcounter(uint64 *v)
|
||||
+{
|
||||
+ /* On 64-bit PowerPC we can read the 64-bit timebase directly into a
|
||||
+ 64-bit register */
|
||||
+ uint64 timebase;
|
||||
+#ifdef _ARCH_PWR4
|
||||
+ asm volatile ("mfspr %0,268" : "=r" (timebase));
|
||||
+#else
|
||||
+ asm volatile ("mftb %0" : "=r" (timebase));
|
||||
+#endif
|
||||
+ *v = timebase;
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+/* 32-bit PowerPC */
|
||||
+#define READ_TIMESTAMP(var) ppc32_getcounter(&var)
|
||||
|
||||
static void
|
||||
-ppc_getcounter(uint64 *v)
|
||||
+ppc32_getcounter(uint64 *v)
|
||||
{
|
||||
- unsigned long tbu, tb, tbu2;
|
||||
+ union { long long ll; long ii[2]; } u;
|
||||
+ long tmp;
|
||||
|
||||
loop:
|
||||
- asm volatile ("mftbu %0" : "=r" (tbu) );
|
||||
- asm volatile ("mftb %0" : "=r" (tb) );
|
||||
- asm volatile ("mftbu %0" : "=r" (tbu2));
|
||||
- if (__builtin_expect(tbu != tbu2, 0)) goto loop;
|
||||
-
|
||||
- /* The slightly peculiar way of writing the next lines is
|
||||
- compiled better by GCC than any other way I tried. */
|
||||
- ((long*)(v))[0] = tbu;
|
||||
- ((long*)(v))[1] = tb;
|
||||
+ asm volatile ("mftbu %0" : "=r" (u.ii[0]) );
|
||||
+ asm volatile ("mftb %0" : "=r" (u.ii[1]) );
|
||||
+ asm volatile ("mftbu %0" : "=r" (tmp));
|
||||
+ if (__builtin_expect(u.ii[0] != tmp, 0)) goto loop;
|
||||
+
|
||||
+ *v = u.ll;
|
||||
}
|
||||
+#endif /* powerpc 32/64 bit */
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
diff -up Python-3.2.2/Lib/test/test_cmath.py.ppc Python-3.2.2/Lib/test/test_cmath.py
|
||||
--- Python-3.2.2/Lib/test/test_cmath.py.ppc 2011-12-07 23:43:55.000000000 +0100
|
||||
+++ Python-3.2.2/Lib/test/test_cmath.py 2011-12-07 23:49:44.000000000 +0100
|
||||
@@ -95,6 +95,7 @@ class CMathTests(unittest.TestCase):
|
||||
self.assertFloatIdentical(x.real, y.real)
|
||||
self.assertFloatIdentical(x.imag, y.imag)
|
||||
|
||||
+ @unittest.skip('Known failure on PPC: glibc bug https://bugzilla.redhat.com/show_bug.cgi?id=750811')
|
||||
def rAssertAlmostEqual(self, a, b, rel_err = 2e-15, abs_err = 5e-323,
|
||||
msg=None):
|
||||
"""Fail if the two floating-point numbers are not almost equal.
|
||||
15
lang/python34/files/00155-avoid-ctypes-thunks.patch
Normal file
15
lang/python34/files/00155-avoid-ctypes-thunks.patch
Normal file
@@ -0,0 +1,15 @@
|
||||
diff -up Python-3.2.3/Lib/ctypes/__init__.py.rhbz814391 Python-3.2.3/Lib/ctypes/__init__.py
|
||||
--- Python-3.2.3/Lib/ctypes/__init__.py.rhbz814391 2012-04-20 15:12:49.017867692 -0400
|
||||
+++ Python-3.2.3/Lib/ctypes/__init__.py 2012-04-20 15:15:09.501111408 -0400
|
||||
@@ -275,11 +275,6 @@ def _reset_cache():
|
||||
# _SimpleCData.c_char_p_from_param
|
||||
POINTER(c_char).from_param = c_char_p.from_param
|
||||
_pointer_type_cache[None] = c_void_p
|
||||
- # XXX for whatever reasons, creating the first instance of a callback
|
||||
- # function is needed for the unittests on Win64 to succeed. This MAY
|
||||
- # be a compiler bug, since the problem occurs only when _ctypes is
|
||||
- # compiled with the MS SDK compiler. Or an uninitialized variable?
|
||||
- CFUNCTYPE(c_int)(lambda: None)
|
||||
|
||||
def create_unicode_buffer(init, size=None):
|
||||
"""create_unicode_buffer(aString) -> character array
|
||||
62
lang/python34/files/00157-uid-gid-overflows.patch
Normal file
62
lang/python34/files/00157-uid-gid-overflows.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
--- Python-3.4.0b1/Lib/test/test_os.py.orig 2013-11-27 12:07:32.368411798 +0100
|
||||
+++ Python-3.4.0b1/Lib/test/test_os.py 2013-11-27 12:12:11.220265174 +0100
|
||||
@@ -1319,30 +1319,36 @@
|
||||
def test_setuid(self):
|
||||
if os.getuid() != 0:
|
||||
self.assertRaises(OSError, os.setuid, 0)
|
||||
+ self.assertRaises(TypeError, os.setuid, 'not an int')
|
||||
self.assertRaises(OverflowError, os.setuid, 1<<32)
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'setgid'), 'test needs os.setgid()')
|
||||
def test_setgid(self):
|
||||
if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
|
||||
self.assertRaises(OSError, os.setgid, 0)
|
||||
+ self.assertRaises(TypeError, os.setgid, 'not an int')
|
||||
self.assertRaises(OverflowError, os.setgid, 1<<32)
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'seteuid'), 'test needs os.seteuid()')
|
||||
def test_seteuid(self):
|
||||
if os.getuid() != 0:
|
||||
self.assertRaises(OSError, os.seteuid, 0)
|
||||
+ self.assertRaises(TypeError, os.seteuid, 'not an int')
|
||||
self.assertRaises(OverflowError, os.seteuid, 1<<32)
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'setegid'), 'test needs os.setegid()')
|
||||
def test_setegid(self):
|
||||
if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
|
||||
self.assertRaises(OSError, os.setegid, 0)
|
||||
+ self.assertRaises(TypeError, os.setegid, 'not an int')
|
||||
self.assertRaises(OverflowError, os.setegid, 1<<32)
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()')
|
||||
def test_setreuid(self):
|
||||
if os.getuid() != 0:
|
||||
self.assertRaises(OSError, os.setreuid, 0, 0)
|
||||
+ self.assertRaises(TypeError, os.setreuid, 'not an int', 0)
|
||||
+ self.assertRaises(TypeError, os.setreuid, 0, 'not an int')
|
||||
self.assertRaises(OverflowError, os.setreuid, 1<<32, 0)
|
||||
self.assertRaises(OverflowError, os.setreuid, 0, 1<<32)
|
||||
|
||||
@@ -1358,6 +1364,8 @@
|
||||
def test_setregid(self):
|
||||
if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
|
||||
self.assertRaises(OSError, os.setregid, 0, 0)
|
||||
+ self.assertRaises(TypeError, os.setregid, 'not an int', 0)
|
||||
+ self.assertRaises(TypeError, os.setregid, 0, 'not an int')
|
||||
self.assertRaises(OverflowError, os.setregid, 1<<32, 0)
|
||||
self.assertRaises(OverflowError, os.setregid, 0, 1<<32)
|
||||
|
||||
--- Python-3.4.0b1/Lib/test/test_pwd.py.orig 2013-11-24 21:36:55.000000000 +0100
|
||||
+++ Python-3.4.0b1/Lib/test/test_pwd.py 2013-11-27 12:07:32.369411798 +0100
|
||||
@@ -89,9 +89,9 @@
|
||||
# In some cases, byuids isn't a complete list of all users in the
|
||||
# system, so if we try to pick a value not in byuids (via a perturbing
|
||||
# loop, say), pwd.getpwuid() might still be able to find data for that
|
||||
- # uid. Using sys.maxint may provoke the same problems, but hopefully
|
||||
+ # uid. Using 2**32 - 2 may provoke the same problems, but hopefully
|
||||
# it will be a more repeatable failure.
|
||||
- fakeuid = sys.maxsize
|
||||
+ fakeuid = 2**32 - 2
|
||||
self.assertNotIn(fakeuid, byuids)
|
||||
self.assertRaises(KeyError, pwd.getpwuid, fakeuid)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
diff -up cpython-59223da36dec/Lib/test/test_posix.py.disable-test_fs_holes-in-rpm-build cpython-59223da36dec/Lib/test/test_posix.py
|
||||
--- cpython-59223da36dec/Lib/test/test_posix.py.disable-test_fs_holes-in-rpm-build 2012-08-07 17:15:59.000000000 -0400
|
||||
+++ cpython-59223da36dec/Lib/test/test_posix.py 2012-08-07 17:16:53.528330330 -0400
|
||||
@@ -973,6 +973,7 @@ class PosixTester(unittest.TestCase):
|
||||
posix.RTLD_GLOBAL
|
||||
posix.RTLD_LOCAL
|
||||
|
||||
+ @unittest._skipInRpmBuild('running kernel may not match kernel in chroot')
|
||||
@unittest.skipUnless(hasattr(os, 'SEEK_HOLE'),
|
||||
"test needs an OS that reports file holes")
|
||||
def test_fs_holes(self):
|
||||
@@ -0,0 +1,11 @@
|
||||
diff -up Python-3.3.0b1/Lib/test/test_socket.py.disable-test_socket-in-rpm-builds Python-3.3.0b1/Lib/test/test_socket.py
|
||||
--- Python-3.3.0b1/Lib/test/test_socket.py.disable-test_socket-in-rpm-builds 2012-07-24 15:02:30.823355067 -0400
|
||||
+++ Python-3.3.0b1/Lib/test/test_socket.py 2012-07-24 15:08:13.021354999 -0400
|
||||
@@ -2188,6 +2188,7 @@ class RecvmsgGenericStreamTests(RecvmsgG
|
||||
# Tests which require a stream socket and can use either recvmsg()
|
||||
# or recvmsg_into().
|
||||
|
||||
+ @unittest._skipInRpmBuild('fails intermittently when run within Koji')
|
||||
def testRecvmsgEOF(self):
|
||||
# Receive end-of-stream indicator (b"", peer socket closed).
|
||||
msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, 1024)
|
||||
@@ -0,0 +1,52 @@
|
||||
diff -up Python-3.4.2/Lib/test/test_exceptions.py.ppc Python-3.4.2/Lib/test/test_exceptions.py
|
||||
--- Python-3.4.2/Lib/test/test_exceptions.py.ppc 2014-10-08 04:18:13.000000000 -0400
|
||||
+++ Python-3.4.2/Lib/test/test_exceptions.py 2015-01-12 05:56:15.922833055 -0500
|
||||
@@ -429,6 +429,7 @@ class ExceptionTests(unittest.TestCase):
|
||||
self.assertIsNone(e.__context__)
|
||||
self.assertIsNone(e.__cause__)
|
||||
|
||||
+ @unittest.skip('rhbz#846849')
|
||||
def testChainingDescriptors(self):
|
||||
try:
|
||||
raise Exception()
|
||||
diff -up Python-3.4.2/Lib/test/test_io.py.ppc Python-3.4.2/Lib/test/test_io.py
|
||||
--- Python-3.4.2/Lib/test/test_io.py.ppc 2015-01-12 05:56:15.922833055 -0500
|
||||
+++ Python-3.4.2/Lib/test/test_io.py 2015-01-12 05:58:23.482833055 -0500
|
||||
@@ -3296,12 +3296,15 @@ class SignalsTest(unittest.TestCase):
|
||||
if e.errno != errno.EBADF:
|
||||
raise
|
||||
|
||||
+ @unittest.skip('rhbz#846849')
|
||||
def test_interrupted_write_unbuffered(self):
|
||||
self.check_interrupted_write(b"xy", b"xy", mode="wb", buffering=0)
|
||||
|
||||
+ @unittest.skip('rhbz#846849')
|
||||
def test_interrupted_write_buffered(self):
|
||||
self.check_interrupted_write(b"xy", b"xy", mode="wb")
|
||||
|
||||
+ @unittest.skip('rhbz#846849')
|
||||
# Issue #22331: The test hangs on FreeBSD 7.2
|
||||
@support.requires_freebsd_version(8)
|
||||
def test_interrupted_write_text(self):
|
||||
diff -up Python-3.4.2/Lib/test/test_raise.py.ppc Python-3.4.2/Lib/test/test_raise.py
|
||||
--- Python-3.4.2/Lib/test/test_raise.py.ppc 2014-10-08 04:18:14.000000000 -0400
|
||||
+++ Python-3.4.2/Lib/test/test_raise.py 2015-01-12 05:56:15.922833055 -0500
|
||||
@@ -151,6 +151,7 @@ class TestRaise(unittest.TestCase):
|
||||
|
||||
class TestCause(unittest.TestCase):
|
||||
|
||||
+ @unittest.skip('rhbz#846849')
|
||||
def testCauseSyntax(self):
|
||||
try:
|
||||
try:
|
||||
diff -up Python-3.4.2/Lib/test/test_traceback.py.ppc Python-3.4.2/Lib/test/test_traceback.py
|
||||
--- Python-3.4.2/Lib/test/test_traceback.py.ppc 2014-10-08 04:18:14.000000000 -0400
|
||||
+++ Python-3.4.2/Lib/test/test_traceback.py 2015-01-12 05:56:15.922833055 -0500
|
||||
@@ -314,6 +314,7 @@ class BaseExceptionReportingTests:
|
||||
self.check_zero_div(blocks[0])
|
||||
self.assertIn('inner_raise() # Marker', blocks[2])
|
||||
|
||||
+ @unittest.skip('rhbz#846849')
|
||||
def test_context_suppression(self):
|
||||
try:
|
||||
try:
|
||||
325
lang/python34/files/00170-gc-assertions.patch
Normal file
325
lang/python34/files/00170-gc-assertions.patch
Normal file
@@ -0,0 +1,325 @@
|
||||
Index: Include/object.h
|
||||
===================================================================
|
||||
--- Include/object.h (revision 87911)
|
||||
+++ Include/object.h (working copy)
|
||||
@@ -914,6 +914,49 @@
|
||||
_PyObject_DebugTypeStats(FILE *out);
|
||||
#endif /* ifndef Py_LIMITED_API */
|
||||
|
||||
+/*
|
||||
+ Define a pair of assertion macros.
|
||||
+
|
||||
+ These work like the regular C assert(), in that they will abort the
|
||||
+ process with a message on stderr if the given condition fails to hold,
|
||||
+ but compile away to nothing if NDEBUG is defined.
|
||||
+
|
||||
+ However, before aborting, Python will also try to call _PyObject_Dump() on
|
||||
+ the given object. This may be of use when investigating bugs in which a
|
||||
+ particular object is corrupt (e.g. buggy a tp_visit method in an extension
|
||||
+ module breaking the garbage collector), to help locate the broken objects.
|
||||
+
|
||||
+ The WITH_MSG variant allows you to supply an additional message that Python
|
||||
+ will attempt to print to stderr, after the object dump.
|
||||
+*/
|
||||
+#ifdef NDEBUG
|
||||
+/* No debugging: compile away the assertions: */
|
||||
+#define PyObject_ASSERT_WITH_MSG(obj, expr, msg) ((void)0)
|
||||
+#else
|
||||
+/* With debugging: generate checks: */
|
||||
+#define PyObject_ASSERT_WITH_MSG(obj, expr, msg) \
|
||||
+ ((expr) \
|
||||
+ ? (void)(0) \
|
||||
+ : _PyObject_AssertFailed((obj), \
|
||||
+ (msg), \
|
||||
+ (__STRING(expr)), \
|
||||
+ (__FILE__), \
|
||||
+ (__LINE__), \
|
||||
+ (__PRETTY_FUNCTION__)))
|
||||
+#endif
|
||||
+
|
||||
+#define PyObject_ASSERT(obj, expr) \
|
||||
+ PyObject_ASSERT_WITH_MSG(obj, expr, NULL)
|
||||
+
|
||||
+/*
|
||||
+ Declare and define the entrypoint even when NDEBUG is defined, to avoid
|
||||
+ causing compiler/linker errors when building extensions without NDEBUG
|
||||
+ against a Python built with NDEBUG defined
|
||||
+*/
|
||||
+PyAPI_FUNC(void) _PyObject_AssertFailed(PyObject *, const char *,
|
||||
+ const char *, const char *, int,
|
||||
+ const char *);
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Index: Objects/object.c
|
||||
===================================================================
|
||||
--- Objects/object.c (revision 87911)
|
||||
+++ Objects/object.c (working copy)
|
||||
@@ -1899,6 +1899,35 @@
|
||||
}
|
||||
}
|
||||
|
||||
+PyAPI_FUNC(void)
|
||||
+_PyObject_AssertFailed(PyObject *obj, const char *msg, const char *expr,
|
||||
+ const char *file, int line, const char *function)
|
||||
+{
|
||||
+ fprintf(stderr,
|
||||
+ "%s:%d: %s: Assertion \"%s\" failed.\n",
|
||||
+ file, line, function, expr);
|
||||
+ if (msg) {
|
||||
+ fprintf(stderr, "%s\n", msg);
|
||||
+ }
|
||||
+
|
||||
+ fflush(stderr);
|
||||
+
|
||||
+ if (obj) {
|
||||
+ /* This might succeed or fail, but we're about to abort, so at least
|
||||
+ try to provide any extra info we can: */
|
||||
+ _PyObject_Dump(obj);
|
||||
+ }
|
||||
+ else {
|
||||
+ fprintf(stderr, "NULL object\n");
|
||||
+ }
|
||||
+
|
||||
+ fflush(stdout);
|
||||
+ fflush(stderr);
|
||||
+
|
||||
+ /* Terminate the process: */
|
||||
+ abort();
|
||||
+}
|
||||
+
|
||||
#ifndef Py_TRACE_REFS
|
||||
/* For Py_LIMITED_API, we need an out-of-line version of _Py_Dealloc.
|
||||
Define this here, so we can undefine the macro. */
|
||||
Index: Lib/test/test_gc.py
|
||||
===================================================================
|
||||
--- Lib/test/test_gc.py (revision 87911)
|
||||
+++ Lib/test/test_gc.py (working copy)
|
||||
@@ -1,6 +1,6 @@
|
||||
import unittest
|
||||
from test.support import (verbose, refcount_test, run_unittest,
|
||||
- strip_python_stderr, cpython_only)
|
||||
+ strip_python_stderr, cpython_only, import_module)
|
||||
from test.script_helper import assert_python_ok, make_script, temp_dir
|
||||
|
||||
import sys
|
||||
@@ -512,6 +512,48 @@
|
||||
self.assertEqual(len(gc.garbage), 0)
|
||||
|
||||
|
||||
+ def test_refcount_errors(self):
|
||||
+ self.preclean()
|
||||
+ # Verify the "handling" of objects with broken refcounts
|
||||
+ import_module("ctypes") #skip if not supported
|
||||
+
|
||||
+ import subprocess
|
||||
+ code = '''if 1:
|
||||
+ a = []
|
||||
+ b = [a]
|
||||
+
|
||||
+ # Simulate the refcount of "a" being too low (compared to the
|
||||
+ # references held on it by live data), but keeping it above zero
|
||||
+ # (to avoid deallocating it):
|
||||
+ import ctypes
|
||||
+ ctypes.pythonapi.Py_DecRef(ctypes.py_object(a))
|
||||
+
|
||||
+ # The garbage collector should now have a fatal error when it reaches
|
||||
+ # the broken object:
|
||||
+ import gc
|
||||
+ gc.collect()
|
||||
+ '''
|
||||
+ p = subprocess.Popen([sys.executable, "-c", code],
|
||||
+ stdout=subprocess.PIPE,
|
||||
+ stderr=subprocess.PIPE)
|
||||
+ stdout, stderr = p.communicate()
|
||||
+ p.stdout.close()
|
||||
+ p.stderr.close()
|
||||
+ # Verify that stderr has a useful error message:
|
||||
+ self.assertRegex(stderr,
|
||||
+ b'Modules/gcmodule.c:[0-9]+: visit_decref: Assertion "\(\(gc\)->gc.gc_refs >> \(1\)\) != 0" failed.')
|
||||
+ self.assertRegex(stderr,
|
||||
+ b'refcount was too small')
|
||||
+ self.assertRegex(stderr,
|
||||
+ b'object : \[\]')
|
||||
+ self.assertRegex(stderr,
|
||||
+ b'type : list')
|
||||
+ self.assertRegex(stderr,
|
||||
+ b'refcount: 1')
|
||||
+ self.assertRegex(stderr,
|
||||
+ b'address : 0x[0-9a-f]+')
|
||||
+
|
||||
+
|
||||
class GCTogglingTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
gc.enable()
|
||||
diff -up Modules/gcmodule.c.orig2 Modules/gcmodule.c
|
||||
--- Modules/gcmodule.c.orig2 2014-12-08 10:54:14.251742911 +0100
|
||||
+++ Modules/gcmodule.c 2014-12-08 10:52:45.674771917 +0100
|
||||
@@ -341,7 +341,8 @@ update_refs(PyGC_Head *containers)
|
||||
{
|
||||
PyGC_Head *gc = containers->gc.gc_next;
|
||||
for (; gc != containers; gc = gc->gc.gc_next) {
|
||||
- assert(_PyGCHead_REFS(gc) == GC_REACHABLE);
|
||||
+ PyObject_ASSERT(FROM_GC(gc),
|
||||
+ _PyGCHead_REFS(gc) == GC_REACHABLE);
|
||||
_PyGCHead_SET_REFS(gc, Py_REFCNT(FROM_GC(gc)));
|
||||
/* Python's cyclic gc should never see an incoming refcount
|
||||
* of 0: if something decref'ed to 0, it should have been
|
||||
@@ -361,7 +362,8 @@ update_refs(PyGC_Head *containers)
|
||||
* so serious that maybe this should be a release-build
|
||||
* check instead of an assert?
|
||||
*/
|
||||
- assert(_PyGCHead_REFS(gc) != 0);
|
||||
+ PyObject_ASSERT(FROM_GC(gc),
|
||||
+ _PyGCHead_REFS(gc) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,7 +378,9 @@ visit_decref(PyObject *op, void *data)
|
||||
* generation being collected, which can be recognized
|
||||
* because only they have positive gc_refs.
|
||||
*/
|
||||
- assert(_PyGCHead_REFS(gc) != 0); /* else refcount was too small */
|
||||
+ PyObject_ASSERT_WITH_MSG(FROM_GC(gc),
|
||||
+ _PyGCHead_REFS(gc) != 0,
|
||||
+ "refcount was too small"); /* else refcount was too small */
|
||||
if (_PyGCHead_REFS(gc) > 0)
|
||||
_PyGCHead_DECREF(gc);
|
||||
}
|
||||
@@ -436,9 +440,10 @@ visit_reachable(PyObject *op, PyGC_Head
|
||||
* If gc_refs == GC_UNTRACKED, it must be ignored.
|
||||
*/
|
||||
else {
|
||||
- assert(gc_refs > 0
|
||||
- || gc_refs == GC_REACHABLE
|
||||
- || gc_refs == GC_UNTRACKED);
|
||||
+ PyObject_ASSERT(FROM_GC(gc),
|
||||
+ gc_refs > 0
|
||||
+ || gc_refs == GC_REACHABLE
|
||||
+ || gc_refs == GC_UNTRACKED);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -480,7 +485,7 @@ move_unreachable(PyGC_Head *young, PyGC_
|
||||
*/
|
||||
PyObject *op = FROM_GC(gc);
|
||||
traverseproc traverse = Py_TYPE(op)->tp_traverse;
|
||||
- assert(_PyGCHead_REFS(gc) > 0);
|
||||
+ PyObject_ASSERT(op, _PyGCHead_REFS(gc) > 0);
|
||||
_PyGCHead_SET_REFS(gc, GC_REACHABLE);
|
||||
(void) traverse(op,
|
||||
(visitproc)visit_reachable,
|
||||
@@ -543,7 +548,7 @@ move_legacy_finalizers(PyGC_Head *unreac
|
||||
for (gc = unreachable->gc.gc_next; gc != unreachable; gc = next) {
|
||||
PyObject *op = FROM_GC(gc);
|
||||
|
||||
- assert(IS_TENTATIVELY_UNREACHABLE(op));
|
||||
+ PyObject_ASSERT(op, IS_TENTATIVELY_UNREACHABLE(op));
|
||||
next = gc->gc.gc_next;
|
||||
|
||||
if (has_legacy_finalizer(op)) {
|
||||
@@ -619,7 +624,7 @@ handle_weakrefs(PyGC_Head *unreachable,
|
||||
PyWeakReference **wrlist;
|
||||
|
||||
op = FROM_GC(gc);
|
||||
- assert(IS_TENTATIVELY_UNREACHABLE(op));
|
||||
+ PyObject_ASSERT(op, IS_TENTATIVELY_UNREACHABLE(op));
|
||||
next = gc->gc.gc_next;
|
||||
|
||||
if (! PyType_SUPPORTS_WEAKREFS(Py_TYPE(op)))
|
||||
@@ -640,9 +645,9 @@ handle_weakrefs(PyGC_Head *unreachable,
|
||||
* the callback pointer intact. Obscure: it also
|
||||
* changes *wrlist.
|
||||
*/
|
||||
- assert(wr->wr_object == op);
|
||||
+ PyObject_ASSERT(wr->wr_object, wr->wr_object == op);
|
||||
_PyWeakref_ClearRef(wr);
|
||||
- assert(wr->wr_object == Py_None);
|
||||
+ PyObject_ASSERT(wr->wr_object, wr->wr_object == Py_None);
|
||||
if (wr->wr_callback == NULL)
|
||||
continue; /* no callback */
|
||||
|
||||
@@ -676,7 +681,7 @@ handle_weakrefs(PyGC_Head *unreachable,
|
||||
*/
|
||||
if (IS_TENTATIVELY_UNREACHABLE(wr))
|
||||
continue;
|
||||
- assert(IS_REACHABLE(wr));
|
||||
+ PyObject_ASSERT(op, IS_REACHABLE(wr));
|
||||
|
||||
/* Create a new reference so that wr can't go away
|
||||
* before we can process it again.
|
||||
@@ -685,7 +690,8 @@ handle_weakrefs(PyGC_Head *unreachable,
|
||||
|
||||
/* Move wr to wrcb_to_call, for the next pass. */
|
||||
wrasgc = AS_GC(wr);
|
||||
- assert(wrasgc != next); /* wrasgc is reachable, but
|
||||
+ PyObject_ASSERT(op, wrasgc != next);
|
||||
+ /* wrasgc is reachable, but
|
||||
next isn't, so they can't
|
||||
be the same */
|
||||
gc_list_move(wrasgc, &wrcb_to_call);
|
||||
@@ -701,11 +707,11 @@ handle_weakrefs(PyGC_Head *unreachable,
|
||||
|
||||
gc = wrcb_to_call.gc.gc_next;
|
||||
op = FROM_GC(gc);
|
||||
- assert(IS_REACHABLE(op));
|
||||
- assert(PyWeakref_Check(op));
|
||||
+ PyObject_ASSERT(op, IS_REACHABLE(op));
|
||||
+ PyObject_ASSERT(op, PyWeakref_Check(op));
|
||||
wr = (PyWeakReference *)op;
|
||||
callback = wr->wr_callback;
|
||||
- assert(callback != NULL);
|
||||
+ PyObject_ASSERT(op, callback != NULL);
|
||||
|
||||
/* copy-paste of weakrefobject.c's handle_callback() */
|
||||
temp = PyObject_CallFunctionObjArgs(callback, wr, NULL);
|
||||
@@ -822,12 +828,14 @@ check_garbage(PyGC_Head *collectable)
|
||||
for (gc = collectable->gc.gc_next; gc != collectable;
|
||||
gc = gc->gc.gc_next) {
|
||||
_PyGCHead_SET_REFS(gc, Py_REFCNT(FROM_GC(gc)));
|
||||
- assert(_PyGCHead_REFS(gc) != 0);
|
||||
+ PyObject_ASSERT(FROM_GC(gc),
|
||||
+ _PyGCHead_REFS(gc) != 0);
|
||||
}
|
||||
subtract_refs(collectable);
|
||||
for (gc = collectable->gc.gc_next; gc != collectable;
|
||||
gc = gc->gc.gc_next) {
|
||||
- assert(_PyGCHead_REFS(gc) >= 0);
|
||||
+ PyObject_ASSERT(FROM_GC(gc),
|
||||
+ _PyGCHead_REFS(gc) >= 0);
|
||||
if (_PyGCHead_REFS(gc) != 0)
|
||||
return -1;
|
||||
}
|
||||
diff -up Lib/test/test_gc.py.old Lib/test/test_gc.py
|
||||
--- Lib/test/test_gc.py.old 2014-12-10 11:19:33.503982288 +0100
|
||||
+++ Lib/test/test_gc.py 2014-12-10 11:21:13.220021364 +0100
|
||||
@@ -49,6 +49,8 @@ class GC_Detector(object):
|
||||
# gc collects it.
|
||||
self.wr = weakref.ref(C1055820(666), it_happened)
|
||||
|
||||
+BUILD_WITH_NDEBUG = ('-DNDEBUG' in sysconfig.get_config_vars()['PY_CFLAGS'])
|
||||
+
|
||||
@with_tp_del
|
||||
class Uncollectable(object):
|
||||
"""Create a reference cycle with multiple __del__ methods.
|
||||
@@ -854,6 +856,8 @@ class GCCallbackTests(unittest.TestCase)
|
||||
self.assertEqual(len(gc.garbage), 0)
|
||||
|
||||
|
||||
+ @unittest.skipIf(BUILD_WITH_NDEBUG,
|
||||
+ 'built with -NDEBUG')
|
||||
def test_refcount_errors(self):
|
||||
self.preclean()
|
||||
# Verify the "handling" of objects with broken refcounts
|
||||
diff -up Lib/test/test_gc.py.old Lib/test/test_gc.py
|
||||
--- Lib/test/test_gc.py.old 2014-12-10 12:50:58.252121318 +0100
|
||||
+++ Lib/test/test_gc.py 2014-12-10 12:51:08.594266653 +0100
|
||||
@@ -4,6 +4,7 @@ from test.support import (verbose, refco
|
||||
from test.script_helper import assert_python_ok, make_script, temp_dir
|
||||
|
||||
import sys
|
||||
+import sysconfig
|
||||
import time
|
||||
import gc
|
||||
import weakref
|
||||
@@ -0,0 +1,12 @@
|
||||
--- Python-3.4.0b1/Lib/test/support/__init__.py.orig 2013-11-27 12:14:26.507216624 +0100
|
||||
+++ Python-3.4.0b1/Lib/test/support/__init__.py 2013-11-27 12:17:01.490805587 +0100
|
||||
@@ -593,7 +593,8 @@
|
||||
if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) == 1:
|
||||
raise TestFailed("tests should never set the SO_REUSEADDR " \
|
||||
"socket option on TCP/IP sockets!")
|
||||
- if hasattr(socket, 'SO_REUSEPORT'):
|
||||
+ if hasattr(socket, 'SO_REUSEPORT') \
|
||||
+ and 'WITHIN_PYTHON_RPM_BUILD' not in os.environ: # rhbz#913732
|
||||
try:
|
||||
if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT) == 1:
|
||||
raise TestFailed("tests should never set the SO_REUSEPORT " \
|
||||
@@ -0,0 +1,30 @@
|
||||
diff -r 39b9b05c3085 Lib/distutils/sysconfig.py
|
||||
--- a/Lib/distutils/sysconfig.py Wed Apr 10 00:27:23 2013 +0200
|
||||
+++ b/Lib/distutils/sysconfig.py Wed Apr 10 10:14:18 2013 +0200
|
||||
@@ -362,7 +362,10 @@
|
||||
done[n] = item = ""
|
||||
if found:
|
||||
after = value[m.end():]
|
||||
- value = value[:m.start()] + item + after
|
||||
+ value = value[:m.start()]
|
||||
+ if item.strip() not in value:
|
||||
+ value += item
|
||||
+ value += after
|
||||
if "$" in after:
|
||||
notdone[name] = value
|
||||
else:
|
||||
diff -r 39b9b05c3085 Lib/sysconfig.py
|
||||
--- a/Lib/sysconfig.py Wed Apr 10 00:27:23 2013 +0200
|
||||
+++ b/Lib/sysconfig.py Wed Apr 10 10:14:18 2013 +0200
|
||||
@@ -296,7 +296,10 @@
|
||||
|
||||
if found:
|
||||
after = value[m.end():]
|
||||
- value = value[:m.start()] + item + after
|
||||
+ value = value[:m.start()]
|
||||
+ if item.strip() not in value:
|
||||
+ value += item
|
||||
+ value += after
|
||||
if "$" in after:
|
||||
notdone[name] = value
|
||||
else:
|
||||
@@ -0,0 +1,48 @@
|
||||
--- a/Tools/gdb/libpython.py 2013-04-06 03:41:58.000000000 -0400
|
||||
+++ b/Tools/gdb/libpython.py 2013-04-24 03:51:04.720540343 -0400
|
||||
@@ -274,6 +274,9 @@
|
||||
self.tp_name = tp_name
|
||||
self.address = address
|
||||
|
||||
+ def __len__(self):
|
||||
+ return len(repr(self))
|
||||
+
|
||||
def __repr__(self):
|
||||
# For the NULL pointer, we have no way of knowing a type, so
|
||||
# special-case it as per
|
||||
@@ -881,6 +884,8 @@
|
||||
filename = self.filename()
|
||||
try:
|
||||
f = open(os_fsencode(filename), 'r')
|
||||
+ except TypeError: # filename is FakeRepr
|
||||
+ return None
|
||||
except IOError:
|
||||
return None
|
||||
with f:
|
||||
@@ -1523,9 +1528,12 @@
|
||||
|
||||
def print_summary(self):
|
||||
if self.is_evalframeex():
|
||||
- pyop = self.get_pyop()
|
||||
- if pyop:
|
||||
+ try:
|
||||
+ pyop = self.get_pyop()
|
||||
line = pyop.get_truncated_repr(MAX_OUTPUT_LEN)
|
||||
+ except:
|
||||
+ pyop = None
|
||||
+ if pyop:
|
||||
write_unicode(sys.stdout, '#%i %s\n' % (self.get_index(), line))
|
||||
if not pyop.is_optimized_out():
|
||||
line = pyop.current_line()
|
||||
@@ -1542,7 +1550,10 @@
|
||||
|
||||
def print_traceback(self):
|
||||
if self.is_evalframeex():
|
||||
- pyop = self.get_pyop()
|
||||
+ try:
|
||||
+ pyop = self.get_pyop()
|
||||
+ except:
|
||||
+ pyop = None
|
||||
if pyop:
|
||||
pyop.print_traceback()
|
||||
if not pyop.is_optimized_out():
|
||||
@@ -0,0 +1,12 @@
|
||||
diff -r de35eae9048a config.sub
|
||||
--- a/config.sub Wed Apr 24 23:33:20 2013 +0200
|
||||
+++ b/config.sub Thu Apr 25 08:51:00 2013 +0200
|
||||
@@ -1008,7 +1008,7 @@
|
||||
;;
|
||||
ppc64) basic_machine=powerpc64-unknown
|
||||
;;
|
||||
- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
+ ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
|
||||
basic_machine=powerpc64le-unknown
|
||||
@@ -0,0 +1,12 @@
|
||||
--- Python-3.3.2/setup.py.orig 2013-07-01 15:23:24.377711044 +0200
|
||||
+++ Python-3.3.2/setup.py 2013-07-01 15:23:34.094676496 +0200
|
||||
@@ -1882,7 +1882,8 @@
|
||||
if not line:
|
||||
ffi_inc = None
|
||||
break
|
||||
- if line.startswith('#define LIBFFI_H'):
|
||||
+ if line.startswith('#define LIBFFI_H') or \
|
||||
+ line.startswith('#define ffi_wrapper_h'):
|
||||
break
|
||||
ffi_lib = None
|
||||
if ffi_inc is not None:
|
||||
14
lang/python34/files/00186-dont-raise-from-py_compile.patch
Normal file
14
lang/python34/files/00186-dont-raise-from-py_compile.patch
Normal file
@@ -0,0 +1,14 @@
|
||||
diff -r 7fa3e824a4ee Lib/test/test_py_compile.py
|
||||
--- a/Lib/test/test_py_compile.py Tue Oct 29 22:25:06 2013 -0400
|
||||
+++ b/Lib/test/test_py_compile.py Wed Oct 30 11:08:31 2013 +0100
|
||||
@@ -54,6 +54,10 @@
|
||||
self.assertTrue(os.path.exists(self.pyc_path))
|
||||
self.assertFalse(os.path.exists(self.cache_path))
|
||||
|
||||
+ def test_bad_coding(self):
|
||||
+ bad_coding = os.path.join(os.path.dirname(__file__), 'bad_coding2.py')
|
||||
+ self.assertIsNone(py_compile.compile(bad_coding, doraise=False))
|
||||
+
|
||||
def test_relative_path(self):
|
||||
py_compile.compile(os.path.relpath(self.source_path),
|
||||
os.path.relpath(self.pyc_path))
|
||||
@@ -0,0 +1,11 @@
|
||||
diff -r 28c04e954bb6 Lib/lib2to3/main.py
|
||||
--- a/Lib/lib2to3/main.py Tue Oct 29 22:25:55 2013 -0400
|
||||
+++ b/Lib/lib2to3/main.py Wed Nov 06 14:33:07 2013 +0100
|
||||
@@ -213,6 +213,7 @@
|
||||
|
||||
# Set up logging handler
|
||||
level = logging.DEBUG if options.verbose else logging.INFO
|
||||
+ logging.root.handlers = []
|
||||
logging.basicConfig(format='%(name)s: %(message)s', level=level)
|
||||
logger = logging.getLogger('lib2to3.main')
|
||||
|
||||
67
lang/python34/files/00189-use-rpm-wheels.patch
Normal file
67
lang/python34/files/00189-use-rpm-wheels.patch
Normal file
@@ -0,0 +1,67 @@
|
||||
diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py
|
||||
index 25c5567..2553524 100644
|
||||
--- a/Lib/ensurepip/__init__.py
|
||||
+++ b/Lib/ensurepip/__init__.py
|
||||
@@ -1,16 +1,27 @@
|
||||
+import distutils.version
|
||||
+import glob
|
||||
import os
|
||||
import os.path
|
||||
-import pkgutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
|
||||
__all__ = ["version", "bootstrap"]
|
||||
|
||||
+_WHEEL_DIR = "/usr/share/python-wheels/"
|
||||
|
||||
-_SETUPTOOLS_VERSION = "28.8.0"
|
||||
|
||||
-_PIP_VERSION = "9.0.1"
|
||||
+def _get_most_recent_wheel_version(pkg):
|
||||
+ prefix = os.path.join(_WHEEL_DIR, "{}-".format(pkg))
|
||||
+ suffix = "-py2.py3-none-any.whl"
|
||||
+ pattern = "{}*{}".format(prefix, suffix)
|
||||
+ versions = (p[len(prefix):-len(suffix)] for p in glob.glob(pattern))
|
||||
+ return str(max(versions, key=distutils.version.LooseVersion))
|
||||
+
|
||||
+
|
||||
+_SETUPTOOLS_VERSION = _get_most_recent_wheel_version("setuptools")
|
||||
+
|
||||
+_PIP_VERSION = _get_most_recent_wheel_version("pip")
|
||||
|
||||
# pip currently requires ssl support, so we try to provide a nicer
|
||||
# error message when that is missing (http://bugs.python.org/issue19744)
|
||||
@@ -37,8 +48,13 @@ def _run_pip(args, additional_paths=None):
|
||||
sys.path = additional_paths + sys.path
|
||||
|
||||
# Install the bundled software
|
||||
- import pip
|
||||
- pip.main(args)
|
||||
+ try:
|
||||
+ # pip 10
|
||||
+ from pip._internal import main
|
||||
+ except ImportError:
|
||||
+ # pip 9
|
||||
+ from pip import main
|
||||
+ main(args)
|
||||
|
||||
|
||||
def version():
|
||||
@@ -93,12 +109,9 @@ def bootstrap(*, root=None, upgrade=False, user=False,
|
||||
additional_paths = []
|
||||
for project, version in _PROJECTS:
|
||||
wheel_name = "{}-{}-py2.py3-none-any.whl".format(project, version)
|
||||
- whl = pkgutil.get_data(
|
||||
- "ensurepip",
|
||||
- "_bundled/{}".format(wheel_name),
|
||||
- )
|
||||
- with open(os.path.join(tmpdir, wheel_name), "wb") as fp:
|
||||
- fp.write(whl)
|
||||
+ with open(os.path.join(_WHEEL_DIR, wheel_name), "rb") as sfp:
|
||||
+ with open(os.path.join(tmpdir, wheel_name), "wb") as fp:
|
||||
+ fp.write(sfp.read())
|
||||
|
||||
additional_paths.append(os.path.join(tmpdir, wheel_name))
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
Subject: python3.test gdb match addr before builtin
|
||||
From: Michel Normand <normand@linux.vnet.ibm.com>
|
||||
|
||||
For ppc64le archi and python3... and gdb... versions
|
||||
the test_gdb.py need a change of re.match to handle address before the builtin_id word.
|
||||
Of course there is no error if this substring is not present.
|
||||
===
|
||||
...
|
||||
#0 0x00003fffb7dd0898 in builtin_id (self=<module at remote 0x3fffb7901440>, v=<unknown at remote 0x3fffb7f68910>) at /builddir/build/BUILD/Python-3.3.2/Python/bltinmodule.c:966
|
||||
....xxxxxxxxxxxxxxxxxxxxxx <= added regexp
|
||||
===
|
||||
|
||||
Signed-off-by: Michel Normand <normand@linux.vnet.ibm.com>
|
||||
---
|
||||
Lib/test/test_gdb.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
Index: Python-3.3.2/Lib/test/test_gdb.py
|
||||
===================================================================
|
||||
--- Python-3.3.2.orig/Lib/test/test_gdb.py
|
||||
+++ Python-3.3.2/Lib/test/test_gdb.py
|
||||
@@ -230,7 +230,7 @@ class DebuggerTests(unittest.TestCase):
|
||||
# gdb can insert additional '\n' and space characters in various places
|
||||
# in its output, depending on the width of the terminal it's connected
|
||||
# to (using its "wrap_here" function)
|
||||
- m = re.match('.*#0\s+builtin_id\s+\(self\=.*,\s+v=\s*(.*?)\)\s+at\s+\S*Python/bltinmodule.c.*',
|
||||
+ m = re.match('.*#0\s+(?: 0x[0-9a-f]+\s+in\s+)?builtin_id\s+\(self\=.*,\s+v=\s*(.*?)\)\s+at\s+\S*Python/bltinmodule.c.*',
|
||||
gdb_output, re.DOTALL)
|
||||
if not m:
|
||||
self.fail('Unexpected gdb output: %r\n%s' % (gdb_output, gdb_output))
|
||||
12
lang/python34/files/00200-gettext-plural-fix.patch
Normal file
12
lang/python34/files/00200-gettext-plural-fix.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff -up Python-2.5.1/Lib/gettext.py.plural Python-2.5.1/Lib/gettext.py
|
||||
--- Python-2.5.1/Lib/gettext.py.plural 2007-09-10 11:38:57.000000000 -0400
|
||||
+++ Python-2.5.1/Lib/gettext.py 2007-09-10 11:39:00.000000000 -0400
|
||||
@@ -299,6 +299,8 @@ class GNUTranslations(NullTranslations):
|
||||
item = b_item.decode().strip()
|
||||
if not item:
|
||||
continue
|
||||
+ if item.startswith("#"):
|
||||
+ continue
|
||||
if ':' in item:
|
||||
k, v = item.split(':', 1)
|
||||
k = k.strip().lower()
|
||||
10
lang/python34/files/00201-fix-memory-leak-in-gdbm.patch
Normal file
10
lang/python34/files/00201-fix-memory-leak-in-gdbm.patch
Normal file
@@ -0,0 +1,10 @@
|
||||
--- Modules/_gdbmmodule.c.orig 2013-07-08 14:54:27.803790151 +0200
|
||||
+++ Modules/_gdbmmodule.c 2013-07-08 14:55:25.006672443 +0200
|
||||
@@ -106,6 +106,7 @@
|
||||
if(okey.dsize) free(okey.dptr);
|
||||
okey=key;
|
||||
}
|
||||
+ if(okey.dsize) free(okey.dptr);
|
||||
dp->di_size = size;
|
||||
}
|
||||
return dp->di_size;
|
||||
11
lang/python34/files/00203-disable-threading-test-koji.patch
Normal file
11
lang/python34/files/00203-disable-threading-test-koji.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
diff -up Python-3.4.3/Lib/test/test_threading.py.mstuchli Python-3.4.3/Lib/test/test_threading.py
|
||||
--- Python-3.4.3/Lib/test/test_threading.py.mstuchli 2015-03-10 10:00:42.917355215 +0100
|
||||
+++ Python-3.4.3/Lib/test/test_threading.py 2015-03-10 10:00:47.735373842 +0100
|
||||
@@ -988,6 +988,7 @@ class ThreadingExceptionTests(BaseTestCa
|
||||
self.assertIn("ZeroDivisionError", err)
|
||||
self.assertNotIn("Unhandled exception", err)
|
||||
|
||||
+ @unittest.skip('Fails in Koji due to mishandled signals')
|
||||
def test_print_exception_stderr_is_none_1(self):
|
||||
script = r"""if True:
|
||||
import sys
|
||||
22
lang/python34/files/00250-getentropy.patch
Normal file
22
lang/python34/files/00250-getentropy.patch
Normal file
@@ -0,0 +1,22 @@
|
||||
diff --git a/Python/random.c b/Python/random.c
|
||||
index af3d0bd..5451815 100644
|
||||
--- a/Python/random.c
|
||||
+++ b/Python/random.c
|
||||
@@ -68,8 +68,15 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
|
||||
}
|
||||
|
||||
/* Issue #25003: Don' use getentropy() on Solaris (available since
|
||||
- * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
|
||||
-#elif defined(HAVE_GETENTROPY) && !defined(sun)
|
||||
+ Solaris 11.3), it is blocking whereas os.urandom() should not block.
|
||||
+
|
||||
+ Issue #29188: Don't use getentropy() on Linux since the glibc 2.24
|
||||
+ implements it with the getrandom() syscall which can fail with ENOSYS,
|
||||
+ and this error is not supported in py_getentropy() and getrandom() is called
|
||||
+ with flags=0 which blocks until system urandom is initialized, which is not
|
||||
+ the desired behaviour to seed the Python hash secret nor for os.urandom():
|
||||
+ see the PEP 524 which was only implemented in Python 3.6. */
|
||||
+#elif defined(HAVE_GETENTROPY) && !defined(sun) && !defined(linux)
|
||||
#define PY_GETENTROPY 1
|
||||
|
||||
/* Fill buffer with size pseudo-random bytes generated by getentropy().
|
||||
13
lang/python34/files/00273-skip-float-test.patch
Normal file
13
lang/python34/files/00273-skip-float-test.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py
|
||||
index 24fe128..d7dd939 100644
|
||||
--- a/Lib/test/test_float.py
|
||||
+++ b/Lib/test/test_float.py
|
||||
@@ -107,7 +107,7 @@ class GeneralFloatCases(unittest.TestCase):
|
||||
else:
|
||||
self.fail("Expected int(%r) to raise a ValueError", s)
|
||||
|
||||
-
|
||||
+ @unittest.skip('Fails in Koji: https://bugzilla.redhat.com/show_bug.cgi?id=1484497')
|
||||
@support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
|
||||
def test_float_with_comma(self):
|
||||
# set locale to something that doesn't use '.' for the decimal point
|
||||
@@ -0,0 +1,50 @@
|
||||
diff -U3 -r Python-3.4.8-orig/configure Python-3.4.8/configure
|
||||
--- Python-3.4.8-orig/configure 2018-02-13 11:08:48.126741021 +0100
|
||||
+++ Python-3.4.8/configure 2018-02-13 11:32:32.579790986 +0100
|
||||
@@ -7006,7 +7006,7 @@
|
||||
|
||||
fi
|
||||
|
||||
-for ac_header in asm/types.h conio.h direct.h dlfcn.h errno.h \
|
||||
+for ac_header in asm/types.h crypt.h conio.h direct.h dlfcn.h errno.h \
|
||||
fcntl.h grp.h \
|
||||
ieeefp.h io.h langinfo.h libintl.h process.h pthread.h \
|
||||
sched.h shadow.h signal.h stdint.h stropts.h termios.h \
|
||||
diff -U3 -r Python-3.4.8-orig/configure.ac Python-3.4.8/configure.ac
|
||||
--- Python-3.4.8-orig/configure.ac 2018-02-13 11:08:48.060740742 +0100
|
||||
+++ Python-3.4.8/configure.ac 2018-02-13 11:09:59.208039082 +0100
|
||||
@@ -1563,7 +1563,7 @@
|
||||
|
||||
# checks for header files
|
||||
AC_HEADER_STDC
|
||||
-AC_CHECK_HEADERS(asm/types.h conio.h direct.h dlfcn.h errno.h \
|
||||
+AC_CHECK_HEADERS(asm/types.h crypt.h conio.h direct.h dlfcn.h errno.h \
|
||||
fcntl.h grp.h \
|
||||
ieeefp.h io.h langinfo.h libintl.h process.h pthread.h \
|
||||
sched.h shadow.h signal.h stdint.h stropts.h termios.h \
|
||||
diff -U3 -r Python-3.4.8-orig/Include/Python.h Python-3.4.8/Include/Python.h
|
||||
--- Python-3.4.8-orig/Include/Python.h 2018-02-05 00:40:38.000000000 +0100
|
||||
+++ Python-3.4.8/Include/Python.h 2018-02-13 11:09:40.689963273 +0100
|
||||
@@ -35,6 +35,9 @@
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
+#ifdef HAVE_CRYPT_H
|
||||
+#include <crypt.h>
|
||||
+#endif
|
||||
|
||||
/* For size_t? */
|
||||
#ifdef HAVE_STDDEF_H
|
||||
diff -U3 -r Python-3.4.8-orig/Modules/_cryptmodule.c Python-3.4.8/Modules/_cryptmodule.c
|
||||
--- Python-3.4.8-orig/Modules/_cryptmodule.c 2018-02-05 00:40:38.000000000 +0100
|
||||
+++ Python-3.4.8/Modules/_cryptmodule.c 2018-02-13 12:00:51.636164978 +0100
|
||||
@@ -69,7 +69,8 @@
|
||||
{
|
||||
/* On some platforms (AtheOS) crypt returns NULL for an invalid
|
||||
salt. Return None in that case. XXX Maybe raise an exception? */
|
||||
- return Py_BuildValue("s", crypt(word, salt));
|
||||
+ char *result = crypt(word, salt);
|
||||
+ return Py_BuildValue("s", result);
|
||||
}
|
||||
|
||||
|
||||
46
lang/python34/files/00315-test_email-mktime.patch
Normal file
46
lang/python34/files/00315-test_email-mktime.patch
Normal file
@@ -0,0 +1,46 @@
|
||||
From 0165caf04ef9c615c8b86dd16f7c201ca7a0befa Mon Sep 17 00:00:00 2001
|
||||
From: Victor Stinner <vstinner@redhat.com>
|
||||
Date: Tue, 27 Nov 2018 12:40:50 +0100
|
||||
Subject: [PATCH] bpo-35317: Fix mktime() error in test_email (GH-10721)
|
||||
|
||||
Fix mktime() overflow error in test_email: run
|
||||
test_localtime_daylight_true_dst_true() and
|
||||
test_localtime_daylight_false_dst_true() with a specific timezone.
|
||||
(cherry picked from commit cfaafda8e3e19764682abb4bd4c574accb784c42)
|
||||
|
||||
Co-authored-by: Victor Stinner <vstinner@redhat.com>
|
||||
---
|
||||
Lib/test/test_email/test_utils.py | 2 ++
|
||||
.../NEWS.d/next/Tests/2018-11-26-16-54-21.bpo-35317.jByGP2.rst | 3 +++
|
||||
2 files changed, 5 insertions(+)
|
||||
create mode 100644 Misc/NEWS.d/next/Tests/2018-11-26-16-54-21.bpo-35317.jByGP2.rst
|
||||
|
||||
diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py
|
||||
index 6dcb3bbe7aab..4e3c3f3a195f 100644
|
||||
--- a/Lib/test/test_email/test_utils.py
|
||||
+++ b/Lib/test/test_email/test_utils.py
|
||||
@@ -75,6 +75,7 @@ def test_localtime_daylight_false_dst_false(self):
|
||||
t2 = utils.localtime(t1)
|
||||
self.assertEqual(t1, t2)
|
||||
|
||||
+ @test.support.run_with_tz('Europe/Minsk')
|
||||
def test_localtime_daylight_true_dst_true(self):
|
||||
test.support.patch(self, time, 'daylight', True)
|
||||
t0 = datetime.datetime(2012, 3, 12, 1, 1)
|
||||
@@ -82,6 +83,7 @@ def test_localtime_daylight_true_dst_true(self):
|
||||
t2 = utils.localtime(t1)
|
||||
self.assertEqual(t1, t2)
|
||||
|
||||
+ @test.support.run_with_tz('Europe/Minsk')
|
||||
def test_localtime_daylight_false_dst_true(self):
|
||||
test.support.patch(self, time, 'daylight', False)
|
||||
t0 = datetime.datetime(2012, 3, 12, 1, 1)
|
||||
diff --git a/Misc/NEWS.d/next/Tests/2018-11-26-16-54-21.bpo-35317.jByGP2.rst b/Misc/NEWS.d/next/Tests/2018-11-26-16-54-21.bpo-35317.jByGP2.rst
|
||||
new file mode 100644
|
||||
index 000000000000..73a30f71927f
|
||||
--- /dev/null
|
||||
+++ b/Misc/NEWS.d/next/Tests/2018-11-26-16-54-21.bpo-35317.jByGP2.rst
|
||||
@@ -0,0 +1,3 @@
|
||||
+Fix ``mktime()`` overflow error in ``test_email``: run
|
||||
+``test_localtime_daylight_true_dst_true()`` and
|
||||
+``test_localtime_daylight_false_dst_true()`` with a specific timezone.
|
||||
42
lang/python34/files/00320-CVE-2019-10160.patch
Normal file
42
lang/python34/files/00320-CVE-2019-10160.patch
Normal file
@@ -0,0 +1,42 @@
|
||||
diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py
|
||||
index 77c2007..c6c54b0 100644
|
||||
--- a/Lib/test/test_urlparse.py
|
||||
+++ b/Lib/test/test_urlparse.py
|
||||
@@ -885,6 +885,12 @@ class UrlParseTestCase(unittest.TestCase):
|
||||
self.assertIn('\u2100', denorm_chars)
|
||||
self.assertIn('\uFF03', denorm_chars)
|
||||
|
||||
+ # bpo-36742: Verify port separators are ignored when they
|
||||
+ # existed prior to decomposition
|
||||
+ urllib.parse.urlsplit('http://\u30d5\u309a:80')
|
||||
+ with self.assertRaises(ValueError):
|
||||
+ urllib.parse.urlsplit('http://\u30d5\u309a\ufe1380')
|
||||
+
|
||||
for scheme in ["http", "https", "ftp"]:
|
||||
for c in denorm_chars:
|
||||
url = "{}://netloc{}false.netloc/path".format(scheme, c)
|
||||
diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py
|
||||
index 243f470..da3a40c 100644
|
||||
--- a/Lib/urllib/parse.py
|
||||
+++ b/Lib/urllib/parse.py
|
||||
@@ -322,13 +322,16 @@ def _checknetloc(netloc):
|
||||
# looking for characters like \u2100 that expand to 'a/c'
|
||||
# IDNA uses NFKC equivalence, so normalize for this check
|
||||
import unicodedata
|
||||
- netloc2 = unicodedata.normalize('NFKC', netloc)
|
||||
- if netloc == netloc2:
|
||||
+ n = netloc.rpartition('@')[2] # ignore anything to the left of '@'
|
||||
+ n = n.replace(':', '') # ignore characters already included
|
||||
+ n = n.replace('#', '') # but not the surrounding text
|
||||
+ n = n.replace('?', '')
|
||||
+ netloc2 = unicodedata.normalize('NFKC', n)
|
||||
+ if n == netloc2:
|
||||
return
|
||||
- _, _, netloc = netloc.rpartition('@') # anything to the left of '@' is okay
|
||||
for c in '/?#@:':
|
||||
if c in netloc2:
|
||||
- raise ValueError("netloc '" + netloc2 + "' contains invalid " +
|
||||
+ raise ValueError("netloc '" + netloc + "' contains invalid " +
|
||||
"characters under NFKC normalization")
|
||||
|
||||
def urlsplit(url, scheme='', allow_fragments=True):
|
||||
816
lang/python34/files/00321-python34-openssl-1.1.1.patch
Normal file
816
lang/python34/files/00321-python34-openssl-1.1.1.patch
Normal file
@@ -0,0 +1,816 @@
|
||||
From 55ffb704cc17d41ddf8f34aac3de5f218cd43dee Mon Sep 17 00:00:00 2001
|
||||
From: Christian Heimes <christian@python.org>
|
||||
Date: Mon, 5 Sep 2016 23:19:05 +0200
|
||||
Subject: [PATCH] bpo-26470: Port ssl and hashlib module to OpenSSL 1.1.0.
|
||||
|
||||
Backport notes
|
||||
|
||||
* Don't add PROTOCOL_TLS
|
||||
* Ignore documentation changes
|
||||
|
||||
(cherry picked from commit 598894ff48e9c1171cb2ec1c798235826a75c7e0)
|
||||
|
||||
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
|
||||
index e36a309..401cc2f 100644
|
||||
--- a/Lib/test/test_ssl.py
|
||||
+++ b/Lib/test/test_ssl.py
|
||||
@@ -23,6 +23,8 @@ ssl = support.import_module("ssl")
|
||||
|
||||
PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
|
||||
HOST = support.HOST
|
||||
+IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
|
||||
+
|
||||
|
||||
def data_file(*name):
|
||||
return os.path.join(os.path.dirname(__file__), *name)
|
||||
@@ -318,9 +320,9 @@ class BasicSocketTests(unittest.TestCase):
|
||||
self.assertGreaterEqual(status, 0)
|
||||
self.assertLessEqual(status, 15)
|
||||
# Version string as returned by {Open,Libre}SSL, the format might change
|
||||
- if "LibreSSL" in s:
|
||||
- self.assertTrue(s.startswith("LibreSSL {:d}.{:d}".format(major, minor)),
|
||||
- (s, t))
|
||||
+ if IS_LIBRESSL:
|
||||
+ self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
|
||||
+ (s, t, hex(n)))
|
||||
else:
|
||||
self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
|
||||
(s, t))
|
||||
@@ -698,15 +700,15 @@ class ContextTests(unittest.TestCase):
|
||||
def test_options(self):
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||
# OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
|
||||
- self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
|
||||
- ctx.options)
|
||||
+ default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
|
||||
+ if not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0):
|
||||
+ default |= ssl.OP_NO_COMPRESSION
|
||||
+ self.assertEqual(default, ctx.options)
|
||||
ctx.options |= ssl.OP_NO_TLSv1
|
||||
- self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1,
|
||||
- ctx.options)
|
||||
+ self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
|
||||
if can_clear_options():
|
||||
- ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
|
||||
- self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
|
||||
- ctx.options)
|
||||
+ ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
|
||||
+ self.assertEqual(default, ctx.options)
|
||||
ctx.options = 0
|
||||
# Ubuntu has OP_NO_SSLv3 forced on by default
|
||||
self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
|
||||
@@ -1042,6 +1044,7 @@ class ContextTests(unittest.TestCase):
|
||||
self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
|
||||
|
||||
@unittest.skipIf(sys.platform == "win32", "not-Windows specific")
|
||||
+ @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
|
||||
def test_load_default_certs_env(self):
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||
with support.EnvironmentVarGuard() as env:
|
||||
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
|
||||
index f494e77..6387c3f 100644
|
||||
--- a/Modules/_hashopenssl.c
|
||||
+++ b/Modules/_hashopenssl.c
|
||||
@@ -38,10 +38,22 @@
|
||||
#define _OPENSSL_SUPPORTS_SHA2
|
||||
#endif
|
||||
|
||||
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
|
||||
+/* OpenSSL < 1.1.0 */
|
||||
+#define EVP_MD_CTX_new EVP_MD_CTX_create
|
||||
+#define EVP_MD_CTX_free EVP_MD_CTX_destroy
|
||||
+#define HAS_FAST_PKCS5_PBKDF2_HMAC 0
|
||||
+#include <openssl/hmac.h>
|
||||
+#else
|
||||
+/* OpenSSL >= 1.1.0 */
|
||||
+#define HAS_FAST_PKCS5_PBKDF2_HMAC 1
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject *name; /* name of this hash algorithm */
|
||||
- EVP_MD_CTX ctx; /* OpenSSL message digest context */
|
||||
+ EVP_MD_CTX *ctx; /* OpenSSL message digest context */
|
||||
#ifdef WITH_THREAD
|
||||
PyThread_type_lock lock; /* OpenSSL context lock */
|
||||
#endif
|
||||
@@ -54,10 +66,10 @@ static PyTypeObject EVPtype;
|
||||
We have one of these per algorithm */
|
||||
typedef struct {
|
||||
PyObject *name_obj;
|
||||
- EVP_MD_CTX ctxs[2];
|
||||
+ EVP_MD_CTX* ctxs[2];
|
||||
/* ctx_ptrs will point to ctxs unless an error occurred, when it will
|
||||
be NULL: */
|
||||
- EVP_MD_CTX *ctx_ptrs[2];
|
||||
+ int initialized[2];
|
||||
PyObject *error_msgs[2];
|
||||
} EVPCachedInfo;
|
||||
|
||||
@@ -74,18 +86,57 @@ DEFINE_CONSTS_FOR_NEW(sha512)
|
||||
#endif
|
||||
|
||||
|
||||
+/* LCOV_EXCL_START */
|
||||
+static PyObject *
|
||||
+_setException(PyObject *exc)
|
||||
+{
|
||||
+ unsigned long errcode;
|
||||
+ const char *lib, *func, *reason;
|
||||
+
|
||||
+ errcode = ERR_peek_last_error();
|
||||
+ if (!errcode) {
|
||||
+ PyErr_SetString(exc, "unknown reasons");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ ERR_clear_error();
|
||||
+
|
||||
+ lib = ERR_lib_error_string(errcode);
|
||||
+ func = ERR_func_error_string(errcode);
|
||||
+ reason = ERR_reason_error_string(errcode);
|
||||
+
|
||||
+ if (lib && func) {
|
||||
+ PyErr_Format(exc, "[%s: %s] %s", lib, func, reason);
|
||||
+ }
|
||||
+ else if (lib) {
|
||||
+ PyErr_Format(exc, "[%s] %s", lib, reason);
|
||||
+ }
|
||||
+ else {
|
||||
+ PyErr_SetString(exc, reason);
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+/* LCOV_EXCL_STOP */
|
||||
+
|
||||
static EVPobject *
|
||||
newEVPobject(PyObject *name)
|
||||
{
|
||||
EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, &EVPtype);
|
||||
+ if (retval == NULL) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
/* save the name for .name to return */
|
||||
- if (retval != NULL) {
|
||||
- Py_INCREF(name);
|
||||
- retval->name = name;
|
||||
+ Py_INCREF(name);
|
||||
+ retval->name = name;
|
||||
#ifdef WITH_THREAD
|
||||
- retval->lock = NULL;
|
||||
+ retval->lock = NULL;
|
||||
#endif
|
||||
+
|
||||
+ retval->ctx = EVP_MD_CTX_new();
|
||||
+ if (retval->ctx == NULL) {
|
||||
+ Py_DECREF(retval);
|
||||
+ PyErr_NoMemory();
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
@@ -101,7 +152,7 @@ EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len)
|
||||
process = MUNCH_SIZE;
|
||||
else
|
||||
process = Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int);
|
||||
- EVP_DigestUpdate(&self->ctx, (const void*)cp, process);
|
||||
+ EVP_DigestUpdate(self->ctx, (const void*)cp, process);
|
||||
len -= process;
|
||||
cp += process;
|
||||
}
|
||||
@@ -158,16 +209,19 @@ EVP_dealloc(EVPobject *self)
|
||||
if (self->lock != NULL)
|
||||
PyThread_free_lock(self->lock);
|
||||
#endif
|
||||
- EVP_MD_CTX_cleanup(&self->ctx);
|
||||
+ EVP_MD_CTX_free(self->ctx);
|
||||
Py_XDECREF(self->name);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
-static void locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self)
|
||||
+static int
|
||||
+locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self)
|
||||
{
|
||||
+ int result;
|
||||
ENTER_HASHLIB(self);
|
||||
- EVP_MD_CTX_copy(new_ctx_p, &self->ctx);
|
||||
+ result = EVP_MD_CTX_copy(new_ctx_p, self->ctx);
|
||||
LEAVE_HASHLIB(self);
|
||||
+ return result;
|
||||
}
|
||||
|
||||
/* External methods for a hash object */
|
||||
@@ -183,7 +237,9 @@ EVP_copy(EVPobject *self, PyObject *unused)
|
||||
if ( (newobj = newEVPobject(self->name))==NULL)
|
||||
return NULL;
|
||||
|
||||
- locked_EVP_MD_CTX_copy(&newobj->ctx, self);
|
||||
+ if (!locked_EVP_MD_CTX_copy(newobj->ctx, self)) {
|
||||
+ return _setException(PyExc_ValueError);
|
||||
+ }
|
||||
return (PyObject *)newobj;
|
||||
}
|
||||
|
||||
@@ -194,16 +250,24 @@ static PyObject *
|
||||
EVP_digest(EVPobject *self, PyObject *unused)
|
||||
{
|
||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
- EVP_MD_CTX temp_ctx;
|
||||
+ EVP_MD_CTX *temp_ctx;
|
||||
PyObject *retval;
|
||||
unsigned int digest_size;
|
||||
|
||||
- locked_EVP_MD_CTX_copy(&temp_ctx, self);
|
||||
- digest_size = EVP_MD_CTX_size(&temp_ctx);
|
||||
- EVP_DigestFinal(&temp_ctx, digest, NULL);
|
||||
+ temp_ctx = EVP_MD_CTX_new();
|
||||
+ if (temp_ctx == NULL) {
|
||||
+ PyErr_NoMemory();
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) {
|
||||
+ return _setException(PyExc_ValueError);
|
||||
+ }
|
||||
+ digest_size = EVP_MD_CTX_size(temp_ctx);
|
||||
+ EVP_DigestFinal(temp_ctx, digest, NULL);
|
||||
|
||||
retval = PyBytes_FromStringAndSize((const char *)digest, digest_size);
|
||||
- EVP_MD_CTX_cleanup(&temp_ctx);
|
||||
+ EVP_MD_CTX_free(temp_ctx);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -214,17 +278,25 @@ static PyObject *
|
||||
EVP_hexdigest(EVPobject *self, PyObject *unused)
|
||||
{
|
||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
- EVP_MD_CTX temp_ctx;
|
||||
+ EVP_MD_CTX *temp_ctx;
|
||||
PyObject *retval;
|
||||
char *hex_digest;
|
||||
unsigned int i, j, digest_size;
|
||||
|
||||
+ temp_ctx = EVP_MD_CTX_new();
|
||||
+ if (temp_ctx == NULL) {
|
||||
+ PyErr_NoMemory();
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
/* Get the raw (binary) digest value */
|
||||
- locked_EVP_MD_CTX_copy(&temp_ctx, self);
|
||||
- digest_size = EVP_MD_CTX_size(&temp_ctx);
|
||||
- EVP_DigestFinal(&temp_ctx, digest, NULL);
|
||||
+ if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) {
|
||||
+ return _setException(PyExc_ValueError);
|
||||
+ }
|
||||
+ digest_size = EVP_MD_CTX_size(temp_ctx);
|
||||
+ EVP_DigestFinal(temp_ctx, digest, NULL);
|
||||
|
||||
- EVP_MD_CTX_cleanup(&temp_ctx);
|
||||
+ EVP_MD_CTX_free(temp_ctx);
|
||||
|
||||
/* Allocate a new buffer */
|
||||
hex_digest = PyMem_Malloc(digest_size * 2 + 1);
|
||||
@@ -293,7 +365,7 @@ static PyObject *
|
||||
EVP_get_block_size(EVPobject *self, void *closure)
|
||||
{
|
||||
long block_size;
|
||||
- block_size = EVP_MD_CTX_block_size(&self->ctx);
|
||||
+ block_size = EVP_MD_CTX_block_size(self->ctx);
|
||||
return PyLong_FromLong(block_size);
|
||||
}
|
||||
|
||||
@@ -301,7 +373,7 @@ static PyObject *
|
||||
EVP_get_digest_size(EVPobject *self, void *closure)
|
||||
{
|
||||
long size;
|
||||
- size = EVP_MD_CTX_size(&self->ctx);
|
||||
+ size = EVP_MD_CTX_size(self->ctx);
|
||||
return PyLong_FromLong(size);
|
||||
}
|
||||
|
||||
@@ -363,8 +435,8 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
|
||||
PyBuffer_Release(&view);
|
||||
return -1;
|
||||
}
|
||||
- mc_ctx_init(&self->ctx, usedforsecurity);
|
||||
- if (!EVP_DigestInit_ex(&self->ctx, digest, NULL)) {
|
||||
+ mc_ctx_init(self->ctx, usedforsecurity);
|
||||
+ if (!EVP_DigestInit_ex(self->ctx, digest, NULL)) {
|
||||
set_evp_exception();
|
||||
PyBuffer_Release(&view);
|
||||
return -1;
|
||||
@@ -466,10 +538,10 @@ EVPnew(PyObject *name_obj,
|
||||
return NULL;
|
||||
|
||||
if (initial_ctx) {
|
||||
- EVP_MD_CTX_copy(&self->ctx, initial_ctx);
|
||||
+ EVP_MD_CTX_copy(self->ctx, initial_ctx);
|
||||
} else {
|
||||
- mc_ctx_init(&self->ctx, usedforsecurity);
|
||||
- if (!EVP_DigestInit_ex(&self->ctx, digest, NULL)) {
|
||||
+ mc_ctx_init(self->ctx, usedforsecurity);
|
||||
+ if (!EVP_DigestInit_ex(self->ctx, digest, NULL)) {
|
||||
set_evp_exception();
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
@@ -548,6 +620,7 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
|
||||
|
||||
#define PY_PBKDF2_HMAC 1
|
||||
|
||||
+#if !HAS_FAST_PKCS5_PBKDF2_HMAC
|
||||
/* Improved implementation of PKCS5_PBKDF2_HMAC()
|
||||
*
|
||||
* PKCS5_PBKDF2_HMAC_fast() hashes the password exactly one time instead of
|
||||
@@ -629,37 +702,8 @@ PKCS5_PBKDF2_HMAC_fast(const char *pass, int passlen,
|
||||
HMAC_CTX_cleanup(&hctx_tpl);
|
||||
return 1;
|
||||
}
|
||||
+#endif
|
||||
|
||||
-/* LCOV_EXCL_START */
|
||||
-static PyObject *
|
||||
-_setException(PyObject *exc)
|
||||
-{
|
||||
- unsigned long errcode;
|
||||
- const char *lib, *func, *reason;
|
||||
-
|
||||
- errcode = ERR_peek_last_error();
|
||||
- if (!errcode) {
|
||||
- PyErr_SetString(exc, "unknown reasons");
|
||||
- return NULL;
|
||||
- }
|
||||
- ERR_clear_error();
|
||||
-
|
||||
- lib = ERR_lib_error_string(errcode);
|
||||
- func = ERR_func_error_string(errcode);
|
||||
- reason = ERR_reason_error_string(errcode);
|
||||
-
|
||||
- if (lib && func) {
|
||||
- PyErr_Format(exc, "[%s: %s] %s", lib, func, reason);
|
||||
- }
|
||||
- else if (lib) {
|
||||
- PyErr_Format(exc, "[%s] %s", lib, reason);
|
||||
- }
|
||||
- else {
|
||||
- PyErr_SetString(exc, reason);
|
||||
- }
|
||||
- return NULL;
|
||||
-}
|
||||
-/* LCOV_EXCL_STOP */
|
||||
|
||||
PyDoc_STRVAR(pbkdf2_hmac__doc__,
|
||||
"pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None) -> key\n\
|
||||
@@ -741,10 +785,17 @@ pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict)
|
||||
key = PyBytes_AS_STRING(key_obj);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
+#if HAS_FAST_PKCS5_PBKDF2_HMAC
|
||||
+ retval = PKCS5_PBKDF2_HMAC((char*)password.buf, (int)password.len,
|
||||
+ (unsigned char *)salt.buf, (int)salt.len,
|
||||
+ iterations, digest, dklen,
|
||||
+ (unsigned char *)key);
|
||||
+#else
|
||||
retval = PKCS5_PBKDF2_HMAC_fast((char*)password.buf, (int)password.len,
|
||||
(unsigned char *)salt.buf, (int)salt.len,
|
||||
iterations, digest, dklen,
|
||||
(unsigned char *)key);
|
||||
+#endif
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
if (!retval) {
|
||||
@@ -860,11 +911,11 @@ implement_specific_EVP_new(PyObject *self, PyObject *args, PyObject *kwdict,
|
||||
* If an error occurred during creation of the global content, the ctx_ptr
|
||||
* will be NULL, and the error_msg will hopefully be non-NULL:
|
||||
*/
|
||||
- if (cached_info->ctx_ptrs[idx]) {
|
||||
+ if (cached_info->initialized[idx]) {
|
||||
/* We successfully initialized this context; copy it: */
|
||||
ret_obj = EVPnew(cached_info->name_obj,
|
||||
NULL,
|
||||
- cached_info->ctx_ptrs[idx],
|
||||
+ cached_info->ctxs[idx],
|
||||
(unsigned char*)view.buf, view.len,
|
||||
usedforsecurity);
|
||||
} else {
|
||||
@@ -897,14 +948,11 @@ implement_specific_EVP_new(PyObject *self, PyObject *args, PyObject *kwdict,
|
||||
|
||||
Try to initialize a context for each hash twice, once with
|
||||
EVP_MD_CTX_FLAG_NON_FIPS_ALLOW and once without.
|
||||
-
|
||||
- Any that have errors during initialization will end up with a NULL ctx_ptrs
|
||||
- entry, and err_msgs will be set (unless we're very low on memory)
|
||||
+
|
||||
+ Any that have errors during initialization will end up with initialized[i]
|
||||
+ set to 0 and err_msgs being set.
|
||||
*/
|
||||
-#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \
|
||||
- init_constructor_constant(&cached_info_ ## NAME, #NAME); \
|
||||
-} while (0);
|
||||
-static void
|
||||
+static int
|
||||
init_constructor_constant(EVPCachedInfo *cached_info, const char *name)
|
||||
{
|
||||
assert(cached_info);
|
||||
@@ -912,18 +960,25 @@ init_constructor_constant(EVPCachedInfo *cached_info, const char *name)
|
||||
if (EVP_get_digestbyname(name)) {
|
||||
int i;
|
||||
for (i=0; i<2; i++) {
|
||||
- mc_ctx_init(&cached_info->ctxs[i], i);
|
||||
- if (EVP_DigestInit_ex(&cached_info->ctxs[i],
|
||||
- EVP_get_digestbyname(name), NULL)) {
|
||||
+ cached_info->ctxs[i] = EVP_MD_CTX_new();
|
||||
+ if (cached_info->ctxs[i] == NULL) {
|
||||
+ PyErr_NoMemory();
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ mc_ctx_init(cached_info->ctxs[i], i);
|
||||
+ if (EVP_DigestInit(cached_info->ctxs[i],
|
||||
+ EVP_get_digestbyname(name))) {
|
||||
/* Success: */
|
||||
- cached_info->ctx_ptrs[i] = &cached_info->ctxs[i];
|
||||
+ cached_info->initialized[i] = 1;
|
||||
} else {
|
||||
/* Failure: */
|
||||
- cached_info->ctx_ptrs[i] = NULL;
|
||||
- cached_info->error_msgs[i] = error_msg_for_last_error();
|
||||
+ cached_info->error_msgs[i] = error_msg_for_last_error();
|
||||
+ cached_info->initialized[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1002,6 +1057,13 @@ PyInit__hashlib(void)
|
||||
Py_INCREF((PyObject *)&EVPtype);
|
||||
PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype);
|
||||
|
||||
+#define INIT_CONSTRUCTOR_CONSTANTS(NAME) \
|
||||
+ do { \
|
||||
+ if (init_constructor_constant(&cached_info_ ## NAME, #NAME) < 0) { \
|
||||
+ return NULL; \
|
||||
+ } \
|
||||
+ } while (0);
|
||||
+
|
||||
/* these constants are used by the convenience constructors */
|
||||
INIT_CONSTRUCTOR_CONSTANTS(md5);
|
||||
INIT_CONSTRUCTOR_CONSTANTS(sha1);
|
||||
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
|
||||
index 0ff9d55..c94cdc3 100644
|
||||
--- a/Modules/_ssl.c
|
||||
+++ b/Modules/_ssl.c
|
||||
@@ -55,6 +55,14 @@ static PySocketModule_APIObject PySocketModule;
|
||||
#include <sys/poll.h>
|
||||
#endif
|
||||
|
||||
+/* Don't warn about deprecated functions */
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
+#endif
|
||||
+#ifdef __clang__
|
||||
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
+#endif
|
||||
+
|
||||
/* Include OpenSSL header files */
|
||||
#include "openssl/rsa.h"
|
||||
#include "openssl/crypto.h"
|
||||
@@ -90,6 +98,10 @@ struct py_ssl_library_code {
|
||||
/* Include generated data (error codes) */
|
||||
#include "_ssl_data.h"
|
||||
|
||||
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
+# define OPENSSL_VERSION_1_1 1
|
||||
+#endif
|
||||
+
|
||||
/* Openssl comes with TLSv1.1 and TLSv1.2 between 1.0.0h and 1.0.1
|
||||
http://www.openssl.org/news/changelog.html
|
||||
*/
|
||||
@@ -108,6 +120,72 @@ struct py_ssl_library_code {
|
||||
# define HAVE_SNI 0
|
||||
#endif
|
||||
|
||||
+#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
+# define HAVE_ALPN
|
||||
+#endif
|
||||
+
|
||||
+#ifndef INVALID_SOCKET /* MS defines this */
|
||||
+#define INVALID_SOCKET (-1)
|
||||
+#endif
|
||||
+
|
||||
+#ifdef OPENSSL_VERSION_1_1
|
||||
+/* OpenSSL 1.1.0+ */
|
||||
+#ifndef OPENSSL_NO_SSL2
|
||||
+#define OPENSSL_NO_SSL2
|
||||
+#endif
|
||||
+#else /* OpenSSL < 1.1.0 */
|
||||
+#if defined(WITH_THREAD)
|
||||
+#define HAVE_OPENSSL_CRYPTO_LOCK
|
||||
+#endif
|
||||
+
|
||||
+static int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne)
|
||||
+{
|
||||
+ return ne->set;
|
||||
+}
|
||||
+
|
||||
+#ifndef OPENSSL_NO_COMP
|
||||
+static int COMP_get_type(const COMP_METHOD *meth)
|
||||
+{
|
||||
+ return meth->type;
|
||||
+}
|
||||
+
|
||||
+static const char *COMP_get_name(const COMP_METHOD *meth)
|
||||
+{
|
||||
+ return meth->name;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx)
|
||||
+{
|
||||
+ return ctx->default_passwd_callback;
|
||||
+}
|
||||
+
|
||||
+static void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx)
|
||||
+{
|
||||
+ return ctx->default_passwd_callback_userdata;
|
||||
+}
|
||||
+
|
||||
+static int X509_OBJECT_get_type(X509_OBJECT *x)
|
||||
+{
|
||||
+ return x->type;
|
||||
+}
|
||||
+
|
||||
+static X509 *X509_OBJECT_get0_X509(X509_OBJECT *x)
|
||||
+{
|
||||
+ return x->data.x509;
|
||||
+}
|
||||
+
|
||||
+static STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *store) {
|
||||
+ return store->objs;
|
||||
+}
|
||||
+
|
||||
+static X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *store)
|
||||
+{
|
||||
+ return store->param;
|
||||
+}
|
||||
+#endif /* OpenSSL < 1.1.0 or LibreSSL */
|
||||
+
|
||||
+
|
||||
enum py_ssl_error {
|
||||
/* these mirror ssl.h */
|
||||
PY_SSL_ERROR_NONE,
|
||||
@@ -691,7 +769,7 @@ _create_tuple_for_X509_NAME (X509_NAME *xname)
|
||||
|
||||
/* check to see if we've gotten to a new RDN */
|
||||
if (rdn_level >= 0) {
|
||||
- if (rdn_level != entry->set) {
|
||||
+ if (rdn_level != X509_NAME_ENTRY_set(entry)) {
|
||||
/* yes, new RDN */
|
||||
/* add old RDN to DN */
|
||||
rdnt = PyList_AsTuple(rdn);
|
||||
@@ -708,7 +786,7 @@ _create_tuple_for_X509_NAME (X509_NAME *xname)
|
||||
goto fail0;
|
||||
}
|
||||
}
|
||||
- rdn_level = entry->set;
|
||||
+ rdn_level = X509_NAME_ENTRY_set(entry);
|
||||
|
||||
/* now add this attribute to the current RDN */
|
||||
name = X509_NAME_ENTRY_get_object(entry);
|
||||
@@ -811,18 +889,18 @@ _get_peer_alt_names (X509 *certificate) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- p = ext->value->data;
|
||||
+ p = X509_EXTENSION_get_data(ext)->data;
|
||||
if (method->it)
|
||||
names = (GENERAL_NAMES*)
|
||||
(ASN1_item_d2i(NULL,
|
||||
&p,
|
||||
- ext->value->length,
|
||||
+ X509_EXTENSION_get_data(ext)->length,
|
||||
ASN1_ITEM_ptr(method->it)));
|
||||
else
|
||||
names = (GENERAL_NAMES*)
|
||||
(method->d2i(NULL,
|
||||
&p,
|
||||
- ext->value->length));
|
||||
+ X509_EXTENSION_get_data(ext)->length));
|
||||
|
||||
for(j = 0; j < sk_GENERAL_NAME_num(names); j++) {
|
||||
/* get a rendering of each name in the set of names */
|
||||
@@ -1033,13 +1111,11 @@ _get_crl_dp(X509 *certificate) {
|
||||
int i, j;
|
||||
PyObject *lst, *res = NULL;
|
||||
|
||||
-#if OPENSSL_VERSION_NUMBER < 0x10001000L
|
||||
- dps = X509_get_ext_d2i(certificate, NID_crl_distribution_points, NULL, NULL);
|
||||
-#else
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||||
/* Calls x509v3_cache_extensions and sets up crldp */
|
||||
X509_check_ca(certificate);
|
||||
- dps = certificate->crldp;
|
||||
#endif
|
||||
+ dps = X509_get_ext_d2i(certificate, NID_crl_distribution_points, NULL, NULL);
|
||||
|
||||
if (dps == NULL)
|
||||
return Py_None;
|
||||
@@ -1431,9 +1507,9 @@ static PyObject *PySSL_compression(PySSLSocket *self) {
|
||||
if (self->ssl == NULL)
|
||||
Py_RETURN_NONE;
|
||||
comp_method = SSL_get_current_compression(self->ssl);
|
||||
- if (comp_method == NULL || comp_method->type == NID_undef)
|
||||
+ if (comp_method == NULL || COMP_get_type(comp_method) == NID_undef)
|
||||
Py_RETURN_NONE;
|
||||
- short_name = OBJ_nid2sn(comp_method->type);
|
||||
+ short_name = COMP_get_name(comp_method);
|
||||
if (short_name == NULL)
|
||||
Py_RETURN_NONE;
|
||||
return PyUnicode_DecodeFSDefault(short_name);
|
||||
@@ -2051,8 +2127,9 @@ context_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
/* Allow automatic ECDH curve selection (on OpenSSL 1.0.2+), or use
|
||||
prime256v1 by default. This is Apache mod_ssl's initialization
|
||||
- policy, so we should be safe. */
|
||||
-#if defined(SSL_CTX_set_ecdh_auto)
|
||||
+ policy, so we should be safe. OpenSSL 1.1 has it enabled by default.
|
||||
+ */
|
||||
+#if defined(SSL_CTX_set_ecdh_auto) && !defined(OPENSSL_VERSION_1_1)
|
||||
SSL_CTX_set_ecdh_auto(self->ctx, 1);
|
||||
#else
|
||||
{
|
||||
@@ -2263,10 +2340,12 @@ static PyObject *
|
||||
get_verify_flags(PySSLContext *self, void *c)
|
||||
{
|
||||
X509_STORE *store;
|
||||
+ X509_VERIFY_PARAM *param;
|
||||
unsigned long flags;
|
||||
|
||||
store = SSL_CTX_get_cert_store(self->ctx);
|
||||
- flags = X509_VERIFY_PARAM_get_flags(store->param);
|
||||
+ param = X509_STORE_get0_param(store);
|
||||
+ flags = X509_VERIFY_PARAM_get_flags(param);
|
||||
return PyLong_FromUnsignedLong(flags);
|
||||
}
|
||||
|
||||
@@ -2274,22 +2353,24 @@ static int
|
||||
set_verify_flags(PySSLContext *self, PyObject *arg, void *c)
|
||||
{
|
||||
X509_STORE *store;
|
||||
+ X509_VERIFY_PARAM *param;
|
||||
unsigned long new_flags, flags, set, clear;
|
||||
|
||||
if (!PyArg_Parse(arg, "k", &new_flags))
|
||||
return -1;
|
||||
store = SSL_CTX_get_cert_store(self->ctx);
|
||||
- flags = X509_VERIFY_PARAM_get_flags(store->param);
|
||||
+ param = X509_STORE_get0_param(store);
|
||||
+ flags = X509_VERIFY_PARAM_get_flags(param);
|
||||
clear = flags & ~new_flags;
|
||||
set = ~flags & new_flags;
|
||||
if (clear) {
|
||||
- if (!X509_VERIFY_PARAM_clear_flags(store->param, clear)) {
|
||||
+ if (!X509_VERIFY_PARAM_clear_flags(param, clear)) {
|
||||
_setSSLError(NULL, 0, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (set) {
|
||||
- if (!X509_VERIFY_PARAM_set_flags(store->param, set)) {
|
||||
+ if (!X509_VERIFY_PARAM_set_flags(param, set)) {
|
||||
_setSSLError(NULL, 0, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
@@ -2459,8 +2540,8 @@ load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwds)
|
||||
char *kwlist[] = {"certfile", "keyfile", "password", NULL};
|
||||
PyObject *certfile, *keyfile = NULL, *password = NULL;
|
||||
PyObject *certfile_bytes = NULL, *keyfile_bytes = NULL;
|
||||
- pem_password_cb *orig_passwd_cb = self->ctx->default_passwd_callback;
|
||||
- void *orig_passwd_userdata = self->ctx->default_passwd_callback_userdata;
|
||||
+ pem_password_cb *orig_passwd_cb = SSL_CTX_get_default_passwd_cb(self->ctx);
|
||||
+ void *orig_passwd_userdata = SSL_CTX_get_default_passwd_cb_userdata(self->ctx);
|
||||
_PySSLPasswordInfo pw_info = { NULL, NULL, NULL, 0, 0 };
|
||||
int r;
|
||||
|
||||
@@ -2591,8 +2672,9 @@ _add_ca_certs(PySSLContext *self, void *data, Py_ssize_t len,
|
||||
cert = d2i_X509_bio(biobuf, NULL);
|
||||
} else {
|
||||
cert = PEM_read_bio_X509(biobuf, NULL,
|
||||
- self->ctx->default_passwd_callback,
|
||||
- self->ctx->default_passwd_callback_userdata);
|
||||
+ SSL_CTX_get_default_passwd_cb(self->ctx),
|
||||
+ SSL_CTX_get_default_passwd_cb_userdata(self->ctx)
|
||||
+ );
|
||||
}
|
||||
if (cert == NULL) {
|
||||
break;
|
||||
@@ -3040,25 +3122,24 @@ static PyObject *
|
||||
cert_store_stats(PySSLContext *self)
|
||||
{
|
||||
X509_STORE *store;
|
||||
+ STACK_OF(X509_OBJECT) *objs;
|
||||
X509_OBJECT *obj;
|
||||
- int x509 = 0, crl = 0, pkey = 0, ca = 0, i;
|
||||
+ int x509 = 0, crl = 0, ca = 0, i;
|
||||
|
||||
store = SSL_CTX_get_cert_store(self->ctx);
|
||||
- for (i = 0; i < sk_X509_OBJECT_num(store->objs); i++) {
|
||||
- obj = sk_X509_OBJECT_value(store->objs, i);
|
||||
- switch (obj->type) {
|
||||
+ objs = X509_STORE_get0_objects(store);
|
||||
+ for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
|
||||
+ obj = sk_X509_OBJECT_value(objs, i);
|
||||
+ switch (X509_OBJECT_get_type(obj)) {
|
||||
case X509_LU_X509:
|
||||
x509++;
|
||||
- if (X509_check_ca(obj->data.x509)) {
|
||||
+ if (X509_check_ca(X509_OBJECT_get0_X509(obj))) {
|
||||
ca++;
|
||||
}
|
||||
break;
|
||||
case X509_LU_CRL:
|
||||
crl++;
|
||||
break;
|
||||
- case X509_LU_PKEY:
|
||||
- pkey++;
|
||||
- break;
|
||||
default:
|
||||
/* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY.
|
||||
* As far as I can tell they are internal states and never
|
||||
@@ -3083,6 +3164,7 @@ get_ca_certs(PySSLContext *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
char *kwlist[] = {"binary_form", NULL};
|
||||
X509_STORE *store;
|
||||
+ STACK_OF(X509_OBJECT) *objs;
|
||||
PyObject *ci = NULL, *rlist = NULL;
|
||||
int i;
|
||||
int binary_mode = 0;
|
||||
@@ -3097,17 +3179,18 @@ get_ca_certs(PySSLContext *self, PyObject *args, PyObject *kwds)
|
||||
}
|
||||
|
||||
store = SSL_CTX_get_cert_store(self->ctx);
|
||||
- for (i = 0; i < sk_X509_OBJECT_num(store->objs); i++) {
|
||||
+ objs = X509_STORE_get0_objects(store);
|
||||
+ for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
|
||||
X509_OBJECT *obj;
|
||||
X509 *cert;
|
||||
|
||||
- obj = sk_X509_OBJECT_value(store->objs, i);
|
||||
- if (obj->type != X509_LU_X509) {
|
||||
+ obj = sk_X509_OBJECT_value(objs, i);
|
||||
+ if (X509_OBJECT_get_type(obj) != X509_LU_X509) {
|
||||
/* not a x509 cert */
|
||||
continue;
|
||||
}
|
||||
/* CA for any purpose */
|
||||
- cert = obj->data.x509;
|
||||
+ cert = X509_OBJECT_get0_X509(obj);
|
||||
if (!X509_check_ca(cert)) {
|
||||
continue;
|
||||
}
|
||||
@@ -3780,10 +3863,12 @@ static PyMethodDef PySSL_methods[] = {
|
||||
};
|
||||
|
||||
|
||||
-#ifdef WITH_THREAD
|
||||
+#ifdef HAVE_OPENSSL_CRYPTO_LOCK
|
||||
|
||||
/* an implementation of OpenSSL threading operations in terms
|
||||
- of the Python C thread library */
|
||||
+ * of the Python C thread library
|
||||
+ * Only used up to 1.0.2. OpenSSL 1.1.0+ has its own locking code.
|
||||
+ */
|
||||
|
||||
static PyThread_type_lock *_ssl_locks = NULL;
|
||||
|
||||
@@ -3864,7 +3949,7 @@ static int _setup_ssl_threads(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
-#endif /* def HAVE_THREAD */
|
||||
+#endif /* HAVE_OPENSSL_CRYPTO_LOCK for WITH_THREAD && OpenSSL < 1.1.0 */
|
||||
|
||||
PyDoc_STRVAR(module_doc,
|
||||
"Implementation module for SSL socket operations. See the socket module\n\
|
||||
@@ -3931,11 +4016,16 @@ PyInit__ssl(void)
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
#ifdef WITH_THREAD
|
||||
+#ifdef HAVE_OPENSSL_CRYPTO_LOCK
|
||||
/* note that this will start threading if not already started */
|
||||
if (!_setup_ssl_threads()) {
|
||||
return NULL;
|
||||
}
|
||||
+#elif OPENSSL_VERSION_1_1 && defined(OPENSSL_THREADS)
|
||||
+ /* OpenSSL 1.1.0 builtin thread support is enabled */
|
||||
+ _ssl_locks_count++;
|
||||
#endif
|
||||
+#endif /* WITH_THREAD */
|
||||
OpenSSL_add_all_algorithms();
|
||||
|
||||
/* Add symbols to module dict */
|
||||
67
lang/python34/files/00322-test_ssl-skip-openssl111.patch
Normal file
67
lang/python34/files/00322-test_ssl-skip-openssl111.patch
Normal file
@@ -0,0 +1,67 @@
|
||||
bpo-36576: Skip test_ssl and test_asyncio tests failing with OpenSSL 1.1.1
|
||||
|
||||
Some test_ssl and test_asyncio are written for OpenSSL 1.0 and TLS
|
||||
1.0, but fail with OpenSSL 1.1.1 and TLS 1.3.
|
||||
|
||||
Fixing these needs require to backport new ssl flags like
|
||||
ssl.OP_NO_TLSv1_3 or ssl.OP_NO_COMPRESSION which cannot be done in a
|
||||
minor 3.5.x release. Moreover, it is not really worth it: the code
|
||||
works fine, issues are in the tests.
|
||||
|
||||
Backport of: https://github.com/python/cpython/pull/12694
|
||||
|
||||
Resolves: rhbz#1685609
|
||||
|
||||
diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py
|
||||
index 6373618..3db3707 100644
|
||||
--- a/Lib/test/test_asyncio/test_events.py
|
||||
+++ b/Lib/test/test_asyncio/test_events.py
|
||||
@@ -33,6 +33,12 @@ except ImportError:
|
||||
from asyncio import test_support as support
|
||||
|
||||
|
||||
+if ssl is not None:
|
||||
+ IS_OPENSSL_1_1_1 = ssl.OPENSSL_VERSION_INFO >= (1, 1, 1)
|
||||
+else:
|
||||
+ IS_OPENSSL_1_1_1 = False
|
||||
+
|
||||
+
|
||||
def data_file(filename):
|
||||
if hasattr(support, 'TEST_HOME_DIR'):
|
||||
fullname = os.path.join(support.TEST_HOME_DIR, filename)
|
||||
@@ -1049,6 +1055,7 @@ class EventLoopTestsMixin:
|
||||
self.test_create_unix_server_ssl_verify_failed()
|
||||
|
||||
@unittest.skipIf(ssl is None, 'No ssl module')
|
||||
+ @unittest.skipIf(IS_OPENSSL_1_1_1, "bpo-36576: fail on OpenSSL 1.1.1")
|
||||
def test_create_server_ssl_match_failed(self):
|
||||
proto = MyProto(loop=self.loop)
|
||||
server, host, port = self._make_ssl_server(
|
||||
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
|
||||
index 401cc2f..8edf055 100644
|
||||
--- a/Lib/test/test_ssl.py
|
||||
+++ b/Lib/test/test_ssl.py
|
||||
@@ -24,6 +24,7 @@ ssl = support.import_module("ssl")
|
||||
PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
|
||||
HOST = support.HOST
|
||||
IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
|
||||
+IS_OPENSSL_1_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 1)
|
||||
|
||||
|
||||
def data_file(*name):
|
||||
@@ -697,6 +698,7 @@ class ContextTests(unittest.TestCase):
|
||||
ctx.set_ciphers("^$:,;?*'dorothyx")
|
||||
|
||||
@skip_if_broken_ubuntu_ssl
|
||||
+ @unittest.skipIf(IS_OPENSSL_1_1_1, "bpo-36576: fail on OpenSSL 1.1.1")
|
||||
def test_options(self):
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||
# OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
|
||||
@@ -2655,6 +2657,7 @@ else:
|
||||
self.assertIn("no shared cipher", str(server.conn_errors[0]))
|
||||
|
||||
@unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
|
||||
+ @unittest.skipIf(IS_OPENSSL_1_1_1, "bpo-36576: fail on OpenSSL 1.1.1")
|
||||
def test_default_ecdh_curve(self):
|
||||
# Issue #21015: elliptic curve-based Diffie Hellman key exchange
|
||||
# should be enabled by default on SSL contexts.
|
||||
95
lang/python34/files/00332-CVE-2019-16056.patch
Normal file
95
lang/python34/files/00332-CVE-2019-16056.patch
Normal file
@@ -0,0 +1,95 @@
|
||||
diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py
|
||||
index 37a9fbcbb67d..facc208fde12 100644
|
||||
--- a/Lib/email/_header_value_parser.py
|
||||
+++ b/Lib/email/_header_value_parser.py
|
||||
@@ -1964,6 +1964,8 @@ def get_domain(value):
|
||||
token, value = get_dot_atom(value)
|
||||
except errors.HeaderParseError:
|
||||
token, value = get_atom(value)
|
||||
+ if value and value[0] == '@':
|
||||
+ raise errors.HeaderParseError('Invalid Domain')
|
||||
if leader is not None:
|
||||
token[:0] = [leader]
|
||||
domain.append(token)
|
||||
diff --git a/Lib/email/_parseaddr.py b/Lib/email/_parseaddr.py
|
||||
index cdfa3729adc7..41ff6f8c000d 100644
|
||||
--- a/Lib/email/_parseaddr.py
|
||||
+++ b/Lib/email/_parseaddr.py
|
||||
@@ -379,7 +379,12 @@ def getaddrspec(self):
|
||||
aslist.append('@')
|
||||
self.pos += 1
|
||||
self.gotonext()
|
||||
- return EMPTYSTRING.join(aslist) + self.getdomain()
|
||||
+ domain = self.getdomain()
|
||||
+ if not domain:
|
||||
+ # Invalid domain, return an empty address instead of returning a
|
||||
+ # local part to denote failed parsing.
|
||||
+ return EMPTYSTRING
|
||||
+ return EMPTYSTRING.join(aslist) + domain
|
||||
|
||||
def getdomain(self):
|
||||
"""Get the complete domain name from an address."""
|
||||
@@ -394,6 +399,10 @@ def getdomain(self):
|
||||
elif self.field[self.pos] == '.':
|
||||
self.pos += 1
|
||||
sdlist.append('.')
|
||||
+ elif self.field[self.pos] == '@':
|
||||
+ # bpo-34155: Don't parse domains with two `@` like
|
||||
+ # `a@malicious.org@important.com`.
|
||||
+ return EMPTYSTRING
|
||||
elif self.field[self.pos] in self.atomends:
|
||||
break
|
||||
else:
|
||||
diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py
|
||||
index b1e7dff2405d..8ae617a6bd58 100644
|
||||
--- a/Lib/test/test_email/test__header_value_parser.py
|
||||
+++ b/Lib/test/test_email/test__header_value_parser.py
|
||||
@@ -1418,6 +1418,16 @@ def test_get_addr_spec_dot_atom(self):
|
||||
self.assertEqual(addr_spec.domain, 'example.com')
|
||||
self.assertEqual(addr_spec.addr_spec, 'star.a.star@example.com')
|
||||
|
||||
+ def test_get_addr_spec_multiple_domains(self):
|
||||
+ with self.assertRaises(errors.HeaderParseError):
|
||||
+ parser.get_addr_spec('star@a.star@example.com')
|
||||
+
|
||||
+ with self.assertRaises(errors.HeaderParseError):
|
||||
+ parser.get_addr_spec('star@a@example.com')
|
||||
+
|
||||
+ with self.assertRaises(errors.HeaderParseError):
|
||||
+ parser.get_addr_spec('star@172.17.0.1@example.com')
|
||||
+
|
||||
# get_obs_route
|
||||
|
||||
def test_get_obs_route_simple(self):
|
||||
diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
|
||||
index 9b86a2aee9ac..d4c3447e63d0 100644
|
||||
--- a/Lib/test/test_email/test_email.py
|
||||
+++ b/Lib/test/test_email/test_email.py
|
||||
@@ -3015,6 +3015,20 @@ def test_parseaddr_empty(self):
|
||||
self.assertEqual(utils.parseaddr('<>'), ('', ''))
|
||||
self.assertEqual(utils.formataddr(utils.parseaddr('<>')), '')
|
||||
|
||||
+ def test_parseaddr_multiple_domains(self):
|
||||
+ self.assertEqual(
|
||||
+ utils.parseaddr('a@b@c'),
|
||||
+ ('', '')
|
||||
+ )
|
||||
+ self.assertEqual(
|
||||
+ utils.parseaddr('a@b.c@c'),
|
||||
+ ('', '')
|
||||
+ )
|
||||
+ self.assertEqual(
|
||||
+ utils.parseaddr('a@172.17.0.1@c'),
|
||||
+ ('', '')
|
||||
+ )
|
||||
+
|
||||
def test_noquote_dump(self):
|
||||
self.assertEqual(
|
||||
utils.formataddr(('A Silly Person', 'person@dom.ain')),
|
||||
diff --git a/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst
|
||||
new file mode 100644
|
||||
index 000000000000..50292e29ed1d
|
||||
--- /dev/null
|
||||
+++ b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst
|
||||
@@ -0,0 +1 @@
|
||||
+Fix parsing of invalid email addresses with more than one ``@`` (e.g. a@b@c.com.) to not return the part before 2nd ``@`` as valid email address. Patch by maxking & jpic.
|
||||
72
lang/python34/files/05000-autotool-intermediates.patch
Normal file
72
lang/python34/files/05000-autotool-intermediates.patch
Normal file
@@ -0,0 +1,72 @@
|
||||
diff -up ./configure.autotool-intermediates ./configure
|
||||
--- ./configure.autotool-intermediates 2013-04-09 14:52:49.831773426 +0200
|
||||
+++ ./configure 2013-04-09 14:52:53.204765347 +0200
|
||||
@@ -802,6 +802,8 @@ with_thread
|
||||
enable_ipv6
|
||||
with_doc_strings
|
||||
with_tsc
|
||||
+with_count_allocs
|
||||
+with_call_profile
|
||||
with_pymalloc
|
||||
with_valgrind
|
||||
with_systemtap
|
||||
@@ -1479,6 +1481,8 @@ Optional Packages:
|
||||
deprecated; use --with(out)-threads
|
||||
--with(out)-doc-strings disable/enable documentation strings
|
||||
--with(out)-tsc enable/disable timestamp counter profile
|
||||
+ --with(out)count-allocs enable/disable per-type instance accounting
|
||||
+ --with(out)-call-profile enable/disable statistics on function call invocation
|
||||
--with(out)-pymalloc disable/enable specialized mallocs
|
||||
--with-valgrind Enable Valgrind support
|
||||
--with(out)-systemtap disable/enable SystemTap support
|
||||
@@ -10117,6 +10121,50 @@ $as_echo "#define WITH_TSC 1" >>confdefs
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
+else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
+$as_echo "no" >&6; }
|
||||
+fi
|
||||
+else
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
+$as_echo "no" >&6; }
|
||||
+fi
|
||||
+
|
||||
+
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-count-allocs" >&5
|
||||
+$as_echo_n "checking for --with-count-allocs... " >&6; }
|
||||
+
|
||||
+# Check whether --with-count-allocs was given.
|
||||
+if test "${with_count_allocs+set}" = set; then :
|
||||
+ withval=$with_count_allocs;
|
||||
+if test "$withval" != no
|
||||
+then
|
||||
+
|
||||
+$as_echo "#define COUNT_ALLOCS 1" >>confdefs.h
|
||||
+
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
+$as_echo "yes" >&6; }
|
||||
+else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
+$as_echo "no" >&6; }
|
||||
+fi
|
||||
+else
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
+$as_echo "no" >&6; }
|
||||
+fi
|
||||
+
|
||||
+
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-call-profile" >&5
|
||||
+$as_echo_n "checking for --with-call-profile... " >&6; }
|
||||
+
|
||||
+# Check whether --with-call-profile was given.
|
||||
+if test "${with_call_profile+set}" = set; then :
|
||||
+ withval=$with_call_profile;
|
||||
+if test "$withval" != no
|
||||
+then
|
||||
+
|
||||
+$as_echo "#define CALL_PROFILE 1" >>confdefs.h
|
||||
+
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
+$as_echo "yes" >&6; }
|
||||
else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
637
lang/python34/files/patch-00146-hashlib-fips.patch
Normal file
637
lang/python34/files/patch-00146-hashlib-fips.patch
Normal file
@@ -0,0 +1,637 @@
|
||||
--- Lib/hashlib.py.hashlib-fips 2013-11-24 21:36:54.000000000 +0100
|
||||
+++ Lib/hashlib.py 2013-11-27 11:45:17.073617547 +0100
|
||||
@@ -23,6 +23,16 @@
|
||||
Choose your hash function wisely. Some have known collision weaknesses.
|
||||
sha384 and sha512 will be slow on 32 bit platforms.
|
||||
|
||||
+If the underlying implementation supports "FIPS mode", and this is enabled, it
|
||||
+may restrict the available hashes to only those that are compliant with FIPS
|
||||
+regulations. For example, it may deny the use of MD5, on the grounds that this
|
||||
+is not secure for uses such as authentication, system integrity checking, or
|
||||
+digital signatures. If you need to use such a hash for non-security purposes
|
||||
+(such as indexing into a data structure for speed), you can override the keyword
|
||||
+argument "usedforsecurity" from True to False to signify that your code is not
|
||||
+relying on the hash for security purposes, and this will allow the hash to be
|
||||
+usable even in FIPS mode.
|
||||
+
|
||||
Hash objects have these methods:
|
||||
- update(arg): Update the hash object with the bytes in arg. Repeated calls
|
||||
are equivalent to a single call with the concatenation of all
|
||||
@@ -63,6 +73,19 @@
|
||||
__all__ = __always_supported + ('new', 'algorithms_guaranteed',
|
||||
'algorithms_available', 'pbkdf2_hmac')
|
||||
|
||||
+import functools
|
||||
+def __ignore_usedforsecurity(func):
|
||||
+ """Used for sha3_* functions. Until OpenSSL implements them, we want
|
||||
+ to use them from Python _sha3 module, but we want them to accept
|
||||
+ usedforsecurity argument too."""
|
||||
+ # TODO: remove this function when OpenSSL implements sha3
|
||||
+ @functools.wraps(func)
|
||||
+ def inner(*args, **kwargs):
|
||||
+ if 'usedforsecurity' in kwargs:
|
||||
+ kwargs.pop('usedforsecurity')
|
||||
+ return func(*args, **kwargs)
|
||||
+ return inner
|
||||
+
|
||||
|
||||
__builtin_constructor_cache = {}
|
||||
|
||||
@@ -108,34 +131,41 @@
|
||||
f = getattr(_hashlib, 'openssl_' + name)
|
||||
# Allow the C module to raise ValueError. The function will be
|
||||
# defined but the hash not actually available thanks to OpenSSL.
|
||||
- f()
|
||||
+ # We pass "usedforsecurity=False" to disable FIPS-based restrictions:
|
||||
+ # at this stage we're merely seeing if the function is callable,
|
||||
+ # rather than using it for actual work.
|
||||
+ f(usedforsecurity=False)
|
||||
# Use the C function directly (very fast)
|
||||
return f
|
||||
except (AttributeError, ValueError):
|
||||
+ # TODO: We want to just raise here when OpenSSL implements sha3
|
||||
+ # because we want to make sure that Fedora uses everything from OpenSSL
|
||||
return __get_builtin_constructor(name)
|
||||
|
||||
|
||||
-def __py_new(name, data=b''):
|
||||
- """new(name, data=b'') - Return a new hashing object using the named algorithm;
|
||||
- optionally initialized with data (which must be bytes).
|
||||
+def __py_new(name, data=b'', usedforsecurity=True):
|
||||
+ """new(name, data=b'', usedforsecurity=True) - Return a new hashing object using
|
||||
+ the named algorithm; optionally initialized with data (which must be bytes).
|
||||
+ The 'usedforsecurity' keyword argument does nothing, and is for compatibilty
|
||||
+ with the OpenSSL implementation
|
||||
"""
|
||||
return __get_builtin_constructor(name)(data)
|
||||
|
||||
|
||||
-def __hash_new(name, data=b''):
|
||||
- """new(name, data=b'') - Return a new hashing object using the named algorithm;
|
||||
- optionally initialized with data (which must be bytes).
|
||||
+def __hash_new(name, data=b'', usedforsecurity=True):
|
||||
+ """new(name, data=b'', usedforsecurity=True) - Return a new hashing object using
|
||||
+ the named algorithm; optionally initialized with data (which must be bytes).
|
||||
+
|
||||
+ Override 'usedforsecurity' to False when using for non-security purposes in
|
||||
+ a FIPS environment
|
||||
"""
|
||||
try:
|
||||
- return _hashlib.new(name, data)
|
||||
+ return _hashlib.new(name, data, usedforsecurity)
|
||||
except ValueError:
|
||||
- # If the _hashlib module (OpenSSL) doesn't support the named
|
||||
- # hash, try using our builtin implementations.
|
||||
- # This allows for SHA224/256 and SHA384/512 support even though
|
||||
- # the OpenSSL library prior to 0.9.8 doesn't provide them.
|
||||
+ # TODO: We want to just raise here when OpenSSL implements sha3
|
||||
+ # because we want to make sure that Fedora uses everything from OpenSSL
|
||||
return __get_builtin_constructor(name)(data)
|
||||
|
||||
-
|
||||
try:
|
||||
import _hashlib
|
||||
new = __hash_new
|
||||
@@ -215,7 +245,10 @@
|
||||
# try them all, some may not work due to the OpenSSL
|
||||
# version not supporting that algorithm.
|
||||
try:
|
||||
- globals()[__func_name] = __get_hash(__func_name)
|
||||
+ func = __get_hash(__func_name)
|
||||
+ if 'sha3_' in __func_name:
|
||||
+ func = __ignore_usedforsecurity(func)
|
||||
+ globals()[__func_name] = func
|
||||
except ValueError:
|
||||
import logging
|
||||
logging.exception('code for hash %s was not found.', __func_name)
|
||||
@@ -223,3 +256,4 @@
|
||||
# Cleanup locals()
|
||||
del __always_supported, __func_name, __get_hash
|
||||
del __py_new, __hash_new, __get_openssl_constructor
|
||||
+del __ignore_usedforsecurity
|
||||
--- Lib/test/test_hashlib.py 2013-11-27 11:55:42.769601363 +0100
|
||||
+++ Lib/test/test_hashlib.py 2013-11-28 09:33:03.929008508 +0100
|
||||
@@ -24,7 +24,22 @@
|
||||
COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount')
|
||||
|
||||
c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib'])
|
||||
-py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
|
||||
+# skipped on Fedora, since we always use OpenSSL implementation
|
||||
+# py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
|
||||
+
|
||||
+def openssl_enforces_fips():
|
||||
+ # Use the "openssl" command (if present) to try to determine if the local
|
||||
+ # OpenSSL is configured to enforce FIPS
|
||||
+ from subprocess import Popen, PIPE
|
||||
+ try:
|
||||
+ p = Popen(['openssl', 'md5'],
|
||||
+ stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
||||
+ except OSError:
|
||||
+ # "openssl" command not found
|
||||
+ return False
|
||||
+ stdout, stderr = p.communicate(input=b'abc')
|
||||
+ return b'unknown cipher' in stderr
|
||||
+OPENSSL_ENFORCES_FIPS = openssl_enforces_fips()
|
||||
|
||||
def hexstr(s):
|
||||
assert isinstance(s, bytes), repr(s)
|
||||
@@ -34,6 +49,16 @@
|
||||
r += h[(i >> 4) & 0xF] + h[i & 0xF]
|
||||
return r
|
||||
|
||||
+# hashlib and _hashlib-based functions support a "usedforsecurity" keyword
|
||||
+# argument, and FIPS mode requires that it be used overridden with a False
|
||||
+# value for these selftests to work. Other cryptographic code within Python
|
||||
+# doesn't support this keyword.
|
||||
+# Modify a function to one in which "usedforsecurity=False" is added to the
|
||||
+# keyword arguments:
|
||||
+def suppress_fips(f):
|
||||
+ def g(*args, **kwargs):
|
||||
+ return f(*args, usedforsecurity=False, **kwargs)
|
||||
+ return g
|
||||
|
||||
class HashLibTestCase(unittest.TestCase):
|
||||
supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1',
|
||||
@@ -66,11 +91,11 @@
|
||||
# For each algorithm, test the direct constructor and the use
|
||||
# of hashlib.new given the algorithm name.
|
||||
for algorithm, constructors in self.constructors_to_test.items():
|
||||
- constructors.add(getattr(hashlib, algorithm))
|
||||
+ constructors.add(suppress_fips(getattr(hashlib, algorithm)))
|
||||
def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm):
|
||||
if data is None:
|
||||
- return hashlib.new(_alg)
|
||||
- return hashlib.new(_alg, data)
|
||||
+ return suppress_fips(hashlib.new)(_alg)
|
||||
+ return suppress_fips(hashlib.new)(_alg, data)
|
||||
constructors.add(_test_algorithm_via_hashlib_new)
|
||||
|
||||
_hashlib = self._conditional_import_module('_hashlib')
|
||||
@@ -82,26 +107,12 @@
|
||||
for algorithm, constructors in self.constructors_to_test.items():
|
||||
constructor = getattr(_hashlib, 'openssl_'+algorithm, None)
|
||||
if constructor:
|
||||
- constructors.add(constructor)
|
||||
+ constructors.add(suppress_fips(constructor))
|
||||
|
||||
def add_builtin_constructor(name):
|
||||
constructor = getattr(hashlib, "__get_builtin_constructor")(name)
|
||||
self.constructors_to_test[name].add(constructor)
|
||||
|
||||
- _md5 = self._conditional_import_module('_md5')
|
||||
- if _md5:
|
||||
- add_builtin_constructor('md5')
|
||||
- _sha1 = self._conditional_import_module('_sha1')
|
||||
- if _sha1:
|
||||
- add_builtin_constructor('sha1')
|
||||
- _sha256 = self._conditional_import_module('_sha256')
|
||||
- if _sha256:
|
||||
- add_builtin_constructor('sha224')
|
||||
- add_builtin_constructor('sha256')
|
||||
- _sha512 = self._conditional_import_module('_sha512')
|
||||
- if _sha512:
|
||||
- add_builtin_constructor('sha384')
|
||||
- add_builtin_constructor('sha512')
|
||||
|
||||
super(HashLibTestCase, self).__init__(*args, **kwargs)
|
||||
|
||||
@@ -157,9 +169,6 @@
|
||||
else:
|
||||
del sys.modules['_md5']
|
||||
self.assertRaises(TypeError, get_builtin_constructor, 3)
|
||||
- constructor = get_builtin_constructor('md5')
|
||||
- self.assertIs(constructor, _md5.md5)
|
||||
- self.assertEqual(sorted(builtin_constructor_cache), ['MD5', 'md5'])
|
||||
|
||||
def test_hexdigest(self):
|
||||
for cons in self.hash_constructors:
|
||||
@@ -558,6 +567,65 @@
|
||||
|
||||
self.assertEqual(expected_hash, hasher.hexdigest())
|
||||
|
||||
+ def test_issue9146(self):
|
||||
+ # Ensure that various ways to use "MD5" from "hashlib" don't segfault:
|
||||
+ m = hashlib.md5(usedforsecurity=False)
|
||||
+ m.update(b'abc\n')
|
||||
+ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
|
||||
+
|
||||
+ m = hashlib.new('md5', usedforsecurity=False)
|
||||
+ m.update(b'abc\n')
|
||||
+ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
|
||||
+
|
||||
+ m = hashlib.md5(b'abc\n', usedforsecurity=False)
|
||||
+ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
|
||||
+
|
||||
+ m = hashlib.new('md5', b'abc\n', usedforsecurity=False)
|
||||
+ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
|
||||
+
|
||||
+ @unittest.skipUnless(OPENSSL_ENFORCES_FIPS,
|
||||
+ 'FIPS enforcement required for this test.')
|
||||
+ def test_hashlib_fips_mode(self):
|
||||
+ # Ensure that we raise a ValueError on vanilla attempts to use MD5
|
||||
+ # in hashlib in a FIPS-enforced setting:
|
||||
+ with self.assertRaisesRegexp(ValueError, '.*unknown cipher'):
|
||||
+ m = hashlib.md5()
|
||||
+
|
||||
+ if not self._conditional_import_module('_md5'):
|
||||
+ with self.assertRaisesRegexp(ValueError, '.*unknown cipher'):
|
||||
+ m = hashlib.new('md5')
|
||||
+
|
||||
+ @unittest.skipUnless(OPENSSL_ENFORCES_FIPS,
|
||||
+ 'FIPS enforcement required for this test.')
|
||||
+ def test_hashopenssl_fips_mode(self):
|
||||
+ # Verify the _hashlib module's handling of md5:
|
||||
+ _hashlib = self._conditional_import_module('_hashlib')
|
||||
+ if _hashlib:
|
||||
+ assert hasattr(_hashlib, 'openssl_md5')
|
||||
+
|
||||
+ # Ensure that _hashlib raises a ValueError on vanilla attempts to
|
||||
+ # use MD5 in a FIPS-enforced setting:
|
||||
+ with self.assertRaisesRegexp(ValueError, '.*unknown cipher'):
|
||||
+ m = _hashlib.openssl_md5()
|
||||
+ with self.assertRaisesRegexp(ValueError, '.*unknown cipher'):
|
||||
+ m = _hashlib.new('md5')
|
||||
+
|
||||
+ # Ensure that in such a setting we can whitelist a callsite with
|
||||
+ # usedforsecurity=False and have it succeed:
|
||||
+ m = _hashlib.openssl_md5(usedforsecurity=False)
|
||||
+ m.update(b'abc\n')
|
||||
+ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
|
||||
+
|
||||
+ m = _hashlib.new('md5', usedforsecurity=False)
|
||||
+ m.update(b'abc\n')
|
||||
+ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
|
||||
+
|
||||
+ m = _hashlib.openssl_md5(b'abc\n', usedforsecurity=False)
|
||||
+ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
|
||||
+
|
||||
+ m = _hashlib.new('md5', b'abc\n', usedforsecurity=False)
|
||||
+ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1")
|
||||
+
|
||||
|
||||
class KDFTests(unittest.TestCase):
|
||||
|
||||
@@ -639,6 +707,7 @@
|
||||
with self.assertRaisesRegex(ValueError, 'unsupported hash type'):
|
||||
pbkdf2('unknown', b'pass', b'salt', 1)
|
||||
|
||||
+ @unittest.skip('skipped on Fedora, as we always use OpenSSL pbkdf2_hmac')
|
||||
def test_pbkdf2_hmac_py(self):
|
||||
self._test_pbkdf2_hmac(py_hashlib.pbkdf2_hmac)
|
||||
|
||||
--- Modules/_hashopenssl.c.hashlib-fips 2013-11-24 21:36:56.000000000 +0100
|
||||
+++ Modules/_hashopenssl.c 2013-11-27 12:01:57.443537463 +0100
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
|
||||
/* EVP is the preferred interface to hashing in OpenSSL */
|
||||
+#include <openssl/ssl.h>
|
||||
+#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
/* We use the object interface to discover what hashes OpenSSL supports. */
|
||||
@@ -48,11 +50,19 @@
|
||||
|
||||
static PyTypeObject EVPtype;
|
||||
|
||||
+/* Struct to hold all the cached information we need on a specific algorithm.
|
||||
+ We have one of these per algorithm */
|
||||
+typedef struct {
|
||||
+ PyObject *name_obj;
|
||||
+ EVP_MD_CTX ctxs[2];
|
||||
+ /* ctx_ptrs will point to ctxs unless an error occurred, when it will
|
||||
+ be NULL: */
|
||||
+ EVP_MD_CTX *ctx_ptrs[2];
|
||||
+ PyObject *error_msgs[2];
|
||||
+} EVPCachedInfo;
|
||||
|
||||
-#define DEFINE_CONSTS_FOR_NEW(Name) \
|
||||
- static PyObject *CONST_ ## Name ## _name_obj = NULL; \
|
||||
- static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \
|
||||
- static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL;
|
||||
+#define DEFINE_CONSTS_FOR_NEW(Name) \
|
||||
+ static EVPCachedInfo cached_info_ ##Name;
|
||||
|
||||
DEFINE_CONSTS_FOR_NEW(md5)
|
||||
DEFINE_CONSTS_FOR_NEW(sha1)
|
||||
@@ -97,6 +107,48 @@
|
||||
}
|
||||
}
|
||||
|
||||
+static void
|
||||
+mc_ctx_init(EVP_MD_CTX *ctx, int usedforsecurity)
|
||||
+{
|
||||
+ EVP_MD_CTX_init(ctx);
|
||||
+
|
||||
+ /*
|
||||
+ If the user has declared that this digest is being used in a
|
||||
+ non-security role (e.g. indexing into a data structure), set
|
||||
+ the exception flag for openssl to allow it
|
||||
+ */
|
||||
+ if (!usedforsecurity) {
|
||||
+#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
|
||||
+ EVP_MD_CTX_set_flags(ctx,
|
||||
+ EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
|
||||
+#endif
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Get an error msg for the last error as a PyObject */
|
||||
+static PyObject *
|
||||
+error_msg_for_last_error(void)
|
||||
+{
|
||||
+ char *errstr;
|
||||
+
|
||||
+ errstr = ERR_error_string(ERR_peek_last_error(), NULL);
|
||||
+ ERR_clear_error();
|
||||
+
|
||||
+ return PyUnicode_FromString(errstr); /* Can be NULL */
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+set_evp_exception(void)
|
||||
+{
|
||||
+ char *errstr;
|
||||
+
|
||||
+ errstr = ERR_error_string(ERR_peek_last_error(), NULL);
|
||||
+ ERR_clear_error();
|
||||
+
|
||||
+ PyErr_SetString(PyExc_ValueError, errstr);
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* Internal methods for a hash object */
|
||||
|
||||
static void
|
||||
@@ -281,15 +333,16 @@
|
||||
static int
|
||||
EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
- static char *kwlist[] = {"name", "string", NULL};
|
||||
+ static char *kwlist[] = {"name", "string", "usedforsecurity", NULL};
|
||||
PyObject *name_obj = NULL;
|
||||
PyObject *data_obj = NULL;
|
||||
+ int usedforsecurity = 1;
|
||||
Py_buffer view;
|
||||
char *nameStr;
|
||||
const EVP_MD *digest;
|
||||
|
||||
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:HASH", kwlist,
|
||||
- &name_obj, &data_obj)) {
|
||||
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:HASH", kwlist,
|
||||
+ &name_obj, &data_obj, &usedforsecurity)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -310,7 +363,12 @@
|
||||
PyBuffer_Release(&view);
|
||||
return -1;
|
||||
}
|
||||
- EVP_DigestInit(&self->ctx, digest);
|
||||
+ mc_ctx_init(&self->ctx, usedforsecurity);
|
||||
+ if (!EVP_DigestInit_ex(&self->ctx, digest, NULL)) {
|
||||
+ set_evp_exception();
|
||||
+ PyBuffer_Release(&view);
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
self->name = name_obj;
|
||||
Py_INCREF(self->name);
|
||||
@@ -394,7 +452,8 @@
|
||||
static PyObject *
|
||||
EVPnew(PyObject *name_obj,
|
||||
const EVP_MD *digest, const EVP_MD_CTX *initial_ctx,
|
||||
- const unsigned char *cp, Py_ssize_t len)
|
||||
+ const unsigned char *cp, Py_ssize_t len,
|
||||
+ int usedforsecurity)
|
||||
{
|
||||
EVPobject *self;
|
||||
|
||||
@@ -409,7 +468,12 @@
|
||||
if (initial_ctx) {
|
||||
EVP_MD_CTX_copy(&self->ctx, initial_ctx);
|
||||
} else {
|
||||
- EVP_DigestInit(&self->ctx, digest);
|
||||
+ mc_ctx_init(&self->ctx, usedforsecurity);
|
||||
+ if (!EVP_DigestInit_ex(&self->ctx, digest, NULL)) {
|
||||
+ set_evp_exception();
|
||||
+ Py_DECREF(self);
|
||||
+ return NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (cp && len) {
|
||||
@@ -433,21 +497,29 @@
|
||||
An optional string argument may be provided and will be\n\
|
||||
automatically hashed.\n\
|
||||
\n\
|
||||
-The MD5 and SHA1 algorithms are always supported.\n");
|
||||
+The MD5 and SHA1 algorithms are always supported.\n\
|
||||
+\n\
|
||||
+An optional \"usedforsecurity=True\" keyword argument is provided for use in\n\
|
||||
+environments that enforce FIPS-based restrictions. Some implementations of\n\
|
||||
+OpenSSL can be configured to prevent the usage of non-secure algorithms (such\n\
|
||||
+as MD5). If you have a non-security use for these algorithms (e.g. a hash\n\
|
||||
+table), you can override this argument by marking the callsite as\n\
|
||||
+\"usedforsecurity=False\".");
|
||||
|
||||
static PyObject *
|
||||
EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
|
||||
{
|
||||
- static char *kwlist[] = {"name", "string", NULL};
|
||||
+ static char *kwlist[] = {"name", "string", "usedforsecurity", NULL};
|
||||
PyObject *name_obj = NULL;
|
||||
PyObject *data_obj = NULL;
|
||||
+ int usedforsecurity = 1;
|
||||
Py_buffer view = { 0 };
|
||||
PyObject *ret_obj;
|
||||
char *name;
|
||||
const EVP_MD *digest;
|
||||
|
||||
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|O:new", kwlist,
|
||||
- &name_obj, &data_obj)) {
|
||||
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|Oi:new", kwlist,
|
||||
+ &name_obj, &data_obj, &usedforsecurity)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -461,7 +533,8 @@
|
||||
|
||||
digest = EVP_get_digestbyname(name);
|
||||
|
||||
- ret_obj = EVPnew(name_obj, digest, NULL, (unsigned char*)view.buf, view.len);
|
||||
+ ret_obj = EVPnew(name_obj, digest, NULL, (unsigned char*)view.buf, view.len,
|
||||
+ usedforsecurity);
|
||||
|
||||
if (data_obj)
|
||||
PyBuffer_Release(&view);
|
||||
@@ -742,57 +815,115 @@
|
||||
|
||||
|
||||
/*
|
||||
- * This macro generates constructor function definitions for specific
|
||||
- * hash algorithms. These constructors are much faster than calling
|
||||
- * the generic one passing it a python string and are noticably
|
||||
- * faster than calling a python new() wrapper. Thats important for
|
||||
+ * This macro and function generates a family of constructor function
|
||||
+ * definitions for specific hash algorithms. These constructors are much
|
||||
+ * faster than calling the generic one passing it a python string and are
|
||||
+ * noticably faster than calling a python new() wrapper. That's important for
|
||||
* code that wants to make hashes of a bunch of small strings.
|
||||
*/
|
||||
#define GEN_CONSTRUCTOR(NAME) \
|
||||
static PyObject * \
|
||||
- EVP_new_ ## NAME (PyObject *self, PyObject *args) \
|
||||
+ EVP_new_ ## NAME (PyObject *self, PyObject *args, PyObject *kwdict) \
|
||||
{ \
|
||||
- PyObject *data_obj = NULL; \
|
||||
- Py_buffer view = { 0 }; \
|
||||
- PyObject *ret_obj; \
|
||||
- \
|
||||
- if (!PyArg_ParseTuple(args, "|O:" #NAME , &data_obj)) { \
|
||||
- return NULL; \
|
||||
- } \
|
||||
- \
|
||||
- if (data_obj) \
|
||||
- GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); \
|
||||
- \
|
||||
- ret_obj = EVPnew( \
|
||||
- CONST_ ## NAME ## _name_obj, \
|
||||
- NULL, \
|
||||
- CONST_new_ ## NAME ## _ctx_p, \
|
||||
- (unsigned char*)view.buf, \
|
||||
- view.len); \
|
||||
- \
|
||||
- if (data_obj) \
|
||||
- PyBuffer_Release(&view); \
|
||||
- return ret_obj; \
|
||||
+ return implement_specific_EVP_new(self, args, kwdict, \
|
||||
+ "|Oi:" #NAME, \
|
||||
+ &cached_info_ ## NAME ); \
|
||||
+ }
|
||||
+
|
||||
+static PyObject *
|
||||
+implement_specific_EVP_new(PyObject *self, PyObject *args, PyObject *kwdict,
|
||||
+ const char *format,
|
||||
+ EVPCachedInfo *cached_info)
|
||||
+{
|
||||
+ static char *kwlist[] = {"string", "usedforsecurity", NULL};
|
||||
+ PyObject *data_obj = NULL;
|
||||
+ Py_buffer view = { 0 };
|
||||
+ int usedforsecurity = 1;
|
||||
+ int idx;
|
||||
+ PyObject *ret_obj = NULL;
|
||||
+
|
||||
+ assert(cached_info);
|
||||
+
|
||||
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, format, kwlist,
|
||||
+ &data_obj, &usedforsecurity)) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (data_obj)
|
||||
+ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view);
|
||||
+
|
||||
+ idx = usedforsecurity ? 1 : 0;
|
||||
+
|
||||
+ /*
|
||||
+ * If an error occurred during creation of the global content, the ctx_ptr
|
||||
+ * will be NULL, and the error_msg will hopefully be non-NULL:
|
||||
+ */
|
||||
+ if (cached_info->ctx_ptrs[idx]) {
|
||||
+ /* We successfully initialized this context; copy it: */
|
||||
+ ret_obj = EVPnew(cached_info->name_obj,
|
||||
+ NULL,
|
||||
+ cached_info->ctx_ptrs[idx],
|
||||
+ (unsigned char*)view.buf, view.len,
|
||||
+ usedforsecurity);
|
||||
+ } else {
|
||||
+ /* Some kind of error happened initializing the global context for
|
||||
+ this (digest, usedforsecurity) pair.
|
||||
+ Raise an exception with the saved error message: */
|
||||
+ if (cached_info->error_msgs[idx]) {
|
||||
+ PyErr_SetObject(PyExc_ValueError, cached_info->error_msgs[idx]);
|
||||
+ } else {
|
||||
+ PyErr_SetString(PyExc_ValueError, "Error initializing hash");
|
||||
+ }
|
||||
}
|
||||
|
||||
+ if (data_obj)
|
||||
+ PyBuffer_Release(&view);
|
||||
+
|
||||
+ return ret_obj;
|
||||
+}
|
||||
+
|
||||
/* a PyMethodDef structure for the constructor */
|
||||
#define CONSTRUCTOR_METH_DEF(NAME) \
|
||||
- {"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, METH_VARARGS, \
|
||||
+ {"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, \
|
||||
+ METH_VARARGS|METH_KEYWORDS, \
|
||||
PyDoc_STR("Returns a " #NAME \
|
||||
" hash object; optionally initialized with a string") \
|
||||
}
|
||||
|
||||
-/* used in the init function to setup a constructor: initialize OpenSSL
|
||||
- constructor constants if they haven't been initialized already. */
|
||||
-#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \
|
||||
- if (CONST_ ## NAME ## _name_obj == NULL) { \
|
||||
- CONST_ ## NAME ## _name_obj = PyUnicode_FromString(#NAME); \
|
||||
- if (EVP_get_digestbyname(#NAME)) { \
|
||||
- CONST_new_ ## NAME ## _ctx_p = &CONST_new_ ## NAME ## _ctx; \
|
||||
- EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
|
||||
- } \
|
||||
- } \
|
||||
+/*
|
||||
+ Macro/function pair to set up the constructors.
|
||||
+
|
||||
+ Try to initialize a context for each hash twice, once with
|
||||
+ EVP_MD_CTX_FLAG_NON_FIPS_ALLOW and once without.
|
||||
+
|
||||
+ Any that have errors during initialization will end up with a NULL ctx_ptrs
|
||||
+ entry, and err_msgs will be set (unless we're very low on memory)
|
||||
+*/
|
||||
+#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \
|
||||
+ init_constructor_constant(&cached_info_ ## NAME, #NAME); \
|
||||
} while (0);
|
||||
+static void
|
||||
+init_constructor_constant(EVPCachedInfo *cached_info, const char *name)
|
||||
+{
|
||||
+ assert(cached_info);
|
||||
+ cached_info->name_obj = PyUnicode_FromString(name);
|
||||
+ if (EVP_get_digestbyname(name)) {
|
||||
+ int i;
|
||||
+ for (i=0; i<2; i++) {
|
||||
+ mc_ctx_init(&cached_info->ctxs[i], i);
|
||||
+ if (EVP_DigestInit_ex(&cached_info->ctxs[i],
|
||||
+ EVP_get_digestbyname(name), NULL)) {
|
||||
+ /* Success: */
|
||||
+ cached_info->ctx_ptrs[i] = &cached_info->ctxs[i];
|
||||
+ } else {
|
||||
+ /* Failure: */
|
||||
+ cached_info->ctx_ptrs[i] = NULL;
|
||||
+ cached_info->error_msgs[i] = error_msg_for_last_error();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
|
||||
GEN_CONSTRUCTOR(md5)
|
||||
GEN_CONSTRUCTOR(sha1)
|
||||
@@ -843,13 +974,10 @@
|
||||
{
|
||||
PyObject *m, *openssl_md_meth_names;
|
||||
|
||||
- OpenSSL_add_all_digests();
|
||||
- ERR_load_crypto_strings();
|
||||
+ SSL_load_error_strings();
|
||||
+ SSL_library_init();
|
||||
|
||||
- /* TODO build EVP_functions openssl_* entries dynamically based
|
||||
- * on what hashes are supported rather than listing many
|
||||
- * but having some be unsupported. Only init appropriate
|
||||
- * constants. */
|
||||
+ OpenSSL_add_all_digests();
|
||||
|
||||
Py_TYPE(&EVPtype) = &PyType_Type;
|
||||
if (PyType_Ready(&EVPtype) < 0)
|
||||
15
lang/python34/files/patch-Lib__distutils__unixccompiler.py
Normal file
15
lang/python34/files/patch-Lib__distutils__unixccompiler.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# Description: Some python extensions can't be compiled with clang 3.4
|
||||
# Issue ID: http://bugs.python.org/issue20767
|
||||
# Submitted by: antoine
|
||||
|
||||
--- ./Lib/distutils/unixccompiler.py.orig 2014-03-09 15:25:15.921204441 +1100
|
||||
+++ ./Lib/distutils/unixccompiler.py 2014-03-09 15:25:50.643809649 +1100
|
||||
@@ -225,6 +225,8 @@
|
||||
if sys.platform[:6] == "darwin":
|
||||
# MacOSX's linker doesn't understand the -R flag at all
|
||||
return "-L" + dir
|
||||
+ elif sys.platform[:7] == "freebsd":
|
||||
+ return "-Wl,-rpath=" + dir
|
||||
elif sys.platform[:5] == "hp-ux":
|
||||
if self._is_gcc(compiler):
|
||||
return ["-Wl,+s", "-L" + dir]
|
||||
63
lang/python34/files/patch-Makefile.pre.in
Normal file
63
lang/python34/files/patch-Makefile.pre.in
Normal file
@@ -0,0 +1,63 @@
|
||||
# Description: Remove duplicate CFLAGS, CPPFLAGS, LDFLAGS by stripping CONFIGURE_*
|
||||
# Submitted by: koobs (r326729)
|
||||
# TODO: Upstream
|
||||
|
||||
# Description: Create symlinks for non-ABI-suffixed python*-config and ABI-suffixed python-*.pc
|
||||
# Submitted by: antoine@ (r358029)
|
||||
# TODO: Upstream
|
||||
|
||||
--- Makefile.pre.in.orig 2014-10-08 12:18:14.000000000 +0400
|
||||
+++ Makefile.pre.in 2014-10-19 12:37:14.000000000 +0400
|
||||
@@ -70,23 +70,20 @@
|
||||
OPT= @OPT@
|
||||
BASECFLAGS= @BASECFLAGS@
|
||||
BASECPPFLAGS= @BASECPPFLAGS@
|
||||
-CONFIGURE_CFLAGS= @CFLAGS@
|
||||
# CFLAGS_NODIST is used for building the interpreter and stdlib C extensions.
|
||||
# Use it when a compiler flag should _not_ be part of the distutils CFLAGS
|
||||
# once Python is installed (Issue #21121).
|
||||
CONFIGURE_CFLAGS_NODIST=@CFLAGS_NODIST@
|
||||
-CONFIGURE_CPPFLAGS= @CPPFLAGS@
|
||||
-CONFIGURE_LDFLAGS= @LDFLAGS@
|
||||
# Avoid assigning CFLAGS, LDFLAGS, etc. so users can use them on the
|
||||
# command line to append to these values without stomping the pre-set
|
||||
# values.
|
||||
-PY_CFLAGS= $(BASECFLAGS) $(OPT) $(CONFIGURE_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS)
|
||||
+PY_CFLAGS= $(BASECFLAGS) $(OPT) $(CFLAGS) $(EXTRA_CFLAGS)
|
||||
PY_CFLAGS_NODIST=$(CONFIGURE_CFLAGS_NODIST) $(CFLAGS_NODIST)
|
||||
# Both CPPFLAGS and LDFLAGS need to contain the shell's value for setup.py to
|
||||
# be able to build extension modules using the directories specified in the
|
||||
# environment variables
|
||||
-PY_CPPFLAGS= $(BASECPPFLAGS) -I. -IInclude -I$(srcdir)/Include $(CONFIGURE_CPPFLAGS) $(CPPFLAGS)
|
||||
-PY_LDFLAGS= $(CONFIGURE_LDFLAGS) $(LDFLAGS)
|
||||
+PY_CPPFLAGS= $(BASECPPFLAGS) -I. -IInclude -I$(srcdir)/Include $(CPPFLAGS)
|
||||
+PY_LDFLAGS= $(LDFLAGS)
|
||||
NO_AS_NEEDED= @NO_AS_NEEDED@
|
||||
LDLAST= @LDLAST@
|
||||
SGI_ABI= @SGI_ABI@
|
||||
@@ -1080,12 +1077,6 @@
|
||||
else true; \
|
||||
fi
|
||||
(cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)$(EXE) python3$(EXE))
|
||||
- -if test "$(VERSION)" != "$(LDVERSION)"; then \
|
||||
- rm -f $(DESTDIR)$(BINDIR)/python$(VERSION)-config; \
|
||||
- (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(LDVERSION)-config python$(VERSION)-config); \
|
||||
- rm -f $(DESTDIR)$(LIBPC)/python-$(LDVERSION).pc; \
|
||||
- (cd $(DESTDIR)$(LIBPC); $(LN) -s python-$(VERSION).pc python-$(LDVERSION).pc); \
|
||||
- fi
|
||||
-rm -f $(DESTDIR)$(BINDIR)/python3-config
|
||||
(cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)-config python3-config)
|
||||
-rm -f $(DESTDIR)$(LIBPC)/python3.pc
|
||||
@@ -1348,6 +1339,12 @@
|
||||
$(INSTALL_SCRIPT) $(srcdir)/install-sh $(DESTDIR)$(LIBPL)/install-sh
|
||||
$(INSTALL_SCRIPT) python-config.py $(DESTDIR)$(LIBPL)/python-config.py
|
||||
$(INSTALL_SCRIPT) python-config $(DESTDIR)$(BINDIR)/python$(LDVERSION)-config
|
||||
+ -if test "$(VERSION)" != "$(LDVERSION)"; then \
|
||||
+ rm -f $(DESTDIR)$(BINDIR)/python$(VERSION)-config; \
|
||||
+ (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(LDVERSION)-config python$(VERSION)-config); \
|
||||
+ rm -f $(DESTDIR)$(LIBPC)/python-$(LDVERSION).pc; \
|
||||
+ (cd $(DESTDIR)$(LIBPC); $(LN) -s python-$(VERSION).pc python-$(LDVERSION).pc); \
|
||||
+ fi
|
||||
@if [ -s Modules/python.exp -a \
|
||||
"`echo $(MACHDEP) | sed 's/^\(...\).*/\1/'`" = "aix" ]; then \
|
||||
echo; echo "Installing support files for building shared extension modules on AIX:"; \
|
||||
11
lang/python34/files/patch-Modules-_ctypes-libffi-configure
Normal file
11
lang/python34/files/patch-Modules-_ctypes-libffi-configure
Normal file
@@ -0,0 +1,11 @@
|
||||
--- Modules/_ctypes/libffi/configure.orig 2014-10-08 12:18:14.000000000 +0400
|
||||
+++ Modules/_ctypes/libffi/configure 2014-10-19 12:39:11.000000000 +0400
|
||||
@@ -7526,7 +7526,7 @@
|
||||
rm -rf conftest*
|
||||
;;
|
||||
|
||||
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
|
||||
+amd64-*-freebsd*|x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
|
||||
s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
|
||||
# Find out what ABI is being produced by ac_compile, and set linker
|
||||
# options accordingly. Note that the listed cases only cover the
|
||||
@@ -0,0 +1,36 @@
|
||||
# Description: Fix _ctypes abort on import for FreeBSD/ARM. This is an issue
|
||||
# for anything !apple that is using the libcompiler_rt provided by clang on arm
|
||||
# PR: ports/149167 ports/184517
|
||||
# Patch by: cognet@ (to be upstreamed @ LLVM)
|
||||
|
||||
--- ./Modules/_ctypes/libffi/src/arm/ffi.c.orig 2013-11-17 18:22:57.000000000 +1100
|
||||
+++ ./Modules/_ctypes/libffi/src/arm/ffi.c 2013-12-03 19:23:24.521993369 +1100
|
||||
@@ -33,6 +33,11 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
+#if defined(__FreeBSD__) && defined(__arm__)
|
||||
+#include <sys/types.h>
|
||||
+#include <machine/sysarch.h>
|
||||
+#endif
|
||||
+
|
||||
/* Forward declares. */
|
||||
static int vfp_type_p (ffi_type *);
|
||||
static void layout_vfp_args (ffi_cif *);
|
||||
@@ -582,6 +587,16 @@
|
||||
|
||||
#else
|
||||
|
||||
+#if defined(__FreeBSD__) && defined(__arm__)
|
||||
+#define __clear_cache(start, end) do { \
|
||||
+ struct arm_sync_icache_args ua; \
|
||||
+ \
|
||||
+ ua.addr = (uintptr_t)(start); \
|
||||
+ ua.len = (char *)(end) - (char *)start; \
|
||||
+ sysarch(ARM_SYNC_ICACHE, &ua); \
|
||||
+ } while (0);
|
||||
+#endif
|
||||
+
|
||||
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
|
||||
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
unsigned int __fun = (unsigned int)(FUN); \
|
||||
53
lang/python34/files/patch-Modules__fcntlmodule.c
Normal file
53
lang/python34/files/patch-Modules__fcntlmodule.c
Normal file
@@ -0,0 +1,53 @@
|
||||
--- ./Modules/fcntlmodule.c.orig 2014-03-04 20:15:17.641117835 +1100
|
||||
+++ ./Modules/fcntlmodule.c 2014-03-04 20:19:36.141145958 +1100
|
||||
@@ -98,20 +98,15 @@
|
||||
{
|
||||
#define IOCTL_BUFSZ 1024
|
||||
int fd;
|
||||
- /* In PyArg_ParseTuple below, we use the unsigned non-checked 'I'
|
||||
+ /* In PyArg_ParseTuple below, we use the unsigned non-checked 'k'
|
||||
format for the 'code' parameter because Python turns 0x8000000
|
||||
into either a large positive number (PyLong or PyInt on 64-bit
|
||||
platforms) or a negative number on others (32-bit PyInt)
|
||||
whereas the system expects it to be a 32bit bit field value
|
||||
regardless of it being passed as an int or unsigned long on
|
||||
- various platforms. See the termios.TIOCSWINSZ constant across
|
||||
- platforms for an example of this.
|
||||
-
|
||||
- If any of the 64bit platforms ever decide to use more than 32bits
|
||||
- in their unsigned long ioctl codes this will break and need
|
||||
- special casing based on the platform being built on.
|
||||
+ various platforms.
|
||||
*/
|
||||
- unsigned int code;
|
||||
+ unsigned long code;
|
||||
int arg;
|
||||
int ret;
|
||||
Py_buffer pstr;
|
||||
@@ -120,7 +115,7 @@
|
||||
int mutate_arg = 1;
|
||||
char buf[IOCTL_BUFSZ+1]; /* argument plus NUL byte */
|
||||
|
||||
- if (PyArg_ParseTuple(args, "O&Iw*|i:ioctl",
|
||||
+ if (PyArg_ParseTuple(args, "O&kw*|i:ioctl",
|
||||
conv_descriptor, &fd, &code,
|
||||
&pstr, &mutate_arg)) {
|
||||
char *arg;
|
||||
@@ -175,7 +170,7 @@
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
- if (PyArg_ParseTuple(args, "O&Is*:ioctl",
|
||||
+ if (PyArg_ParseTuple(args, "O&ks*:ioctl",
|
||||
conv_descriptor, &fd, &code, &pstr)) {
|
||||
str = pstr.buf;
|
||||
len = pstr.len;
|
||||
@@ -202,7 +197,7 @@
|
||||
PyErr_Clear();
|
||||
arg = 0;
|
||||
if (!PyArg_ParseTuple(args,
|
||||
- "O&I|i;ioctl requires a file or file descriptor,"
|
||||
+ "O&k|i;ioctl requires a file or file descriptor,"
|
||||
" an integer and optionally an integer or buffer argument",
|
||||
conv_descriptor, &fd, &code, &arg)) {
|
||||
return NULL;
|
||||
23
lang/python34/files/patch-issue24557
Normal file
23
lang/python34/files/patch-issue24557
Normal file
@@ -0,0 +1,23 @@
|
||||
https://bugs.python.org/issue24557
|
||||
assume egd unless OPENSSL_NO_EGD is defined-remove configure check
|
||||
|
||||
--- Modules/_ssl.c.orig 2016-06-25 21:52:32 UTC
|
||||
+++ Modules/_ssl.c
|
||||
@@ -3325,7 +3325,7 @@ Returns 1 if the OpenSSL PRNG has been s
|
||||
It is necessary to seed the PRNG with RAND_add() on some platforms before\n\
|
||||
using the ssl() function.");
|
||||
|
||||
-#ifdef HAVE_RAND_EGD
|
||||
+#ifndef OPENSSL_NO_EGD
|
||||
static PyObject *
|
||||
PySSL_RAND_egd(PyObject *self, PyObject *args)
|
||||
{
|
||||
@@ -3753,7 +3753,7 @@ static PyMethodDef PySSL_methods[] = {
|
||||
PySSL_RAND_bytes_doc},
|
||||
{"RAND_pseudo_bytes", PySSL_RAND_pseudo_bytes, METH_VARARGS,
|
||||
PySSL_RAND_pseudo_bytes_doc},
|
||||
-#ifdef HAVE_RAND_EGD
|
||||
+#ifndef OPENSSL_NO_EGD
|
||||
{"RAND_egd", PySSL_RAND_egd, METH_VARARGS,
|
||||
PySSL_RAND_egd_doc},
|
||||
#endif
|
||||
118
lang/python34/files/patch-issue30622
Normal file
118
lang/python34/files/patch-issue30622
Normal file
@@ -0,0 +1,118 @@
|
||||
From b2d096bd2a5ff86e53c25d00ee5fa097b36bf1d8 Mon Sep 17 00:00:00 2001
|
||||
From: Melvyn Sopacua <melvyn-sopacua@users.noreply.github.com>
|
||||
Date: Mon, 4 Sep 2017 23:35:15 +0200
|
||||
Subject: [PATCH] bpo-30622: Change NPN detection: (#2079)
|
||||
|
||||
* Change NPN detection:
|
||||
|
||||
Version breakdown, support disabled (pre-patch/post-patch):
|
||||
- pre-1.0.1: OPENSSL_NPN_NEGOTIATED will not be defined -> False/False
|
||||
- 1.0.1 and 1.0.2: OPENSSL_NPN_NEGOTIATED will not be defined ->
|
||||
False/False
|
||||
- 1.1.0+: OPENSSL_NPN_NEGOTIATED will be defined and
|
||||
OPENSSL_NO_NEXTPROTONEG will be defined -> True/False
|
||||
|
||||
Version breakdown support enabled (pre-patch/post-patch):
|
||||
- pre-1.0.1: OPENSSL_NPN_NEGOTIATED will not be defined -> False/False
|
||||
- 1.0.1 and 1.0.2: OPENSSL_NPN_NEGOTIATED will be defined and
|
||||
OPENSSL_NO_NEXTPROTONEG will not be defined -> True/True
|
||||
- 1.1.0+: OPENSSL_NPN_NEGOTIATED will be defined and
|
||||
OPENSSL_NO_NEXTPROTONEG will not be defined -> True/True
|
||||
|
||||
* Refine NPN guard:
|
||||
|
||||
- If NPN is disabled, but ALPN is available we need our callback
|
||||
- Make clinic's ssl behave the same way
|
||||
|
||||
This created a working ssl module for me, with NPN disabled and ALPN
|
||||
enabled for OpenSSL 1.1.0f.
|
||||
|
||||
Concerns to address:
|
||||
The initial commit for NPN support into OpenSSL [1], had the
|
||||
OPENSSL_NPN_* variables defined inside the OPENSSL_NO_NEXTPROTONEG
|
||||
guard. The question is if that ever made it into a release.
|
||||
This would need an ugly hack, something like:
|
||||
|
||||
#if defined(OPENSSL_NO_NEXTPROTONEG) && \
|
||||
!defined(OPENSSL_NPN_NEGOTIATED)
|
||||
# define OPENSSL_NPN_UNSUPPORTED 0
|
||||
# define OPENSSL_NPN_NEGOTIATED 1
|
||||
# define OPENSSL_NPN_NO_OVERLAP 2
|
||||
#endif
|
||||
|
||||
[1] https://github.com/openssl/openssl/commit/68b33cc5c7
|
||||
|
||||
--- Modules/_ssl.c.orig 2018-02-04 23:40:38 UTC
|
||||
+++ Modules/_ssl.c
|
||||
@@ -207,7 +207,7 @@ static unsigned int _ssl_locks_count = 0
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
SSL_CTX *ctx;
|
||||
-#ifdef OPENSSL_NPN_NEGOTIATED
|
||||
+#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
char *npn_protocols;
|
||||
int npn_protocols_len;
|
||||
#endif
|
||||
@@ -1403,7 +1403,7 @@ static PyObject *PySSL_cipher (PySSLSock
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-#ifdef OPENSSL_NPN_NEGOTIATED
|
||||
+#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
static PyObject *PySSL_selected_npn_protocol(PySSLSocket *self) {
|
||||
const unsigned char *out;
|
||||
unsigned int outlen;
|
||||
@@ -1920,7 +1920,7 @@ static PyMethodDef PySSLMethods[] = {
|
||||
{"peer_certificate", (PyCFunction)PySSL_peercert, METH_VARARGS,
|
||||
PySSL_peercert_doc},
|
||||
{"cipher", (PyCFunction)PySSL_cipher, METH_NOARGS},
|
||||
-#ifdef OPENSSL_NPN_NEGOTIATED
|
||||
+#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
{"selected_npn_protocol", (PyCFunction)PySSL_selected_npn_protocol, METH_NOARGS},
|
||||
#endif
|
||||
{"compression", (PyCFunction)PySSL_compression, METH_NOARGS},
|
||||
@@ -2027,7 +2027,7 @@ context_new(PyTypeObject *type, PyObject
|
||||
return NULL;
|
||||
}
|
||||
self->ctx = ctx;
|
||||
-#ifdef OPENSSL_NPN_NEGOTIATED
|
||||
+#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
self->npn_protocols = NULL;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
@@ -2099,7 +2099,7 @@ context_dealloc(PySSLContext *self)
|
||||
{
|
||||
context_clear(self);
|
||||
SSL_CTX_free(self->ctx);
|
||||
-#ifdef OPENSSL_NPN_NEGOTIATED
|
||||
+#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
PyMem_Free(self->npn_protocols);
|
||||
#endif
|
||||
Py_TYPE(self)->tp_free(self);
|
||||
@@ -2126,7 +2126,7 @@ set_ciphers(PySSLContext *self, PyObject
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
-#ifdef OPENSSL_NPN_NEGOTIATED
|
||||
+#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
/* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */
|
||||
static int
|
||||
_advertiseNPN_cb(SSL *s,
|
||||
@@ -2175,7 +2175,7 @@ _selectNPN_cb(SSL *s,
|
||||
static PyObject *
|
||||
_set_npn_protocols(PySSLContext *self, PyObject *args)
|
||||
{
|
||||
-#ifdef OPENSSL_NPN_NEGOTIATED
|
||||
+#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
Py_buffer protos;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "y*:set_npn_protocols", &protos))
|
||||
@@ -4130,7 +4130,7 @@ PyInit__ssl(void)
|
||||
Py_INCREF(r);
|
||||
PyModule_AddObject(m, "HAS_ECDH", r);
|
||||
|
||||
-#ifdef OPENSSL_NPN_NEGOTIATED
|
||||
+#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
r = Py_True;
|
||||
#else
|
||||
r = Py_False;
|
||||
@@ -0,0 +1,23 @@
|
||||
--- ./Lib/test/test_asyncio/test_events.py.orig 2019-03-18 18:51:26.000000000 +0200
|
||||
+++ ./Lib/test/test_asyncio/test_events.py 2019-12-25 16:22:07.715598000 +0200
|
||||
@@ -33,6 +33,12 @@
|
||||
from asyncio import test_support as support
|
||||
|
||||
|
||||
+if ssl is not None:
|
||||
+ IS_OPENSSL_1_1_1 = ssl.OPENSSL_VERSION_INFO >= (1, 1, 1)
|
||||
+else:
|
||||
+ IS_OPENSSL_1_1_1 = False
|
||||
+
|
||||
+
|
||||
def data_file(filename):
|
||||
if hasattr(support, 'TEST_HOME_DIR'):
|
||||
fullname = os.path.join(support.TEST_HOME_DIR, filename)
|
||||
@@ -1049,6 +1055,7 @@
|
||||
self.test_create_unix_server_ssl_verify_failed()
|
||||
|
||||
@unittest.skipIf(ssl is None, 'No ssl module')
|
||||
+ @unittest.skipIf(IS_OPENSSL_1_1_1, "bpo-36576: fail on OpenSSL 1.1.1")
|
||||
def test_create_server_ssl_match_failed(self):
|
||||
proto = MyProto(loop=self.loop)
|
||||
server, host, port = self._make_ssl_server(
|
||||
290
lang/python34/files/patch-x-Modules-_hashopenssl_0.c
Normal file
290
lang/python34/files/patch-x-Modules-_hashopenssl_0.c
Normal file
@@ -0,0 +1,290 @@
|
||||
--- ./Modules/_hashopenssl.c.orig 2019-03-18 18:51:26.000000000 +0200
|
||||
+++ ./Modules/_hashopenssl.c 2019-12-25 16:22:02.398429000 +0200
|
||||
@@ -36,10 +36,22 @@
|
||||
#define _OPENSSL_SUPPORTS_SHA2
|
||||
#endif
|
||||
|
||||
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
|
||||
+/* OpenSSL < 1.1.0 */
|
||||
+#define EVP_MD_CTX_new EVP_MD_CTX_create
|
||||
+#define EVP_MD_CTX_free EVP_MD_CTX_destroy
|
||||
+#define HAS_FAST_PKCS5_PBKDF2_HMAC 0
|
||||
+#include <openssl/hmac.h>
|
||||
+#else
|
||||
+/* OpenSSL >= 1.1.0 */
|
||||
+#define HAS_FAST_PKCS5_PBKDF2_HMAC 1
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject *name; /* name of this hash algorithm */
|
||||
- EVP_MD_CTX ctx; /* OpenSSL message digest context */
|
||||
+ EVP_MD_CTX *ctx; /* OpenSSL message digest context */
|
||||
#ifdef WITH_THREAD
|
||||
PyThread_type_lock lock; /* OpenSSL context lock */
|
||||
#endif
|
||||
@@ -64,18 +76,57 @@
|
||||
#endif
|
||||
|
||||
|
||||
+/* LCOV_EXCL_START */
|
||||
+static PyObject *
|
||||
+_setException(PyObject *exc)
|
||||
+{
|
||||
+ unsigned long errcode;
|
||||
+ const char *lib, *func, *reason;
|
||||
+
|
||||
+ errcode = ERR_peek_last_error();
|
||||
+ if (!errcode) {
|
||||
+ PyErr_SetString(exc, "unknown reasons");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ ERR_clear_error();
|
||||
+
|
||||
+ lib = ERR_lib_error_string(errcode);
|
||||
+ func = ERR_func_error_string(errcode);
|
||||
+ reason = ERR_reason_error_string(errcode);
|
||||
+
|
||||
+ if (lib && func) {
|
||||
+ PyErr_Format(exc, "[%s: %s] %s", lib, func, reason);
|
||||
+ }
|
||||
+ else if (lib) {
|
||||
+ PyErr_Format(exc, "[%s] %s", lib, reason);
|
||||
+ }
|
||||
+ else {
|
||||
+ PyErr_SetString(exc, reason);
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+/* LCOV_EXCL_STOP */
|
||||
+
|
||||
static EVPobject *
|
||||
newEVPobject(PyObject *name)
|
||||
{
|
||||
EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, &EVPtype);
|
||||
+ if (retval == NULL) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
/* save the name for .name to return */
|
||||
- if (retval != NULL) {
|
||||
- Py_INCREF(name);
|
||||
- retval->name = name;
|
||||
+ Py_INCREF(name);
|
||||
+ retval->name = name;
|
||||
#ifdef WITH_THREAD
|
||||
- retval->lock = NULL;
|
||||
+ retval->lock = NULL;
|
||||
#endif
|
||||
+
|
||||
+ retval->ctx = EVP_MD_CTX_new();
|
||||
+ if (retval->ctx == NULL) {
|
||||
+ Py_DECREF(retval);
|
||||
+ PyErr_NoMemory();
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
@@ -91,7 +142,7 @@
|
||||
process = MUNCH_SIZE;
|
||||
else
|
||||
process = Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int);
|
||||
- EVP_DigestUpdate(&self->ctx, (const void*)cp, process);
|
||||
+ EVP_DigestUpdate(self->ctx, (const void*)cp, process);
|
||||
len -= process;
|
||||
cp += process;
|
||||
}
|
||||
@@ -106,16 +157,19 @@
|
||||
if (self->lock != NULL)
|
||||
PyThread_free_lock(self->lock);
|
||||
#endif
|
||||
- EVP_MD_CTX_cleanup(&self->ctx);
|
||||
+ EVP_MD_CTX_free(self->ctx);
|
||||
Py_XDECREF(self->name);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
-static void locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self)
|
||||
+static int
|
||||
+locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self)
|
||||
{
|
||||
+ int result;
|
||||
ENTER_HASHLIB(self);
|
||||
- EVP_MD_CTX_copy(new_ctx_p, &self->ctx);
|
||||
+ result = EVP_MD_CTX_copy(new_ctx_p, self->ctx);
|
||||
LEAVE_HASHLIB(self);
|
||||
+ return result;
|
||||
}
|
||||
|
||||
/* External methods for a hash object */
|
||||
@@ -131,7 +185,9 @@
|
||||
if ( (newobj = newEVPobject(self->name))==NULL)
|
||||
return NULL;
|
||||
|
||||
- locked_EVP_MD_CTX_copy(&newobj->ctx, self);
|
||||
+ if (!locked_EVP_MD_CTX_copy(newobj->ctx, self)) {
|
||||
+ return _setException(PyExc_ValueError);
|
||||
+ }
|
||||
return (PyObject *)newobj;
|
||||
}
|
||||
|
||||
@@ -142,16 +198,24 @@
|
||||
EVP_digest(EVPobject *self, PyObject *unused)
|
||||
{
|
||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
- EVP_MD_CTX temp_ctx;
|
||||
+ EVP_MD_CTX *temp_ctx;
|
||||
PyObject *retval;
|
||||
unsigned int digest_size;
|
||||
|
||||
- locked_EVP_MD_CTX_copy(&temp_ctx, self);
|
||||
- digest_size = EVP_MD_CTX_size(&temp_ctx);
|
||||
- EVP_DigestFinal(&temp_ctx, digest, NULL);
|
||||
+ temp_ctx = EVP_MD_CTX_new();
|
||||
+ if (temp_ctx == NULL) {
|
||||
+ PyErr_NoMemory();
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
+ if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) {
|
||||
+ return _setException(PyExc_ValueError);
|
||||
+ }
|
||||
+ digest_size = EVP_MD_CTX_size(temp_ctx);
|
||||
+ EVP_DigestFinal(temp_ctx, digest, NULL);
|
||||
+
|
||||
retval = PyBytes_FromStringAndSize((const char *)digest, digest_size);
|
||||
- EVP_MD_CTX_cleanup(&temp_ctx);
|
||||
+ EVP_MD_CTX_free(temp_ctx);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -162,17 +226,25 @@
|
||||
EVP_hexdigest(EVPobject *self, PyObject *unused)
|
||||
{
|
||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
- EVP_MD_CTX temp_ctx;
|
||||
+ EVP_MD_CTX *temp_ctx;
|
||||
PyObject *retval;
|
||||
char *hex_digest;
|
||||
unsigned int i, j, digest_size;
|
||||
|
||||
+ temp_ctx = EVP_MD_CTX_new();
|
||||
+ if (temp_ctx == NULL) {
|
||||
+ PyErr_NoMemory();
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
/* Get the raw (binary) digest value */
|
||||
- locked_EVP_MD_CTX_copy(&temp_ctx, self);
|
||||
- digest_size = EVP_MD_CTX_size(&temp_ctx);
|
||||
- EVP_DigestFinal(&temp_ctx, digest, NULL);
|
||||
+ if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) {
|
||||
+ return _setException(PyExc_ValueError);
|
||||
+ }
|
||||
+ digest_size = EVP_MD_CTX_size(temp_ctx);
|
||||
+ EVP_DigestFinal(temp_ctx, digest, NULL);
|
||||
|
||||
- EVP_MD_CTX_cleanup(&temp_ctx);
|
||||
+ EVP_MD_CTX_free(temp_ctx);
|
||||
|
||||
/* Allocate a new buffer */
|
||||
hex_digest = PyMem_Malloc(digest_size * 2 + 1);
|
||||
@@ -241,7 +313,7 @@
|
||||
EVP_get_block_size(EVPobject *self, void *closure)
|
||||
{
|
||||
long block_size;
|
||||
- block_size = EVP_MD_CTX_block_size(&self->ctx);
|
||||
+ block_size = EVP_MD_CTX_block_size(self->ctx);
|
||||
return PyLong_FromLong(block_size);
|
||||
}
|
||||
|
||||
@@ -249,7 +321,7 @@
|
||||
EVP_get_digest_size(EVPobject *self, void *closure)
|
||||
{
|
||||
long size;
|
||||
- size = EVP_MD_CTX_size(&self->ctx);
|
||||
+ size = EVP_MD_CTX_size(self->ctx);
|
||||
return PyLong_FromLong(size);
|
||||
}
|
||||
|
||||
@@ -475,6 +547,7 @@
|
||||
|
||||
#define PY_PBKDF2_HMAC 1
|
||||
|
||||
+#if !HAS_FAST_PKCS5_PBKDF2_HMAC
|
||||
/* Improved implementation of PKCS5_PBKDF2_HMAC()
|
||||
*
|
||||
* PKCS5_PBKDF2_HMAC_fast() hashes the password exactly one time instead of
|
||||
@@ -556,38 +629,9 @@
|
||||
HMAC_CTX_cleanup(&hctx_tpl);
|
||||
return 1;
|
||||
}
|
||||
+#endif
|
||||
|
||||
-/* LCOV_EXCL_START */
|
||||
-static PyObject *
|
||||
-_setException(PyObject *exc)
|
||||
-{
|
||||
- unsigned long errcode;
|
||||
- const char *lib, *func, *reason;
|
||||
|
||||
- errcode = ERR_peek_last_error();
|
||||
- if (!errcode) {
|
||||
- PyErr_SetString(exc, "unknown reasons");
|
||||
- return NULL;
|
||||
- }
|
||||
- ERR_clear_error();
|
||||
-
|
||||
- lib = ERR_lib_error_string(errcode);
|
||||
- func = ERR_func_error_string(errcode);
|
||||
- reason = ERR_reason_error_string(errcode);
|
||||
-
|
||||
- if (lib && func) {
|
||||
- PyErr_Format(exc, "[%s: %s] %s", lib, func, reason);
|
||||
- }
|
||||
- else if (lib) {
|
||||
- PyErr_Format(exc, "[%s] %s", lib, reason);
|
||||
- }
|
||||
- else {
|
||||
- PyErr_SetString(exc, reason);
|
||||
- }
|
||||
- return NULL;
|
||||
-}
|
||||
-/* LCOV_EXCL_STOP */
|
||||
-
|
||||
PyDoc_STRVAR(pbkdf2_hmac__doc__,
|
||||
"pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None) -> key\n\
|
||||
\n\
|
||||
@@ -668,10 +712,17 @@
|
||||
key = PyBytes_AS_STRING(key_obj);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
+#if HAS_FAST_PKCS5_PBKDF2_HMAC
|
||||
+ retval = PKCS5_PBKDF2_HMAC((char*)password.buf, (int)password.len,
|
||||
+ (unsigned char *)salt.buf, (int)salt.len,
|
||||
+ iterations, digest, dklen,
|
||||
+ (unsigned char *)key);
|
||||
+#else
|
||||
retval = PKCS5_PBKDF2_HMAC_fast((char*)password.buf, (int)password.len,
|
||||
(unsigned char *)salt.buf, (int)salt.len,
|
||||
iterations, digest, dklen,
|
||||
(unsigned char *)key);
|
||||
+#endif
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
if (!retval) {
|
||||
@@ -873,6 +924,13 @@
|
||||
|
||||
Py_INCREF((PyObject *)&EVPtype);
|
||||
PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype);
|
||||
+
|
||||
+#define INIT_CONSTRUCTOR_CONSTANTS(NAME) \
|
||||
+ do { \
|
||||
+ if (init_constructor_constant(&cached_info_ ## NAME, #NAME) < 0) { \
|
||||
+ return NULL; \
|
||||
+ } \
|
||||
+ } while (0);
|
||||
|
||||
/* these constants are used by the convenience constructors */
|
||||
INIT_CONSTRUCTOR_CONSTANTS(md5);
|
||||
11
lang/python34/files/patch-x-Modules-_hashopenssl_1.c
Normal file
11
lang/python34/files/patch-x-Modules-_hashopenssl_1.c
Normal file
@@ -0,0 +1,11 @@
|
||||
--- ./Modules/_hashopenssl.c~ 2019-12-25 16:27:31.838225000 +0200
|
||||
+++ ./Modules/_hashopenssl.c 2019-12-25 16:33:11.145818000 +0200
|
||||
@@ -955,7 +955,7 @@
|
||||
#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \
|
||||
init_constructor_constant(&cached_info_ ## NAME, #NAME); \
|
||||
} while (0);
|
||||
-static void
|
||||
+static int
|
||||
init_constructor_constant(EVPCachedInfo *cached_info, const char *name)
|
||||
{
|
||||
assert(cached_info);
|
||||
24
lang/python34/files/patch-x-Modules-_hashopenssl_2.c
Normal file
24
lang/python34/files/patch-x-Modules-_hashopenssl_2.c
Normal file
@@ -0,0 +1,24 @@
|
||||
--- Modules/_hashopenssl.c~ 2019-12-25 16:54:46.745242000 +0200
|
||||
+++ Modules/_hashopenssl.c 2019-12-25 16:59:43.252140000 +0200
|
||||
@@ -27,6 +27,21 @@
|
||||
#include <openssl/objects.h>
|
||||
#include "openssl/err.h"
|
||||
|
||||
+struct evp_md_ctx_st {
|
||||
+ const EVP_MD *digest;
|
||||
+ ENGINE *engine; /* functional reference if 'digest' is
|
||||
+ * ENGINE-provided */
|
||||
+ unsigned long flags;
|
||||
+ void *md_data;
|
||||
+ /* Public key context for sign/verify */
|
||||
+ EVP_PKEY_CTX *pctx;
|
||||
+ /* Update function: usually copied from EVP_MD */
|
||||
+ int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
|
||||
+} /* EVP_MD_CTX */ ;
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
#define MUNCH_SIZE INT_MAX
|
||||
|
||||
#ifndef HASH_OBJ_CONSTRUCTOR
|
||||
351
lang/python34/files/patch-x-Modules-_ssl.c
Normal file
351
lang/python34/files/patch-x-Modules-_ssl.c
Normal file
@@ -0,0 +1,351 @@
|
||||
--- ./Modules/_ssl.c.orig 2019-03-18 18:51:26.000000000 +0200
|
||||
+++ ./Modules/_ssl.c 2019-12-25 16:22:02.402671000 +0200
|
||||
@@ -55,6 +55,14 @@
|
||||
#include <sys/poll.h>
|
||||
#endif
|
||||
|
||||
+/* Don't warn about deprecated functions */
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
+#endif
|
||||
+#ifdef __clang__
|
||||
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
+#endif
|
||||
+
|
||||
/* Include OpenSSL header files */
|
||||
#include "openssl/rsa.h"
|
||||
#include "openssl/crypto.h"
|
||||
@@ -90,6 +98,10 @@
|
||||
/* Include generated data (error codes) */
|
||||
#include "_ssl_data.h"
|
||||
|
||||
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
+# define OPENSSL_VERSION_1_1 1
|
||||
+#endif
|
||||
+
|
||||
/* Openssl comes with TLSv1.1 and TLSv1.2 between 1.0.0h and 1.0.1
|
||||
http://www.openssl.org/news/changelog.html
|
||||
*/
|
||||
@@ -108,6 +120,72 @@
|
||||
# define HAVE_SNI 0
|
||||
#endif
|
||||
|
||||
+#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
+# define HAVE_ALPN
|
||||
+#endif
|
||||
+
|
||||
+#ifndef INVALID_SOCKET /* MS defines this */
|
||||
+#define INVALID_SOCKET (-1)
|
||||
+#endif
|
||||
+
|
||||
+#ifdef OPENSSL_VERSION_1_1
|
||||
+/* OpenSSL 1.1.0+ */
|
||||
+#ifndef OPENSSL_NO_SSL2
|
||||
+#define OPENSSL_NO_SSL2
|
||||
+#endif
|
||||
+#else /* OpenSSL < 1.1.0 */
|
||||
+#if defined(WITH_THREAD)
|
||||
+#define HAVE_OPENSSL_CRYPTO_LOCK
|
||||
+#endif
|
||||
+
|
||||
+static int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne)
|
||||
+{
|
||||
+ return ne->set;
|
||||
+}
|
||||
+
|
||||
+#ifndef OPENSSL_NO_COMP
|
||||
+static int COMP_get_type(const COMP_METHOD *meth)
|
||||
+{
|
||||
+ return meth->type;
|
||||
+}
|
||||
+
|
||||
+static const char *COMP_get_name(const COMP_METHOD *meth)
|
||||
+{
|
||||
+ return meth->name;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx)
|
||||
+{
|
||||
+ return ctx->default_passwd_callback;
|
||||
+}
|
||||
+
|
||||
+static void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx)
|
||||
+{
|
||||
+ return ctx->default_passwd_callback_userdata;
|
||||
+}
|
||||
+
|
||||
+static int X509_OBJECT_get_type(X509_OBJECT *x)
|
||||
+{
|
||||
+ return x->type;
|
||||
+}
|
||||
+
|
||||
+static X509 *X509_OBJECT_get0_X509(X509_OBJECT *x)
|
||||
+{
|
||||
+ return x->data.x509;
|
||||
+}
|
||||
+
|
||||
+static STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *store) {
|
||||
+ return store->objs;
|
||||
+}
|
||||
+
|
||||
+static X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *store)
|
||||
+{
|
||||
+ return store->param;
|
||||
+}
|
||||
+#endif /* OpenSSL < 1.1.0 or LibreSSL */
|
||||
+
|
||||
+
|
||||
enum py_ssl_error {
|
||||
/* these mirror ssl.h */
|
||||
PY_SSL_ERROR_NONE,
|
||||
@@ -691,7 +769,7 @@
|
||||
|
||||
/* check to see if we've gotten to a new RDN */
|
||||
if (rdn_level >= 0) {
|
||||
- if (rdn_level != entry->set) {
|
||||
+ if (rdn_level != X509_NAME_ENTRY_set(entry)) {
|
||||
/* yes, new RDN */
|
||||
/* add old RDN to DN */
|
||||
rdnt = PyList_AsTuple(rdn);
|
||||
@@ -708,7 +786,7 @@
|
||||
goto fail0;
|
||||
}
|
||||
}
|
||||
- rdn_level = entry->set;
|
||||
+ rdn_level = X509_NAME_ENTRY_set(entry);
|
||||
|
||||
/* now add this attribute to the current RDN */
|
||||
name = X509_NAME_ENTRY_get_object(entry);
|
||||
@@ -811,18 +889,18 @@
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- p = ext->value->data;
|
||||
+ p = X509_EXTENSION_get_data(ext)->data;
|
||||
if (method->it)
|
||||
names = (GENERAL_NAMES*)
|
||||
(ASN1_item_d2i(NULL,
|
||||
&p,
|
||||
- ext->value->length,
|
||||
+ X509_EXTENSION_get_data(ext)->length,
|
||||
ASN1_ITEM_ptr(method->it)));
|
||||
else
|
||||
names = (GENERAL_NAMES*)
|
||||
(method->d2i(NULL,
|
||||
&p,
|
||||
- ext->value->length));
|
||||
+ X509_EXTENSION_get_data(ext)->length));
|
||||
|
||||
for(j = 0; j < sk_GENERAL_NAME_num(names); j++) {
|
||||
/* get a rendering of each name in the set of names */
|
||||
@@ -1033,13 +1111,11 @@
|
||||
int i, j;
|
||||
PyObject *lst, *res = NULL;
|
||||
|
||||
-#if OPENSSL_VERSION_NUMBER < 0x10001000L
|
||||
- dps = X509_get_ext_d2i(certificate, NID_crl_distribution_points, NULL, NULL);
|
||||
-#else
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||||
/* Calls x509v3_cache_extensions and sets up crldp */
|
||||
X509_check_ca(certificate);
|
||||
- dps = certificate->crldp;
|
||||
#endif
|
||||
+ dps = X509_get_ext_d2i(certificate, NID_crl_distribution_points, NULL, NULL);
|
||||
|
||||
if (dps == NULL)
|
||||
return Py_None;
|
||||
@@ -1431,9 +1507,9 @@
|
||||
if (self->ssl == NULL)
|
||||
Py_RETURN_NONE;
|
||||
comp_method = SSL_get_current_compression(self->ssl);
|
||||
- if (comp_method == NULL || comp_method->type == NID_undef)
|
||||
+ if (comp_method == NULL || COMP_get_type(comp_method) == NID_undef)
|
||||
Py_RETURN_NONE;
|
||||
- short_name = OBJ_nid2sn(comp_method->type);
|
||||
+ short_name = COMP_get_name(comp_method);
|
||||
if (short_name == NULL)
|
||||
Py_RETURN_NONE;
|
||||
return PyUnicode_DecodeFSDefault(short_name);
|
||||
@@ -2051,8 +2127,9 @@
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
/* Allow automatic ECDH curve selection (on OpenSSL 1.0.2+), or use
|
||||
prime256v1 by default. This is Apache mod_ssl's initialization
|
||||
- policy, so we should be safe. */
|
||||
-#if defined(SSL_CTX_set_ecdh_auto)
|
||||
+ policy, so we should be safe. OpenSSL 1.1 has it enabled by default.
|
||||
+ */
|
||||
+#if defined(SSL_CTX_set_ecdh_auto) && !defined(OPENSSL_VERSION_1_1)
|
||||
SSL_CTX_set_ecdh_auto(self->ctx, 1);
|
||||
#else
|
||||
{
|
||||
@@ -2263,10 +2340,12 @@
|
||||
get_verify_flags(PySSLContext *self, void *c)
|
||||
{
|
||||
X509_STORE *store;
|
||||
+ X509_VERIFY_PARAM *param;
|
||||
unsigned long flags;
|
||||
|
||||
store = SSL_CTX_get_cert_store(self->ctx);
|
||||
- flags = X509_VERIFY_PARAM_get_flags(store->param);
|
||||
+ param = X509_STORE_get0_param(store);
|
||||
+ flags = X509_VERIFY_PARAM_get_flags(param);
|
||||
return PyLong_FromUnsignedLong(flags);
|
||||
}
|
||||
|
||||
@@ -2274,22 +2353,24 @@
|
||||
set_verify_flags(PySSLContext *self, PyObject *arg, void *c)
|
||||
{
|
||||
X509_STORE *store;
|
||||
+ X509_VERIFY_PARAM *param;
|
||||
unsigned long new_flags, flags, set, clear;
|
||||
|
||||
if (!PyArg_Parse(arg, "k", &new_flags))
|
||||
return -1;
|
||||
store = SSL_CTX_get_cert_store(self->ctx);
|
||||
- flags = X509_VERIFY_PARAM_get_flags(store->param);
|
||||
+ param = X509_STORE_get0_param(store);
|
||||
+ flags = X509_VERIFY_PARAM_get_flags(param);
|
||||
clear = flags & ~new_flags;
|
||||
set = ~flags & new_flags;
|
||||
if (clear) {
|
||||
- if (!X509_VERIFY_PARAM_clear_flags(store->param, clear)) {
|
||||
+ if (!X509_VERIFY_PARAM_clear_flags(param, clear)) {
|
||||
_setSSLError(NULL, 0, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (set) {
|
||||
- if (!X509_VERIFY_PARAM_set_flags(store->param, set)) {
|
||||
+ if (!X509_VERIFY_PARAM_set_flags(param, set)) {
|
||||
_setSSLError(NULL, 0, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
@@ -2459,8 +2540,8 @@
|
||||
char *kwlist[] = {"certfile", "keyfile", "password", NULL};
|
||||
PyObject *certfile, *keyfile = NULL, *password = NULL;
|
||||
PyObject *certfile_bytes = NULL, *keyfile_bytes = NULL;
|
||||
- pem_password_cb *orig_passwd_cb = self->ctx->default_passwd_callback;
|
||||
- void *orig_passwd_userdata = self->ctx->default_passwd_callback_userdata;
|
||||
+ pem_password_cb *orig_passwd_cb = SSL_CTX_get_default_passwd_cb(self->ctx);
|
||||
+ void *orig_passwd_userdata = SSL_CTX_get_default_passwd_cb_userdata(self->ctx);
|
||||
_PySSLPasswordInfo pw_info = { NULL, NULL, NULL, 0, 0 };
|
||||
int r;
|
||||
|
||||
@@ -2591,8 +2672,9 @@
|
||||
cert = d2i_X509_bio(biobuf, NULL);
|
||||
} else {
|
||||
cert = PEM_read_bio_X509(biobuf, NULL,
|
||||
- self->ctx->default_passwd_callback,
|
||||
- self->ctx->default_passwd_callback_userdata);
|
||||
+ SSL_CTX_get_default_passwd_cb(self->ctx),
|
||||
+ SSL_CTX_get_default_passwd_cb_userdata(self->ctx)
|
||||
+ );
|
||||
}
|
||||
if (cert == NULL) {
|
||||
break;
|
||||
@@ -3040,25 +3122,24 @@
|
||||
cert_store_stats(PySSLContext *self)
|
||||
{
|
||||
X509_STORE *store;
|
||||
+ STACK_OF(X509_OBJECT) *objs;
|
||||
X509_OBJECT *obj;
|
||||
- int x509 = 0, crl = 0, pkey = 0, ca = 0, i;
|
||||
+ int x509 = 0, crl = 0, ca = 0, i;
|
||||
|
||||
store = SSL_CTX_get_cert_store(self->ctx);
|
||||
- for (i = 0; i < sk_X509_OBJECT_num(store->objs); i++) {
|
||||
- obj = sk_X509_OBJECT_value(store->objs, i);
|
||||
- switch (obj->type) {
|
||||
+ objs = X509_STORE_get0_objects(store);
|
||||
+ for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
|
||||
+ obj = sk_X509_OBJECT_value(objs, i);
|
||||
+ switch (X509_OBJECT_get_type(obj)) {
|
||||
case X509_LU_X509:
|
||||
x509++;
|
||||
- if (X509_check_ca(obj->data.x509)) {
|
||||
+ if (X509_check_ca(X509_OBJECT_get0_X509(obj))) {
|
||||
ca++;
|
||||
}
|
||||
break;
|
||||
case X509_LU_CRL:
|
||||
crl++;
|
||||
break;
|
||||
- case X509_LU_PKEY:
|
||||
- pkey++;
|
||||
- break;
|
||||
default:
|
||||
/* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY.
|
||||
* As far as I can tell they are internal states and never
|
||||
@@ -3083,6 +3164,7 @@
|
||||
{
|
||||
char *kwlist[] = {"binary_form", NULL};
|
||||
X509_STORE *store;
|
||||
+ STACK_OF(X509_OBJECT) *objs;
|
||||
PyObject *ci = NULL, *rlist = NULL;
|
||||
int i;
|
||||
int binary_mode = 0;
|
||||
@@ -3097,17 +3179,18 @@
|
||||
}
|
||||
|
||||
store = SSL_CTX_get_cert_store(self->ctx);
|
||||
- for (i = 0; i < sk_X509_OBJECT_num(store->objs); i++) {
|
||||
+ objs = X509_STORE_get0_objects(store);
|
||||
+ for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
|
||||
X509_OBJECT *obj;
|
||||
X509 *cert;
|
||||
|
||||
- obj = sk_X509_OBJECT_value(store->objs, i);
|
||||
- if (obj->type != X509_LU_X509) {
|
||||
+ obj = sk_X509_OBJECT_value(objs, i);
|
||||
+ if (X509_OBJECT_get_type(obj) != X509_LU_X509) {
|
||||
/* not a x509 cert */
|
||||
continue;
|
||||
}
|
||||
/* CA for any purpose */
|
||||
- cert = obj->data.x509;
|
||||
+ cert = X509_OBJECT_get0_X509(obj);
|
||||
if (!X509_check_ca(cert)) {
|
||||
continue;
|
||||
}
|
||||
@@ -3780,10 +3863,12 @@
|
||||
};
|
||||
|
||||
|
||||
-#ifdef WITH_THREAD
|
||||
+#ifdef HAVE_OPENSSL_CRYPTO_LOCK
|
||||
|
||||
/* an implementation of OpenSSL threading operations in terms
|
||||
- of the Python C thread library */
|
||||
+ * of the Python C thread library
|
||||
+ * Only used up to 1.0.2. OpenSSL 1.1.0+ has its own locking code.
|
||||
+ */
|
||||
|
||||
static PyThread_type_lock *_ssl_locks = NULL;
|
||||
|
||||
@@ -3864,7 +3949,7 @@
|
||||
return 1;
|
||||
}
|
||||
|
||||
-#endif /* def HAVE_THREAD */
|
||||
+#endif /* HAVE_OPENSSL_CRYPTO_LOCK for WITH_THREAD && OpenSSL < 1.1.0 */
|
||||
|
||||
PyDoc_STRVAR(module_doc,
|
||||
"Implementation module for SSL socket operations. See the socket module\n\
|
||||
@@ -3931,11 +4016,16 @@
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
#ifdef WITH_THREAD
|
||||
+#ifdef HAVE_OPENSSL_CRYPTO_LOCK
|
||||
/* note that this will start threading if not already started */
|
||||
if (!_setup_ssl_threads()) {
|
||||
return NULL;
|
||||
}
|
||||
+#elif OPENSSL_VERSION_1_1 && defined(OPENSSL_THREADS)
|
||||
+ /* OpenSSL 1.1.0 builtin thread support is enabled */
|
||||
+ _ssl_locks_count++;
|
||||
#endif
|
||||
+#endif /* WITH_THREAD */
|
||||
OpenSSL_add_all_algorithms();
|
||||
|
||||
/* Add symbols to module dict */
|
||||
4
lang/python34/pkg-descr
Normal file
4
lang/python34/pkg-descr
Normal file
@@ -0,0 +1,4 @@
|
||||
Python is an interpreted object-oriented programming language, and is
|
||||
often compared to Tcl, Perl or Scheme.
|
||||
|
||||
WWW: http://www.python.org/
|
||||
4973
lang/python34/pkg-plist
Normal file
4973
lang/python34/pkg-plist
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user