Backport CVE on REL_2_STABLE - #1903
Open
reshke wants to merge 19 commits into
Open
Conversation
The core of this patch is to prevent array_to_tsvector() from generating invalid tsvectors. It did not check for overly-long lexemes (so that WordEntry.len fields could overflow), nor did it check that the total "datalen" fits within MAXSTRPOS (so that WordEntry.pos fields could overflow, and the number of entries in the tsvector could be much more than the normal limit). While the field overflows couldn't do anything much worse than produce a corrupted tsvector value, a sufficiently large number of tsvector entries could cause integer overflows in later processing, such as tsvectorout. Another important fix is to prevent tsvectorrecv() from accepting invalid tsvectors. The main problem there is that it did not reject empty-string lexemes. Hence, even though it did (mostly) enforce the MAXSTRPOS limit, it could still produce a result with an unreasonable number of tsvector entries, if they were primarily empty strings. Also, fix tsvectorout's calculation of its required output buffer size: it was multiplying the string lengths by pg_database_encoding_max_length() for no reason. That contributed to the risk of integer overflow there. With valid tsvector input, there's no risk, but there's still no reason to make the output buffer several times bigger than needed. I also tried to make a couple of related routines more robust, and spent some effort on improving the comments in ts_type.h. Also, standardize on a single spelling of the "string is too long for tsvector" message, using %zu instead of an assortment of formats. These changes aren't security per se but came out of inspecting the code for problems. Reported-by: Yuhang Wu <yuhang@depthfirst.com> and Zhenpeng Lin Reported-by: Zheng Yu <zheng@depthfirst.com> Reported-by: Hcamael <baiyjrh@gmail.com> Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Amit Langote <amitlangote09@gmail.com> Backpatch-through: 14 Security: CVE-2026-14662
The only overflow hazards I could find in tsquery construction are in QTN2QT(), which builds a flat tsquery datum from the QTNode tree representation used by tsquery_or, tsquery_rewrite, and allied functions. There are two: 1. It seems theoretically possible for the outputs of cntsize() to overflow an int, so I widened them to size_t. There's no hazard certainly in tsquery_or and friends, but tsquery_rewrite could expand the query tree by large multiples (by replacing many identical subtrees with a large replacement tree), so in a 64-bit machine with plenty of available memory it should be possible to build a QTNode tree large enough to cause that. If these counters did overflow then we'd under-allocate the output tsquery and have a heap overwrite problem. size_t is sufficient, since it's counting the size of a subset of an in-memory data structure. We also have to fix the TSQUERY_TOO_BIG() macro to not get confused if sumlen exceeds MaxAllocSize. 2. fillQT() neglects to check that the new "distance" value for a QI_VAL item fits into the available 20-bit field. It's quite easy to reach this, for example by tsquery_or'ing two near-megabyte-sized tsquerys. However, the result is only a corrupt tsquery that does not represent the expected query, so perhaps this doesn't rise to the level of a security bug. Nonetheless it should be fixed. Note: I followed the practice used in other tsquery code of checking each distance value as it's assigned, which means that the last operand string could extend past the MAXSTRPOS boundary. This is a bit different from the pattern used for tsvectors, which insist that the total data length not exceed MAXSTRPOS and thereby avoid making per-item checks. Perhaps that should be harmonized sometime, but for now it's okay for the two types to do this differently as long as each one is self-consistent. Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Amit Langote <amitlangote09@gmail.com> Backpatch-through: 14 Security: CVE-2026-14662
setup_regexp_matches() sizes the buffer used to convert matched substrings back from pg_wchar form at the smaller of maxlen*eml and the original string's byte length, on the assumption that such a conversion cannot produce more bytes than the string it came from. That assumption holds only for validly encoded input. But pg_mb2wchar_with_len() silently accepts bytes that are invalid in the database encoding, turning each such byte into one pg_wchar, and converting that back can take more bytes than the input did. A string made of such bytes therefore overruns the conversion buffer by up to its own length, corrupting the following memory. regexp_match(), regexp_matches(), regexp_split_to_table() and regexp_split_to_array() are all affected. Fix by dropping the tighter bound and always allocating maxlen*eml + 1 bytes. Reported-by: Francesco Verardi <frevadiscor89@gmail.com> Author: Masahiko Sawada <sawada.mshk@gmail.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Backpatch-through: 14 Security: CVE-2026-14664
The special case here for estimating conditions involving a ctid column failed to check that the RHS constant is of type tid. While that'd always be true for the built-in operators that reference this selectivity estimator, a maliciously constructed operator could provide a user-controlled Datum value that would get interpreted as an ItemPointer pointer. That at least risks SIGSEGV, and perhaps with a bit of sweat it could be used for server memory disclosure. Reported-by: Hcamael <baiyjrh@gmail.com> Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Noah Misch <noah@leadboat.com> Backpatch-through: 14 Security: CVE-2026-14668
MatchNamedCall's arggiven array was declared FUNC_MAX_ARGS long, but we may actually use up to pronallargs elements, and that can be more than FUNC_MAX_ARGS if the function has OUT arguments (cf. ProcedureCreate). Convert it to a palloc'd array. Reported-by: Zheng Yu <zheng@depthfirst.com> Reported-by: ylwangtju <ylwangtju@qq.com> Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Michael Paquier <michael@paquier.xyz> Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com> Backpatch-through: 14 Security: CVE-2026-14679
The maximum number of arguments allowed for an aggregate function is FUNC_MAX_ARGS-1 (since the underlying transfn and/or finalfn will be called with one more argument). parse_func.c failed to enforce this, allowing construction of calls that would try to pass FUNC_MAX_ARGS+1 to the underlying functions, resulting in a memory stomp in the executor. Add correct checking there. Since it's possible that a bad call has been stored in a view or SQL function, also add checks in various aggregate-related and window-function-related code that there are not more than FUNC_MAX_ARGS arguments. These will also protect us against the possibility that we're trying to run a stored view that was made by a server executable with different FUNC_MAX_ARGS. (Arguably, that scenario does not qualify as a security problem. But let's just tighten up all of this while we're here, rather than split hairs over whether an overrun is reachable.) Likewise check in compute_function_hashkey. Here the hazard is directly from a pg_proc row, but the scenario is the same. PL/Tcl has a similar issue with a fixed-size string buffer. Let's just replace that buffer with a Tcl_DString, removing the whole issue and making the code look more like what's around it. There are a lot of other FUNC_MAX_ARGS-sized arrays, but the rest have nearby guards already, some with comments explicitly pointing out the hazard of FUNC_MAX_ARGS changing. I also used palloc_array() in a few related places in funcapi.c. Those aren't live hazards AFAICS, but nearby code has been palloc_array-ified already, so it seemed inconsistent to not use it here. Reported-by: Masahiko Sawada <sawada.mshk@gmail.com> Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com> Backpatch-through: 14 Security: CVE-2026-14679
The CACHESIGN.sign field is a BITVECP, not a TRGM, so you should not use GETSIGN() on it. You don't get a compiler warning because the GETSIGN() macro includes a cast. It resulted in a bogus read beyond end of buffer, which would cause bad split decisions or a crash if you're very unlucky. Reported-by: Mehmet D. INCE <mehmet@mehmetince.net> Backpatch-through: 14 Security: CVE-2026-14678
Some of these could overflow on 32-bit systems with the right input. Convert all cases where we called palloc() with multiplication to fix them. Not all of them were bugs, but it's better to be safe than sorry. Reported-by: Tulya Project, Team Dhiutsa, Bitecope Technologies Private Ltd Backpatch-through: 14 Security: CVE-2026-14677
ECPG assumes that any bytea data it receives from a backend starts with '\x' as its first two bytes, but a check was missed to enforce that. A rogue server sending some garbage bytea data would be able to crash a client, resulting in a client-side DoS, in the most common cases. Reported-by: ylwangtju <ylwangtju@qq.com> Backpatch-through: 14 Security: CVE-2026-16241
The parser accepts any string as an EXTRACT() field name, but deparsing does not quote and escape it accordingly. To fix, quote and escape the field name during deparsing as needed. It might be a good idea to validate the field name during parsing and deparsing, too, but that is left as a future exercise. Reported-by: Ben Morris in collaboration with Claude and Anthropic Research Author: Nathan Bossart <nathandbossart@gmail.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Etsuro Fujita <etsuro.fujita@gmail.com> Security: CVE-2026-15741 Backpatch-through: 14
When an EXECUTE or FETCH statement is executed, there are two portals: an outer portal that is created for the EXECUTE or FETCH statement itself, and an inner portal for the statement being executed on its behalf. Before this commit, nothing checked that these two portals agreed on the tuple descriptor of the rows being returned. This can be leveraged to disclose server memory contents and achieve arbitrary code execution. To prevent that, we can make use of an existing safety mechanism, added by Tom Lane in commit 2f48ede, which allows a tuplestore DestReceiver to be informed of the tupleDesc required by the caller, and which will cause an ERROR to occur if that doesn't match the tupleDesc of what emerges from the executor (modulo dropped columns, which aren't an issue in the case at hand). Reported-by: Ben Morris in collaboration with Claude and Anthropic Research Reported-by: Peter Geoghegan <pg@bowt.ie> Reviewed-by: Michael Paquier <michael@paquier.xyz> Security: CVE-2026-16239
This omission allowed roles without USAGE on a type to create range types that depend on it, which could prevent the owner from changing the type later. Reported-by: Jingzhou Fu <fuboat@outlook.com> Author: Nathan Bossart <nathandbossart@gmail.com> Reviewed-by: Noah Misch <noah@leadboat.com> Reviewed-by: Robert Haas <robertmhaas@gmail.com> Security: CVE-2026-6470 Backpatch-through: 14
This omission allowed roles without USAGE on a type to create tables that depend on it, which could prevent the owner from changing the type later. Reported-by: Nathan Bossart <nathandbossart@gmail.com> Author: Nathan Bossart <nathandbossart@gmail.com> Reviewed-by: Robert Haas <robertmhaas@gmail.com> Security: CVE-2026-6470 Backpatch-through: 14
Role membership, role attribute, and database ownership changes may impact the expected behavior of row-level security policies, but currently the plan cache doesn't take notice. To fix, register syscache callbacks on pg_auth_members, pg_authid, and pg_database that invalidate the role-dependent plans. Changes to other databases' pg_database rows are ignored. Reported-by: Ilya Staroverov <i.staroverov@ftdata.ru> Reported-by: Shinya Kato <shinya11.kato@gmail.com> Author: Ilya Staroverov <i.staroverov@ftdata.ru> Author: Shinya Kato <shinya11.kato@gmail.com> Co-authored-by: Nathan Bossart <nathandbossart@gmail.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Security: CVE-2026-14666 Backpatch-through: 14
When we implemented \if ... \endif in psql, we arranged to save/restore the lexer's parenthesis depth counter across any chunk of input that we're ignoring. At the time, that was sufficient, because no other part of PsqlScanState could need to be restored to its prior value. However, commit e717a9a and follow-ons added more state fields that ought to be restored to their prior values. A problem would only be observed if someone tries to \if out a portion of a CREATE FUNCTION/PROCEDURE command that is relevant to BEGIN/END matching, which seems like a pretty unusual usage, so the lack of field reports isn't surprising. Nonetheless it's a bug. To fix, replace the simple counter field in ConditionalStack entries with a pointer to a struct defined by psqlscan_int.h. (In the back branches, keep the old field and associated functions to minimize the risk of API/ABI breakage, even though it seems unlikely that any third-party code is using this. Making the new struct private to psqlscan-related code should prevent API/ABI issues for future additions of this type.) In itself this is only a minor bug fix, but it's prerequisite infrastructure for the fix for CVE-2026-6464, which will add another such field. Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Noah Misch <noah@leadboat.com> Backpatch-through: 14 Security: CVE-2026-6464
PGP encryption was using px_cipher_encrypt without checking if any error was returned. When OpenSSL is running in FIPS mode, or when the legacy provider hasn't been loaded, not all ciphers which are supported by the PGP code are available and fail the init step in px_cipher_encrypt. Since the PGP encryption failed to notice this it XORed the non-encrypted block with the plaintext, effectively disabling the encryption. This was found due to a report of PGP encryption not respecting the pgcrypto.builtin_crypto_enabled flag and allowing Blowfish and DES. This however turned out to be a false positive, since the PGP code only use ciphers from OpenSSL and not the built in ciphers. Bug: #19457 Reported-by: Shishir Sharma <ansh01072001@gmail.com> Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com> Discussion: https://postgr.es/m/19457-4bab15c17aea36c7@postgresql.org Security: CVE-2026-14663 Backpatch-through: 14
The previous commit raises an ERROR during PGP operations if OpenSSL does not support the cipher in use. However, any existing messages created with faulty encryption will no longer be accessible via pgp_[sym|pub]_decrypt(). To help users out of this situation, add a new ignore-cipher-failure option which reverts to the broken behavior during decryption only. A faulty encryption wrapper, created by an OpenSSL configuration that does not support the cipher, can then be stripped back off by that same OpenSSL in order to safely reencrypt it. (Note that when OpenSSL does support the cipher, corrupted messages will not be decrypted regardless of the ignore-cipher-failure setting; this is unchanged.) The new tests add a corrupted Blowfish message for both public- and symmetric-key decryption, resulting in the following test matrix: - Blowfish supported, default behavior: fails to decrypt - Blowfish supported, ignore-cipher-failure: fails to decrypt - Blowfish unsupported, default behavior: fails to load cipher - Blowfish unsupported, ignore-cipher-failure: strips faulty encryption The previous commit's change to the pubkey tests is expanded similarly: correctly encrypted messages cannot be decrypted by an OpenSSL that does not support the cipher, regardless of the option's setting, though the failure mode will change. Suggested-by: Noah Misch <noah@leadboat.com> Reviewed-by: Daniel Gustafsson <daniel@yesql.se> Reviewed-by: Noah Misch <noah@leadboat.com> Security: CVE-2026-14663 Backpatch-through: 14
This oversight in commit 71ea0d6795 allows a malicious server to inject shell commands into plain-text dump output that are run at restore time on the machine running psql. To fix, interpret all text after \unrestrict until the end of the line as its argument. Reported-by: Lucas Velgus <velgusgus599@gmail.com> Reported-by: Filip Janus <fjanus@redhat.com> Reported-by: Daniel Bakker <daniel@jackds.nl> Author: Nathan Bossart <nathandbossart@gmail.com> Reviewed-by: Robert Haas <robertmhaas@gmail.com> Reviewed-by: Noah Misch <noah@leadboat.com> Security: CVE-2026-18408 Backpatch-through: 14
While typical abbreviations are only a few bytes long, a user-supplied time_zone setting could specify a much longer abbreviation, enough to overflow to_char's allocation of 12 bytes per format character. If so, throw an error in the same style as commit 9241c84 (CVE-2015-0241). Reported-by: Hcamael <baiyjrh@gmail.com> Reported-by: Amjad Shahzad <amjadshahzad2000@gmail.com> Reported-by: Tan Zhen of AntAISecurityLab <TanZhen.AntAI@outlook.com> Reported-by: Tomer Fichman <tomer@irregular.com> Reported-by: Zheng Yu <zheng@depthfirst.com> Reported-by: Amy Burnett (OpenAI Codex Security) Reported-by: Rick de Jager <rick@v12.sh> Reported-by: Heewon Song <asteria121@78researchlab.com> Reported-by: Sylvie Mayer <smayer@cloudflare.com> Reported-by: Aleksander Alekseev <aleksander@tigerdata.com> Reported-by: Hillai Ben Sasson <hillai.bensasson@wiz.io> Author: Tom Lane <tgl@sss.pgh.pa.us> Backpatch-through: 14 Security: CVE-2026-14669
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #ISSUE_Number
What does this PR do?
Type of Change
Breaking Changes
Test Plan
make installcheckmake -C src/test installcheck-cbdb-parallelImpact
Performance:
User-facing changes:
Dependencies:
Checklist
Additional Context
CI Skip Instructions