E.2. 发布版本 13.22 #
发布日期:. 2025-08-14
本次发布包含来自 13.21 的多项修复。有关 13 主版本新特性的说明,请参见第 E.24 节。
PostgreSQL 社区将于 2025 年 11 月停止发布 13.X 系列的更新。建议用户尽快升级到较新的发布分支。
E.2.2. 变更
加强规划器估算函数中的安全检查(Dean Rasheed)§
针对 CVE-2017-7484 的修复及后续修复,旨在防止泄漏函数被应用于调用用户无权读取的列的统计数据。在该保护措施中发现了两个漏洞。其中一个漏洞适用于分区和继承层次结构,其中表上的 RLS 策略应当限制对统计数据的访问,但实际上并未限制。
另一个漏洞适用于查询通过视图访问表的情况,其中视图所有者有权读取底层表,但调用用户没有视图的权限。视图所有者的权限满足了安全检查,而泄漏函数会在我们检查调用用户对视图的权限之前就被应用于底层表的统计数据。此问题已通过在规划开始时对视图进行安全检查来修复。这可能会导致权限错误比之前更早发生。
PostgreSQL 项目感谢 Dean Rasheed 报告此问题。(CVE-2025-8713)
防止 pg_dump 脚本被用于攻击执行恢复的用户(Nathan Bossart)§ §
由于导出/恢复操作通常涉及以超级用户身份运行 SQL 命令,目标数据库安装必须信任源服务器。然而,这并不意味着执行 psql 进行恢复的操作系统用户也需要信任源服务器。这里的风险是,已获得源服务器超级用户级别控制权的攻击者可能会使其生成被解释为 psql 元命令的文本。这将提供对恢复用户自身帐户的 shell 级别访问,独立于对目标数据库的访问。
为了提供确保不会发生此问题的正面保证,扩展了 psql,增加了
\restrict命令来阻止执行后续的元命令,并让 pg_dump 在来自源服务器的任何数据之前发出该命令。PostgreSQL 项目感谢 Martin Rakhmanov、Matthieu Denais 和 RyotaK 报告此问题。(CVE-2025-8714)
在 pg_dump 输出的注释中,将名称中包含的换行符转换为空格(Noah Misch)§
包含换行符的对象名称提供了向输出脚本中注入任意 SQL 命令的能力。(如果没有前述的修复,通过这种方式注入 psql 元命令也是可能的。)CVE-2012-0868 曾在当时修复了这类问题,但后续的工作重新引入了若干情况。
PostgreSQL 项目感谢 Noah Misch 报告此问题。(CVE-2025-8715)
避免我们可接受的 XML 输入大小出现退化(Michael Paquier、Erik Wienhold)§ §
我们针对 libxml2 早期 2.13.x 版本中一个 bug 的变通方案使用了一个会拒绝超过 10MB 文本块的代码路径,而之前的代码不会这样做。那些早期版本在实际环境中大概已经不存在了,因此恢复到之前的代码。
允许具有语句级触发器的表成为分区或继承子表(Etsuro Fujita)§
我们不允许分区或继承子表拥有带有转换表的行级触发器,因为对整个继承树的操作需要为每个这样的子表维护单独的转换表。但这个问题不适用于语句级触发器,因为只有父表的语句级触发器会被触发。检查现有表是否可以成为分区或继承子表的代码却错误地拒绝了两种触发器。
禁止从外部子表收集转换元组(Etsuro Fujita)§
我们不支持在外部表上使用带有转换表的触发器。但是,分区或继承子表是外部表的情况被忽略了。如果父表有这样的触发器,就会从外部子表收集到不正确的转换元组。现在改为抛出错误,报告该情况不被支持。
缩短创建名称冲突索引时的竞态条件窗口(Tom Lane)§
在为索引选择自动生成的名称时,除了完全有效的行之外,也避免与尚未提交的
pg_class行冲突。这避免了可能选择与某个并发CREATE INDEX相同名称的问题,当该命令仍在填充其索引,或已完成但属于尚未提交的事务的一部分时。仍然存在问题窗口,但仅限于验证新索引参数并插入其pg_class行所需的时间。防止在单个命令中对多个表执行 vacuum 时使用不正确的
VACUUM选项(Nathan Bossart、Michael Paquier)§一个表的
TRUNCATE和INDEX_CLEANUP选项可能被应用到其他表上。修复
SIMILAR TO正则表达式中字符类的处理(Laurenz Albe)§ §将
SIMILAR TO模式匹配表达式转换为 POSIX 风格正则表达式的代码未考虑方括号可以嵌套的情况。例如,在类似[[:alpha:]%_]的模式中,代码将%和_字符当作元字符处理,而实际上它们应该是字面量。在反解析查询时,始终在
FETCH FIRST子句中的表达式周围添加括号(Heikki Linnakangas)§expressionROWS WITH TIES这避免了某些反解析结果在语法上无效的情况。
限制检查点进程的 fsync 请求队列大小(Alexander Korotkov、Xuneng Zhou)§ §
在
shared_buffers设置非常大时,检查点进程可能尝试为 fsync 请求分配超过 1GB 的内存,导致失败并进入无限循环。限制队列大小以防止此情况发生。避免在读取部分写入的 WAL 记录时逻辑解码出现无限等待(Vignesh C)§
如果服务器在写入跨越多个页面的 WAL 记录的第一部分后崩溃,后续对该 WAL 流的逻辑解码将等待下一个 WAL 页面上的数据到来。如果服务器此时处于空闲状态,这可能永远不会发生。
修复 ACL 字符串中角色名称引用的不一致问题(Tom Lane)§
之前的引用规则是与区域设置相关的,这在跨安装传输
aclitem值时可能导致可移植性问题。(pg_dump 不会这样做,但其他工具可能会。)为确保一致性,始终在aclitem输出中引用非 ASCII 字符;但为了保持向后兼容性,在aclitem输入期间从不要求必须引用它们。拒绝在关系选项和外部数据选项的名称中使用等号(
=)(Tom Lane)§没有明显的用例需要这样的选项名称,而允许它们会在存储表示中产生歧义。
避免 B-树索引扫描在罕见情况下将错误的索引条目标记为死条目(Peter Geoghegan)§
避免在逻辑复制期间重新分发来自其他事务的缓存失效消息(vignesh C)§ §
我们之前一轮小版本发布中包含了一个 bug 修复,确保复制接收进程响应跨进程的缓存失效消息,防止它们在执行复制更新时使用过时的系统目录数据。然而,该修复无意中使它们也重新分发了这些消息,导致失效消息数量呈指数增长,通常最终导致内存分配失败。通过不重新分发已接收的消息来修复此问题。
避免在检查点期间过早移除旧的 WAL(Vitaly Davydov)§
如果在检查点进行过程中复制槽的重启点被推进,不再需要的 WAL 段可能被过早移除,导致在数据库之后立即崩溃时恢复失败。通过将它们多保留一个检查点周期来修复此问题。
绝不将复制槽的已确认刷新位置向后移动(Shveta Malik)§
在某些情况下,复制客户端可能会确认一个超过其持久化存储位置的 LSN,然后在重启后可能发送一个更旧的 LSN。只要客户端在两个位置之间的 WAL 没有需要处理的内容,我们认为这不是一个 bug。但是,我们不应重新发送该 WAL 以避免数据重复,因此确保我们始终相信给定槽的最新已确认 LSN。
允许在备库上等待事务时被中断(Kevin K Biju)§
在备库上创建复制槽可能需要等待主库上的某些活动事务完成,然后在备库上重放。由于这可能是无限期的等待,允许取消该操作是可取的,但循环中没有查询取消的检查。
修复某些位置可能在没有任何快照的情况下尝试获取系统目录中经过 TOAST 处理的字段的问题(Nathan Bossart)§
这可能导致断言失败,或出现“cannot fetch toast data without an active snapshot”错误。
移除在
PortalRunMulti()结束时必须已确定命令标签的错误断言(Álvaro Herrera)§在边界情况下(例如空的预备语句)此断言会失败。
恢复在并行模式下运行 PL/pgSQL 表达式的能力(Dipesh Dhameliya)§
PL/pgSQL 中“表达式”的概念非常广泛,涵盖任何返回单列且不超过一行的 SQL
SELECT查询。因此在某些情况下,例如计算聚合函数时,查询涉及大量工作,使用并行工作进程来运行它会很有用。这以前是可能的,但之前的一个 bug 修复无意中禁用了它。修复 PL/Python 错误报告中的边界情况资源泄漏(Tom Lane)§ §
在报告来自 Python 的错误时发生内存不足故障,可能导致未能减少 Python 对象的引用计数,从而导致会话生命周期内的内存泄漏。
修复 libpq 的
PQport()函数,使其除非传入的连接为 NULL,否则永远不返回 NULL(Daniele Varrazzo)§这是文档中记录的行为,但最近的 libpq 版本在用户未提供端口规范的某些情况下会返回 NULL。恢复到我们历史上在此类情况下返回空字符串的行为。(v18 及更高版本将返回编译时的默认端口号,通常是
"5432"。)避免当 GSSAPI 认证需要大于 16kB 的数据包时出现失败(Jacob Champion、Tom Lane)§
属于许多 AD 组的 Active Directory 用户需要更大的认证数据包。此限制表现为连接失败并伴有难以理解的错误消息,通常是“GSSAPI context establishment error: The routine must be called again to complete its function: Unknown error”。
修复 SSL 和 GSSAPI 数据传输中的时序相关故障(Tom Lane)§
在非阻塞模式下使用 SSL 或 GSSAPI 加密时,libpq 有时会出现“SSL error: bad length”或“GSSAPI caller failed to retransmit all data needing to be retried”错误。
避免在 ecpg 应用程序中连接查找时的空指针解引用(Aleksander Alekseev)§
这种情况只有在应用程序同时存在命名连接和未命名连接时才会发生。
确保 pg_dump 以有效的顺序导出域约束上的注释(Jian He)§
在某些情况下,注释命令可能出现在约束创建之前。
确保 pg_dump 对所有类型的数据库对象具有稳定的排序顺序(Noah Misch、Andreas Karlsson)§ § §
pg_dump 在执行依赖关系驱动的重新排序之前,按逻辑名称对对象进行排序。此排序未考虑标识某些对象类型(如规则和约束)的完整唯一键,因此对于逻辑上相同的数据库可能产生不同的排序顺序。这使得通过比较 pg_dump 输出的 diff 来比较数据库变得困难,因此改进了逻辑以确保在所有情况下排序顺序都是稳定的。
在 pg_upgrade 中,检查不一致的继承非空约束(Ali Akbar)§ § § § § §
18 之前的 PostgreSQL 版本允许删除继承列的非空约束。但是,这会导致无法恢复的模式,从而导致 pg_upgrade 失败。在 pg_upgrade 的预检查中检测此类情况,以便用户在启动升级之前修复它们。
避免在 initdb 期间启用
track_commit_timestamp时的断言失败(Hayato Kuroda、Andy Fan)§避免在
contrib/dblink连接建立过程中可能泄漏已打开的连接(Tom Lane)§在将新连接对象插入 dblink 的 hash 表时遇到内存不足的罕见场景中,已打开的连接会泄漏直到会话结束,在远程服务器上留下一个空闲会话。
使
contrib/pg_prewarm能够处理非常大的shared_buffers设置(Daria Shanina)§如果
shared_buffers大于约 5000 万个缓冲区(400GB),autoprewarm 就会因内存分配错误而失败。在
contrib/pg_stat_statements中,避免在规范化查询中使用的参数编号出现间隔(Sami Imseih)§修复
contrib/postgres_fdw的 DirectModify 方法中的内存泄漏(Tom Lane)§如果查询在 DirectModify 方法的调用之间失败,保存远程修改命令结果的
PGresult将在会话的剩余时间内泄漏,当有RETURNING数据需要处理时可能会发生这种情况。确保 configure 的
--with-includes和--with-libraries选项中列出的目录在系统提供的目录之前被搜索(Tom Lane)§使用这些选项的一个常见原因是允许用户自行构建的库版本覆盖系统提供的版本。然而,在某些环境中,由于 makefile 中发出的命令中开关顺序不当,这无法正常工作。
修复 configure 对
__cpuid()和__cpuidex()的检测(Lukas Fittl、Michael Paquier)§configure 未能检测到这些 Windows 特有的函数,因此它们不会被使用,导致 CRC 计算比必要的慢,因为无法验证硬件指令的可用性。此错误的实际影响有限,因为 Windows 的生产构建通常不使用 Autoconf 工具链。
修复在基于 Solaris 的平台上使用
--with-pam选项时的构建失败(Tom Lane)§Solaris 在 PAM 认证的 API 方面与其他 Unix 平台不一致。这表现为一个“inconsistent pointer”编译器警告,我们之前一直没有处理。但从 GCC 14 开始,默认情况下这是一个错误而不是警告,因此进行了修复。
使我们的代码可移植到 GNU Hurd(Michael Banck、Christoph Berg、Samuel Thibault)§
修复了关于
IOV_MAX和O_RDONLY在 Hurd 上不成立的假设。使我们对
memset_s()的使用严格遵循 C11 标准(Tom Lane)§这避免了在某些平台上的编译失败。
防止 JSONB 比较代码中的未初始化值编译器警告(Tom Lane)§
避免在使用 libxml2 2.14 及更高版本构建时出现弃用警告(Michael Paquier)§
避免在 C++ 下编译
pg_locale.h时的问题(John Naylor)§PostgreSQL 头文件通常需要用
extern "C" { ... }包裹才能在用 C++ 编写的扩展中被包含。对于pg_locale.h,由于它使用了 libicu 头文件,这会失败,但我们可以通过在这些头文件中抑制仅限 C++ 的声明来解决此问题。想要使用 libicu 的 C++ API 的 C++ 扩展可以在包含pg_locale.h之前先包含 libicu 头文件。