
CPython 3.5.4rc1 发布说明深度解读安全修复、核心与标准库变更全览【免费下载链接】cpythonThe Python programming language项目地址: https://gitcode.com/GitHub_Trending/cp/cpython本文以 CPython 3.5 维护分支的候选发布版 3.5.4rc1发布于 2017-07-23的官方变更记录Misc/NEWS.d/3.5.4rc1.rst为主体逐板块梳理其安全修复、Core and Builtins 缺陷修复、标准库行为修正、测试基建增强与构建/Windows/C API 变更并结合当前 CPython 仓库中的源码与测试用例如 Lib/urllib/parse.py、Modules/pyexpat.c、Lib/test/test_urlparse.py佐证底层实现。读完本文你将掌握 3.5.4rc1 每个关键补丁解决的问题、对应源码位置及其对后续版本的影响。一、发布背景与变更总览CPython 3.5 系列属于 2015 年发布的 3.x 分支3.5.4rc1 是 3.5.4 正式版之前的候选发布版文档头部标注的 release date 为 2017-07-23。整个变更记录采用当时标准的NEWS.d条目格式每条包含 bpo 编号、日期、nonce 与所属 sectionSecurity、Core and Builtins、Library、Documentation、Tests、Build、Windows、C API。从板块分布看本版变更呈现三个鲜明特征安全类变更集中覆盖 Windows subprocess 环境变量注入、expat 库连续升级2.1.1 → 2.2.0 → 2.2.1、urllib.parse 主机解析缺陷是 3.5 维护分支对安全问题的集中响应核心解释器缺陷大量修复涉及 dict 并发变异崩溃、pthread 锁阻塞、相对导入异常类型、协程 StopIteration 包装、旧字节码兼容等十余项标准库行为修正面广multiprocessing、asyncio、unittest.mock、typing、pathlib、subprocess 等高频模块均有针对性修补。下文按官方 section 顺序展开并补充仓库源码证据。二、安全修复Security1. Windows 上 subprocess 环境变量注入防护bpo-30730变更内容在 Windows 平台阻止环境变量注入到 subprocess——防止把额外的环境变量与命令行参数传入子进程。原理说明Windows 创建进程时如果传给CreateProcess的lpEnvironment或命令行参数处理不当攻击者可以通过精心构造的环境变量名例如包含的键或命令行转义字符实现参数/环境注入。该补丁在 Lib/subprocess.py 的环境变量序列化路径中体现为显式校验构建env_list时对每个键执行os.fsencode(k)后检查b in k一旦发现非法名称立即抛出ValueError(illegal environment variable name)见 Lib/subprocess.py。这一防御逻辑在后续版本被保留并扩展是 CPython 对 Windows 子进程安全的重要基线。2. expat 升级至 2.2.1修复多个安全漏洞bpo-30694变更内容将内置 expat 副本从 2.2.0 升级到 2.2.1修复多个安全漏洞包括CVE-2017-9233外部实体无限循环导致的拒绝服务External entity infinite loop DoSCVE-2016-9063整数溢出re-fixCVE-2016-0718修复 2.2.0 针对该 CVE 补丁引入的回归 bugCVE-2012-0876SipHash 计数器哈希洪泛Counter hash flooding。关键说明记录中特别指出 CVE-2016-5300使用 getrandom 等 OS 熵源不影响 Python因为 Python 早已通过XML_SetHashSalt()从操作系统获取熵来设置 expat 的 secret。仓库源码可佐证在 Modules/pyexpat.c 中新建解析器时根据XML_COMBINED_VERSION调用XML_SetHashSalt16Bytes(self-itself, _Py_HashSecret.expat.hashsalt16)expat ≥ 2.8.0或XML_SetHashSalt(self-itself, (unsigned long)_Py_HashSecret.expat.hashsalt)expat ≥ 2.1.0即哈希盐直接取自 CPython 的进程级哈希密钥_Py_HashSecret无需依赖 expat 自身的熵源。3. urllib.parse.splithost() 片段解析修复bpo-30500变更内容修复urllib.parse.splithost()对 URL 片段的解析。此前splithost(//127.0.0.1#evil.com/)会把evil.com误当作认证信息loginhost中的 host即解析出错误的主机名修复后正确返回主机127.0.0.1。源码佐证当前 Lib/urllib/parse.py 中_splithost()使用正则//([^/#?]*)(.*)提取主机端口部分#位于排除字符集内因此片段起始符之后的evil.com不再参与主机匹配。测试用例位于 Lib/test/test_urlparse.py明确注释# bpo-30500: # starts a fragment.验证了splithost(//127.0.0.1#host.com)返回(127.0.0.1, /#host.com)等场景。注意urllib.parse.splithost()自 3.8 起被标记为弃用官方建议改用urllib.parse.urlsplit()但底层_splithost仍保留此正确行为。4. expat 升级至 2.2.0bpo-29591变更内容将 expat 副本从 2.1.1 升级到 2.2.0获取 CVE-2016-0718 与 CVE-2016-4472 的修复。这条是 2.2.1 升级bpo-30694的前置步骤两次升级共同构成了 3.5.4 分支对 expat 解析器安全性的完整加固链。三、核心与内置Core and Builtins1. 相对导入行为修正bpo-30876从未加载包unloaded package发起的相对导入现在会重新导入该包而不是以SystemError失败从非包non-package发起的相对导入现在以ImportError失败而不是SystemError。这一改动把包未加载与根本不是包两种情形区分开使异常类型更符合语义也消除了相对导入在边界场景下暴露解释器内部状态SystemError的问题。2. PyThread_acquire_lock() 非阻塞语义修复bpo-30765变更内容当PyThread_acquire_lock()被要求不阻塞non-blocking时避免在pthread_mutex_lock()中阻塞。此前某些平台上非阻塞获取可能退化为阻塞行为导致调用方线程意外挂起修复后严格遵循尝试获取、失败即返回的语义。3. dict 在迭代/插入/比较期间被外部变异时的崩溃修复bpo-27945变更内容修复当输入集合在搜索、插入或比较过程中被并发变异时dict 出现的多种段错误segfault。补丁基于 Duane Griffin 与 Tim Mitchell 的补丁。这属于解释器核心容器在迭代时修改竞态下的健壮性修复。4. type.setattr()/delattr() 对非驻留属性名的修复bpo-25794修复type.__setattr__()与type.__delattr__()在属性名非 interned驻留时的处理错误基于 Eryk Sun 的补丁。涉及元类层面的属性设置/删除与字符串驻留机制的交互。5. tuple/list/deque 的 index() 错误消息修复bpo-29935当向tuple.index()、list.index()、deque.index()传入错误类型如字符串而非整数的索引时错误消息得到修正更准确地描述问题。6. bool(range) 与 len(range) 抛 OverflowError 的交互bpo-28876变更内容即使len(range)抛出OverflowErrorbool(range)也能正常工作。此前布尔判断可能被长度计算的溢出异常干扰。7. 协程返回值 StopIteration 包装修复bpo-29600修复协程返回值在StopIteration中的包装方式确保await表达式能够正确取出协程的返回值而不丢失或错位。8. 与 3.5.0–3.5.2 字节码的运行时兼容bpo-29537变更内容恢复对 CPython 3.5.0 至 3.5.2 生成的字节码文件的运行时兼容性并调整求值循环eval loop以避免这些旧字节码可能包含的畸形BUILD_MAP_UNPACK_WITH_CALL操作码变体引发的问题。补丁作者为 Petr Viktorin、Serhiy Storchaka、Nick Coghlan。这体现了 CPython 维护分支在语言版本演进中对向后兼容的刻意保护。9. str 子类的rmod优先级bpo-28598支持str的子类在str.__mod__之前被调用__rmod__。补丁作者 Martijn Pieters。这修正了反射二元运算符reflected operand在%运算中的方法解析顺序。10. complex 构造函数对有符号零的处理bpo-29602修复complex构造函数对复数子类以及实现了__complex__的输入在有符号零signed zero如-0.0场景下的错误处理避免正负零信息丢失。补丁作者 Serhiy Storchaka。11. 其他核心修复一览bpo-29347创建 weakref 对象时可能解引用未定义指针bpo-29438key sharing dict 中的 use-after-free 问题bpo-29319阻止RunMainFromImporter覆盖sys.path[0]bpo-29337比较 code 对象时可能出现的BytesWarning编译期即可发出警告bpo-29478使用Compat32策略且指定max_line_lengthNone时该设置不再被忽略补丁作者 Mircea Cosbuc。四、标准库Library1. 并发与进程模块bpo-30886修复multiprocessing.Queue.join_thread()——即使线程是由创建队列的同一进程启动的现在也会等待线程完成bpo-24484避免 multiprocessing 清理过程中的竞态条件bpo-30414multiprocessing.Queue._feed后台线程在异常时不再从主循环退出增强鲁棒性bpo-30301修复SimpleQueue.empty()在spawn与forkserver启动方式下的AttributeErrorbpo-28699multiprocessing.pool中可迭代对象在第一个元素处抛异常时异常可能被吞掉或导致程序挂起的问题bpo-29861multiprocessing.Pool中任务完成后尽早释放对任务、参数与结果的引用bpo-30185forkserver辅助进程收到 Ctrl-C 时避免KeyboardInterrupttracebackbpo-29376修复threading._DummyThread.is_alive()的断言错误。2. asynciobpo-29870修复 asyncio/ssl 实现中连接中止时的 SSL socket 泄漏补丁作者 Michaël Sghaïerbpo-29743握手过程中关闭 transport 会泄漏打开状态的 socket补丁作者 Nikolay Kimbpo-27585修复asyncio.Lock中 waiter 取消的问题补丁作者 Mathieu Sornaybpo-29704asyncio.subprocess.SubprocessStreamProtocol不再在所有管道关闭前提前关闭bpo-29703支持在子进程中实例化新的事件循环bpo-30508调用Task/Future.cancel()时不再记录异常日志bpo-30048修复Task.cancel()在任务运行协程且协程在没有更多await的情况下返回时可能被忽略的问题bpo-29742在已关闭的 ssl transport 上调用get_extra_info()现在抛出异常补丁作者 Nikolay Kim。3. unittest.mockbpo-29403修复 autospec 在方法绑定的内建函数上失败的问题补丁作者 Aaron Gallagherbpo-28961修复unittest.mock._Call辅助类忽略name参数的问题补丁作者 Jiajun Huangbpo-28735修复mock.MagicMock与mock.ANY的比较。4. typing 模块系列更新bpo-28556 多条目新增泛型AsyncContextManager并在所有版本上支持ContextManager新增typing.NoReturn类型改用WrapperDescriptorType并修复若干小 bug新增typing.Counter、typing.ChainMap改进 ABC 缓存等bpo-29011补充遗漏的Deque类型。5. 路径、文件与导入bpo-30879os.listdir()与os.scandir()在传入 bytes 类参数时返回 bytes 名称bpo-30645修复imp.load_package()的路径计算解决包仅附带字节码时的加载问题补丁作者 Alexandru Ardeleanbpo-29694修复pathlib中mkdir(parentsTrue)的竞态条件补丁作者 Armin Rigobpo-25803避免 OS 优先返回EACCES而非EEXIST时Path.mkdir(exist_okTrue)抛出错误异常bpo-29416防止pathlib.Path.mkdir出现无限循环。6. subprocess 与 os.environbpo-30746在os.putenv()与os.spawn*()中禁止环境变量名包含字符与 bpo-30730 的 Windows 注入防护互为表里当前 Lib/subprocess.py 仍保留该校验bpo-30441修复在迭代os.environ的同时修改它的 bugbpo-29335修复子进程已退出到 stopped而非 terminated状态如处于 ptrace 下时subprocess.Popen.wait()的行为bpo-30418Windows 上若子进程仍在运行但已关闭管道subprocess.Popen.communicate()在stdin.write()时也忽略EINVAL。7. 网络与套接字bpo-30378修复logging.handlers.SysLogHandler无法处理 IPv6 地址的问题bpo-30205修复 Linux 上未绑定AF_UNIXsocket 的getsockname()bpo-30329imaplib与poplib捕获 Windows socket 在shutdown(SHUT_RDWR)时的WSAEINVAL错误码 10022该错误在 SSL 连接上偶发bpo-29142urllib.request中no_proxy环境变量带前导点的后缀能再次匹配相关主机名如.b.c匹配a.b.c补丁作者 Milan Oberkirch。8. 其他标准库修复精选bpo-30730 关联Windows subprocess 环境安全见安全节bpo-30807signal.setitimer()传入微小值如 1e-6时可能把定时器禁用而非重新调度修复后微秒级有效非零间隔被正确保留bpo-29755gettext 的lgettext()系列函数现在始终返回 bytesbpo-23890unittest.TestCase.assertRaises()手动打破引用环避免对象存活时间超出预期bpo-30149inspect.signature()支持用partialmethod包装的带可变参数的可调用对象补丁作者 Donghee Nabpo-29931修复ipaddress.ip_interface对象的比较检查bpo-28994atexit注册回调中抛出SystemExit时不再显示 tracebackbpo-28969修复 C 实现的functools.lru_cache竞态——满缓存时不同线程以相同未缓存参数并发调用可能抛出KeyErrorbpo-29532创建functools.partial()后修改传入的 kwargs 字典不再影响 partial 对象bpo-29800partial.__repr__在partial.keywords的键不是字符串时崩溃补丁作者 Michael Seifertbpo-29998ImportError的 pickle/复制现在保留name与path属性bpo-29942修复itertools.chain.from_iterable遇到长串空可迭代对象时的崩溃bpo-27863修复 ElementTree 因竞态与错误类型导致的多个崩溃bpo-30061 / bpo-30068IOBase的__next__()/readlines()在readline()或__next__()返回不可 size 对象时崩溃同时检查PyObject_Size()、PySequence_Size()、PyMapping_Size()的结果bpo-30070修复 parser 模块错误处理中的泄漏与崩溃bpo-30243移除_jsonscanner 与 encoder 的__init__方法误用可能导致内存泄漏或崩溃现在对象在__new__中完全初始化bpo-28298修复 array 类型Q、L、I不接受大整数实现__int__的对象作为元素的问题补丁作者 Oren Milmanbpo-29615SimpleXMLRPCDispatcher不再把KeyError或任何其他异常链接到被分发方法抛出的异常bpo-8256修复input()在sys.stdin/sys.stdout的encoding/errors属性未设置或非字符串时失败或崩溃的问题bpo-25455修复递归缓冲文件类对象的 repr 崩溃bpo-29884faulthandler 在 teardown 时恢复旧的sigaltstackbpo-29854使用 readline 的history-size选项时readline段错误补丁作者 Nir Sofferbpo-30961修复 tracemalloc 中递减借用引用borrowed reference的问题bpo-30532修复 email 头部值解析器在特定情况下丢弃折叠空白folding white space的问题bpo-29169zlib 更新至 1.2.11bpo-30003修复 HZ 编解码器对转义字符的处理基于 Ma Lin 的补丁bpo-29990修复 GB18030 解码器的范围检查原始补丁作者 Ma Linbpo-30375编译正则表达式时的警告现在总是指向用户代码所在行而非 re 模块内部bpo-29444修复 match 对象group()方法的越界缓冲区访问基于 WGH 的补丁bpo-29110aifc.open()传入文件系统路径但文件不是合法 AIFF 格式时文件对象泄漏补丁作者 Anthony Zhangbpo-29290修复 argparse 帮助信息在不换行空格处错误换行的回归bpo-29219修复未初始化ctypes.CDLL实例的 repr 无限递归bpo-29519修复解释器关闭期间 weakref 在 multiprocessing 与自定义 codecs 罕见组合下抛异常bpo-29100修复 Python 3.6.0 引入的datetime.fromtimestamp()回归检查最小与最大年份bpo-26293因 zipfile 破坏导致的变更另见 bpo-29094bpo-29692修复contextlib.contextmanager中RuntimeError被任意解除链unchaining的问题补丁作者 Siddharth Velankar。五、文档、测试与构建基础设施1. 文档Documentationbpo-30176在 curses 文档中补充缺失的属性相关常量bpo-26985在 inspect 文档中补充 code 对象的缺失信息bpo-28929为文档页链接到 GitHub 上的源码文件bpo-25008将smtpd.py标注为实际已弃用并指向第三方 asyncio 替代品 aiosmtpdbpo-26355每页增加指向对应主版本文档的 canonical 头部链接补丁作者 Matthias Bussonnierbpo-29349修复文档构建代码中的 Python 2 语法。2. 测试Testsbpo-30822修复 regrtest 命令行解析允许传递-u extralargefile以运行test_zipfile64bpo-30383从 master 分支反向移植并增强 regrtest——新增选项--coverage、--testdir、--list-tests仅列出测试文件不运行、--list-cases仅列出测试标识符不运行issue 30523、--matchfile从文本文件加载测试过滤列表issue 30540、--slowest--slow的别名输出增加时间戳、测试结果、当前运行测试与含总耗时的Tests result: xxx汇总同时修复--huntrleaks引用泄漏排查预先暖缓存、显式创建所有按需创建的内部单例避免引用泄漏检查的误报issue 30675bpo-30357test_thread的setUp()使用support.threading_setup()与support.threading_cleanup()等待线程完成避免对后续测试的随机副作用bpo-28087在 macOS 上跳过test_asyncore与test_eintr的 poll 失败以及部分select.poll测试bpo-30197增强test.support的swap_attr()与swap_item()——在 with 语句内删除被替换的属性/项也能正常工作旧值或不存在时为 None现在会赋给as子句的目标bpo-29571为匹配re.LOCALE行为test_re.test_locale_flag改用locale.getpreferredencoding(False)确定测试正则的候选编码默认区域编码为多字节编码时可正确跳过测试。3. 构建Buildbpo-29243配置--enable-optimizations后避免make test、make install等目标触发的非必要重建bpo-23404不再基于文件修改时间自动重新生成生成文件该操作改为显式执行——用make regen-all取代make touchbpo-29643修复--enable-optimization原文如此指优化构建开关未生效的问题。4. Windows 与 C APIbpo-30687Windows 构建时定位msbuild.exe而非vcvarsall.batbpo-29392防止向 msvcrt 模块传入无效参数时崩溃bpo-27867当Py_LIMITED_API设为 0x03050400 到 0x03060000不含之间或 0x03060100 及以上时PySlice_GetIndicesEx()函数被替换为宏。当前 Include/sliceobject.h 中仍保留函数声明与宏定义的共存结构是稳定 ABIlimited API演进的一个实例bpo-29083修复部分公共 API 函数的声明——PyArg_VaParse()与PyArg_VaParseTupleAndKeywords()此前在 limited API 中不可用PyArg_ValidateKeywordArguments()、PyArg_UnpackTuple()与Py_BuildValue()在定义PY_SSIZE_T_CLEAN时对版本 3.3 的 limited API 不可用。六、从 3.5.4rc1 看 CPython 维护分支的工程实践纵观本版变更记录可以提炼出 CPython 维护分支backport 版本的几条工程规律安全修复优先且成链expat 的两次升级bpo-29591 → bpo-30694属于上游出补丁、CPython 跟进打包的典型路径且对是否受影响做了逐 CVE 判断如 CVE-2016-5300 因 Python 已用XML_SetHashSalt注入熵而不受影响这种审慎态度值得下游发行版参考异常语义是核心稳定性的护城河bpo-30876相对导入异常类型、bpo-29600StopIteration 包装、bpo-29935index() 错误消息等修复都在收敛解释器把内部错误泄漏给用户的边界回归防护与测试基建同步增强bpo-29537 对旧字节码的兼容恢复、bpo-30383 对 regrtest 的大规模增强说明维护版本不仅修 bug还同步提升检测能力C API 与稳定 ABI 持续打磨bpo-27867、bpo-29083 直接关系到第三方扩展在 limited API 下的可用性是生态兼容的重要一环。对于仍在维护 3.5 系列或希望理解后续 3.x 版本相应行为的读者本文件与仓库中的 Lib/test/test_urlparse.py 等测试用例一起构成了验证这些修复行为是否仍然生效的可靠依据。七、如何在当前仓库中验证这些修复你可以在当前仓库中直接运行对应测试来验证上述修复的持续有效性仓库为只读仅需查看与运行测试# 验证 urllib.parse 的 splithost 片段解析bpo-30500 python -m test test_urlparse -m test_splithost # 验证 subprocess 环境变量名校验bpo-30730 / bpo-30746 python -m test test_subprocess # 运行标准库回归测试套件 python -m test test_multiprocessing test_asyncio test_unittest test_typing结合 Lib/test/test_urlparse.py 中# bpo-30500: # starts a fragment.的注释与断言、Lib/subprocess.py 中illegal environment variable name的校验以及 Modules/pyexpat.c 中的XML_SetHashSalt调用可以完整还原 3.5.4rc1 这批变更在解释器与标准库中的落地形态。【免费下载链接】cpythonThe Python programming language项目地址: https://gitcode.com/GitHub_Trending/cp/cpython创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考