Rebase to 2.7.16rc1

This commit is contained in:
Charalampos Stratakis 2019-02-19 16:06:24 +01:00 committed by churchyard
parent b13073ac76
commit 75a0703066
8 changed files with 66 additions and 219 deletions

View File

@ -20,10 +20,10 @@ index b9f1c6c..7b23714 100644
'scripts': '$base/bin',
'data' : '$base',
diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
index 068d1ba..3e7f077 100644
index 031f809..ec5d584 100644
--- a/Lib/distutils/sysconfig.py
+++ b/Lib/distutils/sysconfig.py
@@ -119,8 +119,12 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
@@ -120,8 +120,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":
@ -59,10 +59,10 @@ index c360802..868b7cb 100644
return sitepackages
diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py
index d9a9324..e411e5c 100644
index b4384ee..349f688 100644
--- a/Lib/test/test_site.py
+++ b/Lib/test/test_site.py
@@ -235,17 +235,20 @@ class HelperFunctionsTests(unittest.TestCase):
@@ -254,17 +254,20 @@ class HelperFunctionsTests(unittest.TestCase):
self.assertEqual(dirs[0], wanted)
elif os.sep == '/':
# OS X, Linux, FreeBSD, etc
@ -86,12 +86,12 @@ index d9a9324..e411e5c 100644
+ wanted = os.path.join('xoxo', 'lib64', 'site-packages')
self.assertEqual(dirs[1], wanted)
class PthFile(object):
def test_no_home_directory(self):
diff --git a/Makefile.pre.in b/Makefile.pre.in
index adae76b..ecb27f3 100644
index 4f59dd3..877698c 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -111,7 +111,7 @@ LIBDIR= @libdir@
@@ -110,7 +110,7 @@ LIBDIR= @libdir@
MANDIR= @mandir@
INCLUDEDIR= @includedir@
CONFINCLUDEDIR= $(exec_prefix)/include
@ -101,10 +101,10 @@ index adae76b..ecb27f3 100644
# Detailed destination directories
BINLIBDEST= $(LIBDIR)/python$(VERSION)
diff --git a/Modules/Setup.dist b/Modules/Setup.dist
index fbfa1c1..138fb33 100644
index 2cf35a9..c4c88cb 100644
--- a/Modules/Setup.dist
+++ b/Modules/Setup.dist
@@ -231,7 +231,7 @@
@@ -231,7 +231,7 @@ crypt cryptmodule.c # -lcrypt # crypt(3); needs -lcrypt on some systems
# Some more UNIX dependent modules -- off by default, since these
# are not supported by all UNIX systems:
@ -130,7 +130,7 @@ index fbfa1c1..138fb33 100644
+zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib64 -lz
# Interface to the Expat XML parser
#
# More information on Expat can be found at www.libexpat.org.
diff --git a/Modules/getpath.c b/Modules/getpath.c
index fd33a01..c5c86fd 100644
--- a/Modules/getpath.c
@ -154,7 +154,7 @@ index fd33a01..c5c86fd 100644
/* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
diff --git a/setup.py b/setup.py
index 99ac359..859b6c4 100644
index 0288a6b..7905f6f 100644
--- a/setup.py
+++ b/setup.py
@@ -456,7 +456,7 @@ class PyBuildExt(build_ext):

View File

@ -1,5 +1,5 @@
diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py
index 89ed1ef..8008222 100644
index 5021ebf..1903cc0 100644
--- a/Lib/ensurepip/__init__.py
+++ b/Lib/ensurepip/__init__.py
@@ -1,9 +1,10 @@
@ -14,15 +14,14 @@ index 89ed1ef..8008222 100644
import shutil
import sys
import tempfile
@@ -11,10 +12,20 @@ import tempfile
@@ -12,9 +13,19 @@ import tempfile
__all__ = ["version", "bootstrap"]
-_SETUPTOOLS_VERSION = "40.6.2"
+_WHEEL_DIR = "/usr/share/python-wheels/"
-_SETUPTOOLS_VERSION = "39.0.1"
-_PIP_VERSION = "9.0.3"
-_PIP_VERSION = "18.1"
+def _get_most_recent_wheel_version(pkg):
+ prefix = os.path.join(_WHEEL_DIR, "{}-".format(pkg))
+ suffix = "-py2.py3-none-any.whl"
@ -41,8 +40,8 @@ index 89ed1ef..8008222 100644
sys.path = additional_paths + sys.path
# Install the bundled software
- import pip
- return pip.main(args)
- import pip._internal
- return pip._internal.main(args)
+ try:
+ # pip 10
+ from pip._internal import main

View File

@ -1,11 +1,14 @@
--- Python-2.7.5-orig/Tools/gdb/libpython.py 2013-05-12 03:32:54.000000000 +0000
+++ Python-2.7.5-orig/Tools/gdb/libpython.py 2013-09-15 09:56:25.494000000 +0000
@@ -887,6 +887,8 @@
newline character'''
diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py
index 9def56e..c0df208 100755
--- a/Tools/gdb/libpython.py
+++ b/Tools/gdb/libpython.py
@@ -939,6 +939,9 @@ class PyFrameObjectPtr(PyObjectPtr):
if self.is_optimized_out():
return '(frame information optimized out)'
+ if self.filename() == '<string>':
+ return '(in an eval block)'
filename = self.filename()
try:
f = open(filename, 'r')
+
lineno = self.current_line_num()
if lineno is None:
return '(failed to get frame line number)'

View File

@ -1,61 +0,0 @@
From add531a1e55b0a739b0f42582f1c9747e5649ace Mon Sep 17 00:00:00 2001
From: Benjamin Peterson <benjamin@python.org>
Date: Tue, 28 Aug 2018 22:12:56 -0700
Subject: [PATCH] closes bpo-34540: Convert shutil._call_external_zip to use
subprocess rather than distutils.spawn.
---
Lib/shutil.py | 16 ++++++++++------
.../2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst | 3 +++
2 files changed, 13 insertions(+), 6 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst
diff --git a/Lib/shutil.py b/Lib/shutil.py
index 3462f7c5e91c..0ab1a06f5260 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -413,17 +413,21 @@ def _set_uid_gid(tarinfo):
return archive_name
-def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False):
+def _call_external_zip(base_dir, zip_filename, verbose, dry_run, logger):
# XXX see if we want to keep an external call here
if verbose:
zipoptions = "-r"
else:
zipoptions = "-rq"
- from distutils.errors import DistutilsExecError
- from distutils.spawn import spawn
+ cmd = ["zip", zipoptions, zip_filename, base_dir]
+ if logger is not None:
+ logger.info(' '.join(cmd))
+ if dry_run:
+ return
+ import subprocess
try:
- spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run)
- except DistutilsExecError:
+ subprocess.check_call(cmd)
+ except subprocess.CalledProcessError:
# XXX really should distinguish between "couldn't find
# external 'zip' command" and "zip failed".
raise ExecError, \
@@ -458,7 +462,7 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
zipfile = None
if zipfile is None:
- _call_external_zip(base_dir, zip_filename, verbose, dry_run)
+ _call_external_zip(base_dir, zip_filename, verbose, dry_run, logger)
else:
if logger is not None:
logger.info("creating '%s' and adding '%s' to it",
diff --git a/Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst b/Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst
new file mode 100644
index 000000000000..4f686962a87b
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst
@@ -0,0 +1,3 @@
+When ``shutil.make_archive`` falls back to the external ``zip`` problem, it
+uses :mod:`subprocess` to invoke it rather than :mod:`distutils.spawn`. This
+closes a possible shell injection vector.

View File

@ -1,85 +0,0 @@
From 554c48934c599b3fb04c73d740bba1a745b89b41 Mon Sep 17 00:00:00 2001
From: Christian Heimes <christian@python.org>
Date: Tue, 18 Sep 2018 14:38:58 +0200
Subject: [PATCH] [2.7] bpo-34623: Use XML_SetHashSalt in _elementtree
(GH-9146)
The C accelerated _elementtree module now initializes hash randomization
salt from _Py_HashSecret instead of libexpat's default CPRNG.
Signed-off-by: Christian Heimes <christian@python.org>
https://bugs.python.org/issue34623.
(cherry picked from commit cb5778f00ce48631c7140f33ba242496aaf7102b)
Co-authored-by: Christian Heimes <christian@python.org>
---
Include/pyexpat.h | 4 +++-
.../next/Security/2018-09-10-16-05-39.bpo-34623.Ua9jMv.rst | 2 ++
Modules/_elementtree.c | 5 +++++
Modules/pyexpat.c | 5 +++++
4 files changed, 15 insertions(+), 1 deletion(-)
create mode 100644 Misc/NEWS.d/next/Security/2018-09-10-16-05-39.bpo-34623.Ua9jMv.rst
diff --git a/Include/pyexpat.h b/Include/pyexpat.h
index 5340ef5fa386..3fc5fa54da63 100644
--- a/Include/pyexpat.h
+++ b/Include/pyexpat.h
@@ -3,7 +3,7 @@
/* note: you must import expat.h before importing this module! */
-#define PyExpat_CAPI_MAGIC "pyexpat.expat_CAPI 1.0"
+#define PyExpat_CAPI_MAGIC "pyexpat.expat_CAPI 1.1"
#define PyExpat_CAPSULE_NAME "pyexpat.expat_CAPI"
struct PyExpat_CAPI
@@ -43,6 +43,8 @@ struct PyExpat_CAPI
XML_Parser parser, XML_UnknownEncodingHandler handler,
void *encodingHandlerData);
void (*SetUserData)(XML_Parser parser, void *userData);
+ /* might be none for expat < 2.1.0 */
+ int (*SetHashSalt)(XML_Parser parser, unsigned long hash_salt);
/* always add new stuff to the end! */
};
diff --git a/Misc/NEWS.d/next/Security/2018-09-10-16-05-39.bpo-34623.Ua9jMv.rst b/Misc/NEWS.d/next/Security/2018-09-10-16-05-39.bpo-34623.Ua9jMv.rst
new file mode 100644
index 000000000000..31ad92ef8582
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2018-09-10-16-05-39.bpo-34623.Ua9jMv.rst
@@ -0,0 +1,2 @@
+The C accelerated _elementtree module now initializes hash randomization
+salt from _Py_HashSecret instead of libexpat's default CSPRNG.
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index f7f992dd3a95..b38e0ab329c7 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -2574,6 +2574,11 @@ xmlparser(PyObject* self_, PyObject* args, PyObject* kw)
PyErr_NoMemory();
return NULL;
}
+ /* expat < 2.1.0 has no XML_SetHashSalt() */
+ if (EXPAT(SetHashSalt) != NULL) {
+ EXPAT(SetHashSalt)(self->parser,
+ (unsigned long)_Py_HashSecret.prefix);
+ }
ALLOC(sizeof(XMLParserObject), "create expatparser");
diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c
index 2b4d31293c64..1f8c0d70a559 100644
--- a/Modules/pyexpat.c
+++ b/Modules/pyexpat.c
@@ -2042,6 +2042,11 @@ MODULE_INITFUNC(void)
capi.SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler;
capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler;
capi.SetUserData = XML_SetUserData;
+#if XML_COMBINED_VERSION >= 20100
+ capi.SetHashSalt = XML_SetHashSalt;
+#else
+ capi.SetHashSalt = NULL;
+#endif
/* export using capsule */
capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL);

View File

@ -1,5 +1,7 @@
--- Python-2.7.4/Modules/Setup.dist.rhconfig 2013-04-06 16:02:34.000000000 +0200
+++ Python-2.7.4/Modules/Setup.dist 2013-04-08 10:05:16.369985654 +0200
diff --git a/Modules/Setup.dist b/Modules/Setup.dist
index bbc9222..2cf35a9 100644
--- a/Modules/Setup.dist
+++ b/Modules/Setup.dist
@@ -153,7 +153,7 @@ GLHACK=-Dclear=__GLclear
# modules are to be built as shared libraries (see above for more
# detail; also note that *static* reverses this effect):
@ -9,7 +11,7 @@
# GNU readline. Unlike previous Python incarnations, GNU readline is
# now incorporated in an optional module, configured in the Setup file
@@ -163,77 +163,77 @@ GLHACK=-Dclear=__GLclear
@@ -163,33 +163,33 @@ GLHACK=-Dclear=__GLclear
# it, depending on your system -- see the GNU readline instructions.
# It's okay for this to be a shared library, too.
@ -59,9 +61,7 @@
# Standard I/O baseline
#_io -I$(srcdir)/Modules/_io _io/bufferedio.c _io/bytesio.c _io/fileio.c _io/iobase.c _io/_iomodule.c _io/stringio.c _io/textio.c
# Modules with some UNIX dependencies -- on by default:
@@ -199,41 +199,41 @@ GLHACK=-Dclear=__GLclear
# (If you have a really backward UNIX, select and socket may not be
# supported...)
@ -117,7 +117,7 @@
# Multimedia modules -- off by default.
@@ -238,8 +238,8 @@ GLHACK=-Dclear=__GLclear
@@ -241,8 +241,8 @@ GLHACK=-Dclear=__GLclear
# #993173 says audioop works on 64-bit platforms, though.
# These represent audio samples or images as strings:
@ -128,7 +128,7 @@
# Note that the _md5 and _sha modules are normally only built if the
@@ -249,14 +249,14 @@ GLHACK=-Dclear=__GLclear
@@ -252,14 +252,14 @@ GLHACK=-Dclear=__GLclear
# Message-Digest Algorithm, described in RFC 1321. The necessary files
# md5.c and md5.h are included here.
@ -147,7 +147,7 @@
# SGI IRIX specific modules -- off by default.
@@ -303,12 +303,12 @@ GLHACK=-Dclear=__GLclear
@@ -306,12 +306,12 @@ GLHACK=-Dclear=__GLclear
# A Linux specific module -- off by default; this may also work on
# some *BSDs.
@ -162,7 +162,7 @@
# The _tkinter module.
@@ -323,7 +323,7 @@ GLHACK=-Dclear=__GLclear
@@ -326,7 +326,7 @@ GLHACK=-Dclear=__GLclear
# every system.
# *** Always uncomment this (leave the leading underscore in!):
@ -171,7 +171,7 @@
# *** Uncomment and edit to reflect where your Tcl/Tk libraries are:
# -L/usr/local/lib \
# *** Uncomment and edit to reflect where your Tcl/Tk headers are:
@@ -333,7 +333,7 @@ GLHACK=-Dclear=__GLclear
@@ -336,7 +336,7 @@ GLHACK=-Dclear=__GLclear
# *** Or uncomment this for Solaris:
# -I/usr/openwin/include \
# *** Uncomment and edit for Tix extension only:
@ -180,7 +180,7 @@
# *** Uncomment and edit for BLT extension only:
# -DWITH_BLT -I/usr/local/blt/blt8.0-unoff/include -lBLT8.0 \
# *** Uncomment and edit for PIL (TkImaging) extension only:
@@ -342,7 +342,7 @@ GLHACK=-Dclear=__GLclear
@@ -345,7 +345,7 @@ GLHACK=-Dclear=__GLclear
# *** Uncomment and edit for TOGL extension only:
# -DWITH_TOGL togl.c \
# *** Uncomment and edit to reflect your Tcl/Tk versions:
@ -189,7 +189,7 @@
# *** Uncomment and edit to reflect where your X11 libraries are:
# -L/usr/X11R6/lib \
# *** Or uncomment this for Solaris:
@@ -352,7 +352,7 @@ GLHACK=-Dclear=__GLclear
@@ -355,7 +355,7 @@ GLHACK=-Dclear=__GLclear
# *** Uncomment for AIX:
# -lld \
# *** Always uncomment this; X11 libraries to link with:
@ -198,7 +198,7 @@
# Lance Ellinghaus's syslog module
#syslog syslogmodule.c # syslog daemon interface
@@ -374,7 +374,7 @@ GLHACK=-Dclear=__GLclear
@@ -377,7 +377,7 @@ GLHACK=-Dclear=__GLclear
# it is a highly experimental and dangerous device for calling
# *arbitrary* C functions in *arbitrary* shared libraries:
@ -207,7 +207,7 @@
# Modules that provide persistent dictionary-like semantics. You will
@@ -397,7 +397,7 @@ GLHACK=-Dclear=__GLclear
@@ -400,7 +400,7 @@ GLHACK=-Dclear=__GLclear
#
# First, look at Setup.config; configure may have set this for you.
@ -216,7 +216,7 @@
# Sleepycat Berkeley DB interface.
@@ -412,11 +412,9 @@ GLHACK=-Dclear=__GLclear
@@ -415,11 +415,9 @@ GLHACK=-Dclear=__GLclear
#
# Edit the variables DB and DBLIBVERto point to the db top directory
# and the subdirectory of PORT where you built it.
@ -231,7 +231,7 @@
# Historical Berkeley DB 1.85
#
@@ -431,14 +430,14 @@ GLHACK=-Dclear=__GLclear
@@ -434,14 +432,14 @@ GLHACK=-Dclear=__GLclear
# Helper module for various ascii-encoders
@ -250,7 +250,7 @@
# Lee Busby's SIGFPE modules.
@@ -461,7 +460,7 @@ GLHACK=-Dclear=__GLclear
@@ -464,7 +462,7 @@ GLHACK=-Dclear=__GLclear
# Andrew Kuchling's zlib module.
# This require zlib 1.1.3 (or later).
# See http://www.gzip.org/zlib/
@ -258,20 +258,21 @@
+zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz
# Interface to the Expat XML parser
#
@@ -480,14 +479,14 @@ GLHACK=-Dclear=__GLclear
# More information on Expat can be found at www.libexpat.org.
@@ -475,14 +473,14 @@ GLHACK=-Dclear=__GLclear
# Hye-Shik Chang's CJKCodecs
# multibytecodec is required for all the other CJK codec modules
-#_multibytecodec cjkcodecs/multibytecodec.c
+_multibytecodec cjkcodecs/multibytecodec.c
-
-#_codecs_cn cjkcodecs/_codecs_cn.c
-#_codecs_hk cjkcodecs/_codecs_hk.c
-#_codecs_iso2022 cjkcodecs/_codecs_iso2022.c
-#_codecs_jp cjkcodecs/_codecs_jp.c
-#_codecs_kr cjkcodecs/_codecs_kr.c
-#_codecs_tw cjkcodecs/_codecs_tw.c
+_multibytecodec cjkcodecs/multibytecodec.c
+
+_codecs_cn cjkcodecs/_codecs_cn.c
+_codecs_hk cjkcodecs/_codecs_hk.c
+_codecs_iso2022 cjkcodecs/_codecs_iso2022.c

View File

@ -122,8 +122,11 @@
Summary: An interpreted, interactive, object-oriented programming language
Name: %{python}
# Remember to also rebase python2-docs when changing this:
Version: 2.7.15
Release: 14%{?dist}
%global general_version %{pybasever}.16
%global prerel rc1
%global upstream_version %{general_version}%{?prerel}
Version: %{general_version}%{?prerel:~%{prerel}}
Release: 1%{?dist}
License: Python
Requires: %{python}-libs%{?_isa} = %{version}-%{release}
Provides: python(abi) = %{pybasever}
@ -154,8 +157,7 @@ BuildRequires: readline-devel
BuildRequires: sqlite-devel
BuildRequires: tcl-devel
# https://bugzilla.redhat.com/show_bug.cgi?id=1609291
BuildRequires: compat-openssl10-devel
BuildRequires: openssl-devel
# For the nis module
BuildRequires: libnsl2-devel
@ -221,7 +223,7 @@ Recommends: python2-pip
# Source code and patches
# =======================
Source: https://www.python.org/ftp/python/%{version}/Python-%{version}.tar.xz
Source: https://www.python.org/ftp/python/%{version}/Python-%{upstream_version}.tar.xz
# Work around bug 562906 until it's fixed in rpm-build by providing a fixed
# version of pythondeps.sh:
@ -760,20 +762,6 @@ Patch193: 00193-enable-loading-sqlite-extensions.patch
# (we handle it it in Setup.dist, see Patch0)
Patch289: 00289-disable-nis-detection.patch
# 00309 #
# CVE-2018-1000802
# shutil._call_external_zip to use subprocess instead of distutils.spawn
# rhbz#1631662
# Fixed upstream https://bugs.python.org/issue34540
Patch309: 00309-shutil-spawn-subprocess.patch
# 00310 #
# CVE-2018-14647
# Use XML_SetHashSalt in _elementtree
# rhbz#1631822
# Fixed upstream https://bugs.python.org/issue34623
Patch310: 00310-use-xml-sethashsalt-in-elementtree.patch
# (New patches go here ^^^)
#
# When adding new patches to "python2" and "python3" in Fedora, EL, etc.,
@ -1001,7 +989,7 @@ load its own extensions.
# ======================================================
%prep
%setup -q -n Python-%{version}
%setup -q -n Python-%{upstream_version}
%if 0%{?with_systemtap}
# Provide an example of usage of the tapset:
@ -1120,9 +1108,6 @@ rm Lib/ensurepip/_bundled/*.whl
%patch191 -p1
%patch193 -p1
%patch289 -p1
%patch309 -p1
%patch310 -p1
%if 0%{?_module_build}
%patch4000 -p1
@ -1581,6 +1566,8 @@ CheckPython() {
BinaryName=$2
ConfDir=$(pwd)/build/$ConfName
export OPENSSL_CONF=/non-existing-file
echo STARTING: CHECKING OF PYTHON FOR CONFIGURATION: $ConfName
# Note that we're running the tests using the version of the code in the
@ -1666,7 +1653,7 @@ CheckPython \
%{dynload_dir}/_sha512module.so
%{dynload_dir}/_shamodule.so
%{dynload_dir}/Python-%{version}-py%{pybasever}.egg-info
%{dynload_dir}/Python-%{upstream_version}-py%{pybasever}.egg-info
%{dynload_dir}/_bisectmodule.so
%{dynload_dir}/_bsddb.so
%{dynload_dir}/_codecs_cn.so
@ -2021,6 +2008,9 @@ CheckPython \
# ======================================================
%changelog
* Tue Feb 19 2019 Charalampos Stratakis <cstratak@redhat.com> - 2.7.16~rc1-1
- Update to 2.7.16rc1
* Sun Feb 17 2019 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 2.7.15-14
- Rebuild for readline 8.0

View File

@ -1 +1 @@
SHA512 (Python-2.7.15.tar.xz) = 27ea43eb45fc68f3d2469d5f07636e10801dee11635a430ec8ec922ed790bb426b072da94df885e4dfa1ea8b7a24f2f56dd92f9b0f51e162330f161216bd6de6
SHA512 (Python-2.7.16rc1.tar.xz) = d06edb29d6517c9ff7c5c31f587d6dbe32c420ab11170fdedb5e0207c45423756407d01764a0666f8605eaf629f44f1d5400714224e1a958722b8bee3c3c24a2