mirror of
https://github.com/postgres/postgres.git
synced 2026-06-09 00:32:10 -04:00
Fix tuple deforming with virtual generated columns
TupleDescFinalize() failed to take into account virtual generated
columns, which are always stored as NULL in tuples. TupleDescFinalize()
didn't check for this, and that could result in attcacheoff being set for
and beyond virtual generated columns. Also, the TupleDesc's
firstNonGuaranteedAttr could also be set incorrectly, which could result
in the tuple deformation function deforming without checking for NULLs,
and deforming using incorrectly cached offsets.
This could result in tuples being deformed incorrectly, which could
result in incorrect results, ERRORs or possibly a crash.
This has been broken since c456e39113.
Author: Chao Li <li.evan.chao@gmail.com>
Reported-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: ChangAo Chen <cca5507@qq.com>
Reviewed-by: David Rowley <dgrowleyml@gmail.com>
Discussion: https://postgr.es/m/A4BC563C-0CA3-4EF3-952A-EA41F9E5BF1E%40gmail.com
This commit is contained in:
parent
193a4ded94
commit
89eafad297
2 changed files with 18 additions and 2 deletions
|
|
@ -517,6 +517,7 @@ TupleDescFinalize(TupleDesc tupdesc)
|
|||
for (int i = 0; i < tupdesc->natts; i++)
|
||||
{
|
||||
CompactAttribute *cattr = TupleDescCompactAttr(tupdesc, i);
|
||||
Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
|
||||
|
||||
/*
|
||||
* Find the highest attnum which is guaranteed to exist in all tuples
|
||||
|
|
@ -525,10 +526,18 @@ TupleDescFinalize(TupleDesc tupdesc)
|
|||
*/
|
||||
if (firstNonGuaranteedAttr == tupdesc->natts &&
|
||||
(cattr->attnullability != ATTNULLABLE_VALID || !cattr->attbyval ||
|
||||
cattr->atthasmissing || cattr->attisdropped || cattr->attlen <= 0))
|
||||
cattr->atthasmissing || cattr->attisdropped ||
|
||||
cattr->attlen <= 0 ||
|
||||
attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL))
|
||||
firstNonGuaranteedAttr = i;
|
||||
|
||||
if (cattr->attlen <= 0)
|
||||
/*
|
||||
* Don't cache offsets beyond fixed-width attributes. Virtual
|
||||
* generated attributes are stored as NULLs in the tuple, so we don't
|
||||
* cache offsets beyond these.
|
||||
*/
|
||||
if (cattr->attlen <= 0 ||
|
||||
attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
|
||||
break;
|
||||
|
||||
off = att_nominal_alignby(off, cattr->attalignby);
|
||||
|
|
|
|||
|
|
@ -1074,6 +1074,13 @@ slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
|
|||
{
|
||||
/* Otherwise all required columns are guaranteed to exist */
|
||||
firstNullAttr = natts;
|
||||
|
||||
/*
|
||||
* Check TupleDescFinalize() didn't get confused when setting
|
||||
* firstNonGuaranteedAttr. There should never be a NULL in a
|
||||
* guaranteed column.
|
||||
*/
|
||||
Assert(first_null_attr(tup->t_bits, natts) >= firstNullAttr);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
Loading…
Reference in a new issue