E.4. 发布版本 16.12 #
发布日期:. 2026-02-12
本次发布包含来自 16.11 的多项修复。有关 16 主版本新特性的说明,请参见第 E.16 节。
E.4.2. 变更 #
防止
oidvector/int2vector出现意外的维度(Tom Lane)§这些数据类型预期为不含空值的一维数组,但某些类型转换路径允许违背这些预期。现已为一些原本依赖这些预期却未加验证的函数补充检查,因为它们可能因此产生错误行为。
PostgreSQL 项目感谢 Altan Birler 报告此问题。(CVE-2026-2003)
增强选择率估算器在被附加到接受非预期数据类型的操作符时的防护(Tom Lane)§ § §
contrib/intarray包含一个选择率估算函数;由于它未检查输入是否为预期的数据类型,该函数可被滥用来执行任意代码。第三方扩展也应检查是否存在类似风险,并采用 intarray 现在使用的技术来增加防护。由于此类扩展的修复需要时间,我们现在要求具有超级用户权限,才能将非内置的选择率估算器附加到操作符上。PostgreSQL 项目感谢 Daniel Firer(zeroday.cloud 成员)报告此问题。(CVE-2026-2004)
修复
contrib/pgcryptoPGP 解密函数中的缓冲区溢出问题(Michael Paquier)§解密带有超长会话密钥的精心构造消息会导致缓冲区溢出,严重时甚至可能执行任意代码。
PostgreSQL 项目感谢 Team Xint Code(zeroday.cloud 成员)报告此问题。(CVE-2026-2005)
修复多字节字符长度验证不充分的问题(Thomas Munro,Noah Misch)§ § § § § §
多处漏洞使攻击者只要能够发出精心构造的 SQL,就可能溢出字符串缓冲区,严重时甚至可以执行任意代码。应用这些修复后,当字符串函数处理数据库中存储的无效文本时,应用程序可能会看到“invalid byte sequence for encoding”错误。
PostgreSQL 项目感谢 Paul Gerste 和 Moritz Sanft(zeroday.cloud 成员)报告此问题。(CVE-2026-2006)
不允许由子查询中的 CTE 引用决定聚合函数的语义层级(Tom Lane)§
此变更撤销了两个小版本之前引入的一项更改;现在,如果某个子查询引用的 CTE 所处层级低于按标准 SQL 规则依据其中的列引用和聚合所判定的聚合语义层级,将抛出错误。先前的修复方案本身也带来了问题,而且目前尚不清楚应如何处理。由于 SQL 标准本就完全不允许在聚合中包含子查询,将此类情况视为错误似乎已经足够。
修复 CTE 查询中
MERGE的触发器过渡表捕获问题(Dean Rasheed)§当执行包含
MERGE和另一个对具有语句级AFTER触发器的表的 DML 操作的数据修改 CTE 查询时,传递给触发器的过渡表将不包含MERGE影响的行,而只包含其他操作影响的行。修复当分区目标表的所有子表在 UPDATE 或 DELETE 操作中都被剪枝时的失败问题(Amit Langote)§
在这种情况下,执行器可能报告“could not find junk ctid column”错误,即使实际上无需执行任何操作。
避免当查询包含重复的窗口函数调用时规划器可能出现的失败(Meng Zhang,David Rowley)§
对此类调用去重时的混淆可能导致诸如“WindowFunc with winref 2 assigned to WindowAgg with winref 1”之类的错误。
允许在部分 hash 索引上进行索引扫描,即使索引的谓词蕴含 WHERE 子句的真值(Tom Lane)§
通常我们会删除被谓词蕴含的 WHERE 子句,因为测试它没有意义——对于每个索引条目,该条件必然成立。然而,如果索引是需要在前导索引键上有 WHERE 子句的类型(如 hash 索引),这样做可能阻止创建索引扫描计划。在考虑此类索引时,不要删除被蕴含的子句。
不要为不记录 WAL 的 BRIN 索引生成 WAL(Kirill Reshke)§
一条很少执行到的代码路径错误地为 BRIN 索引生成了 WAL 记录,即使该索引被标记为不记录 WAL。崩溃恢复时将无法重放该记录,并报告文件已存在的错误。
防止截断未读
NOTIFY消息仍然需要的 CLOG(Joel Jacobson,Heikki Linnakangas)§ § §此修复防止了当后端进程吸收
NOTIFY消息较慢时出现的“could not access status of transaction”错误。将
NOTIFY消息处理期间发生的错误升级为 FATAL,即关闭连接(Heikki Linnakangas)§以前,如果后端在吸收
NOTIFY消息时遇到错误,它会跳过该消息,向客户端报告错误,然后继续运行。但这种行为存在很多问题。一个主要问题是,客户端没有好的方法来知道通知丢失了,更无法知道通知的内容是什么。根据应用逻辑的不同,错过一条通知可能导致应用程序卡在等待状态。此外,剩余的消息在有人发送新的NOTIFY之前不会被处理。另外,如果连接在接收到
NOTIFY信号时处于空闲状态,由于无关的原因,任何 ERROR 都会被升级为 FATAL。因此,我们选择在所有情况下都这样做,以保持一致性,并向应用程序提供一个明确的信号,表明它可能错过了一些通知。修复在锁定元组时跟踪更新链的错误(Jasper Smit)§
此代码路径忽略了检查更新链中第一个新元组的 xmin,使得在原始更新者中止且空间被
VACUUM立即回收并重新使用的情况下,可能会锁定一个不相关的元组。这可能导致意外的事务延迟或死锁。与识别到错误元组相关的错误也已被观察到。修复原地更新系统目录时的问题(Noah Misch)§ § §
对于原地更新,发送非事务性的失效消息,因为此类更新在事务回滚后仍会保留。同时,确保该更新在其他会话可见之前已经写入 WAL。这些修复主要防止关系的 frozen-XID 属性出现不一致,从而避免 CLOG 被过早截断并随后出现“could not access status of transaction”错误。
修复后端进程在退出时由于尝试在已取消映射的共享内存段中释放锁而可能崩溃的问题(Rahila Syed)§
防止崩溃后多事务日志被错误截断(Heikki Linnakangas)§
修复
pg_stat_get_backend_activity()可能返回编码错误的结果的问题(Chao Li)§保存会话活动字符串的共享内存缓冲区末尾可能包含不完整的多字节字符。读取者应该截断掉任何此类不完整字符,但此函数未能做到这一点。
防止递归的内存上下文日志记录(Fujii Masao)§
持续不断的请求内存上下文日志记录的信号流可能导致日志记录代码的递归执行,理论上可能导致栈溢出。
修复重新初始化并行执行上下文时的内存上下文使用问题(Jakub Wartak,Jeevan Chalke)§
此错误可能由于附属数据结构的生命周期比并行上下文更短而导致崩溃。目前尚未发现仅使用 PostgreSQL 核心就能触发该问题的情况,但我们收到了扩展中出现问题的报告。
在创建新的多事务 ID 时设置下一个多事务 ID 的偏移量,以消除在边界情况下所需的等待循环(Andrey Borodin)§ §
之前的逻辑可能会卡在等待一个永远不会发生的更新上。
避免多次重写数据修改 CTE(Bernice Southey,Dean Rasheed)§
以前,在更新自动可更新视图或带规则的关系时,如果原始查询含有数据修改 CTE,重写器会由于递归而多次重写这些 CTE。这不仅低效,而且当 CTE 包含对 GENERATED ALWAYS 列的更新时可能产生虚假错误。
如果 WAL 未涵盖检查点记录指示的重做点,则使恢复失败(Nitin Jadhav)§
在开始恢复之前添加一个显式检查,以确保不会造成损害并提供有用的错误消息。以前,在这种情况下恢复可能会崩溃或损坏数据库。
避免在
ALTER PUBLICATION期间修改源查询树(Sunil S)§此错误的可见效果是,为该查询触发的事件触发器只能看到第一个
publish选项,即使指定了多个选项。如果此类查询被设置为预备语句,重新执行时也会出现错误行为。将
CREATE SUBSCRIPTION ... CONNECTION中指定的连接选项传递给发布端的 walsender 进程(Fujii Masao)§在此修复之前,
options连接选项(如果有的话)会被忽略,因此,例如无法在 walsender 会话中设置自定义服务器参数值。该功能本应正常工作;在 PostgreSQL 15 中的重构破坏它之前,它也确实一直是正常工作的,因此这里恢复了先前的行为。防止新创建或新同步的复制槽被无效化(Zhijie Hou)§
与并发检查点的竞争条件可能导致复制槽所需的 WAL 被删除,使得该槽立即被标记为无效。
修复计算复制槽所需 xmin 时的竞争条件(Zhijie Hou)§
这可能导致错误“cannot build an initial slot snapshot as oldest safe xid follows snapshot's xmin”。
在逻辑复制订阅的初始同步期间,在开始复制数据之前提交
pg_replication_origin条目的添加(Zhijie Hou)§以前,如果复制步骤失败,新的
pg_replication_origin条目会因事务回滚而丢失,从而导致共享内存中的状态不一致。在并行工作进程应用失败后不推进逻辑复制进度(Zhijie Hou)§
之前的行为允许订阅者丢失事务。
修复流复制副本服务器重启期间可能出现的“unexpected data beyond EOF”失败问题(Anthonin Bonnefoy)§
修复解析分区范围边界时对列位置的错误跟踪(myzhen)§
这可能导致在关于将分区边界值转换为列的数据类型的错误消息中引用错误的列名。
修复错误消息中的各种小错误(Man Zeng,Tianchen Zhang)§ § §
例如,关于备份清单中时间线编号不匹配的错误报告在应该显示结束时间线编号的地方显示了起始时间线编号。
修复在使用 LLVM 17 或更高版本进行 JIT 编译时无法执行函数内联的问题(Anthonin Bonnefoy)§
调整我们的 JIT 代码以兼容 LLVM 21(Holger Hoffstätte)§
之前的代码在 aarch64 机器上编译失败。
增加新的服务器参数 file_extend_method 来控制
posix_fallocate()的使用(Thomas Munro)§PostgreSQL 版本 16 及更高版本会使用
posix_fallocate()(如果平台提供的话)来扩展关系文件。然而,据报告这与某些文件系统交互不良:BTRFS 压缩会因使用posix_fallocate()而被禁用,而在较旧的 Linux 内核版本中 XFS 可能会产生虚假的ENOSPC错误。为提供一种解决方案,引入了这个新的服务器参数。将file_extend_method设置为write_zeros将使服务器回退到通过写入全零数据块来扩展文件的旧方法。在 Windows 上遵守
open()的O_CLOEXEC标志(Bryan Green,Thomas Munro)§ § §使此标志像在 POSIX 平台上一样工作,以避免将文件句柄泄漏到子进程(如
COPY TO/FROM PROGRAM)中。虽然该泄漏没有造成太多问题,但它似乎是不可取的。修复在使用 meson 构建的 Solaris 可执行文件中无法解析服务器命令行长选项的问题(Tom Lane)§
支持在 GNU/Hurd 上更改进程标题(Michael Banck)§
使 pg_resetwal 在更改 OldestXID 时打印更新后的值(Heikki Linnakangas)§
它对可以更改的其他每个变量都已经这样做了。
使 pg_resetwal 允许将下一个多事务 xid 设置为 0 或将下一个多事务偏移量设置为 UINT32_MAX(Maxim Orlov)§
这些是有效的值,因此拒绝它们是不正确的。在最坏的情况下,如果恰好在多事务回卷点尝试 pg_upgrade,升级将失败。
在
contrib/amcheck中,为 B-树索引父节点检查使用正确的快照(Mihail Nikalayeu)§之前的代码在检查使用
CREATE INDEX CONCURRENTLY创建的索引时会产生虚假错误。修复
contrib/amcheck以正确处理“半死亡” B-树索引页面(Heikki Linnakangas)§amcheck期望此类页面有一个父级下行链接,但实际上没有,导致关于“mismatch between parent key and child high key”的虚假错误报告。修复
contrib/amcheck以正确处理不完整的 B-树根页面分裂(Heikki Linnakangas)§amcheck可能会报告关于“block is not true root”的虚假错误。修复
contrib/intarray中@@选择率估算器的边界情况整数溢出问题(Chao Li)§这可能导致在涉及最大整数值的情况下产生不准确的选择率估算。
修复
contrib/ltree中的多字节编码问题(Jeff Davis)§之前的代码可能将不完整的多字节字符传递给
lower(),可能导致不正确的行为。将时区数据文件更新到 tzdata 2025c 版本(Tom Lane)§
唯一的变更是下加利福尼亚 1976 年之前时间戳的历史数据。
报告文档问题
阅读 上游文档. 通过 PostgreSQL 文档反馈表单.