1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-21 16:02:15 +03:00

Don't crash on reference to an un-available system column.

Adopt a more consistent policy about what slot-type-specific
getsysattr functions should do when system attributes are not
available.  To wit, they should all throw the same user-oriented
error, rather than variously crashing or emitting developer-oriented
messages.

This closes a identifiable problem in commits a71cfc56b and
3fb93103a (in v13 and v12), so back-patch into those branches,
along with a test case to try to ensure we don't break it again.
It is not known that any of the former crash cases are reachable
in HEAD, but this seems like a good safety improvement in any case.

Discussion: https://postgr.es/m/141051591267657@mail.yandex.ru
This commit is contained in:
Tom Lane
2021-04-22 17:30:42 -04:00
parent 197d33ccbe
commit d479d00285
3 changed files with 120 additions and 5 deletions

View File

@ -122,9 +122,8 @@ tts_virtual_clear(TupleTableSlot *slot)
}
/*
* Attribute values are readily available in tts_values and tts_isnull array
* in a VirtualTupleTableSlot. So there should be no need to call either of the
* following two functions.
* VirtualTupleTableSlots always have fully populated tts_values and
* tts_isnull arrays. So this function should never be called.
*/
static void
tts_virtual_getsomeattrs(TupleTableSlot *slot, int natts)
@ -132,10 +131,19 @@ tts_virtual_getsomeattrs(TupleTableSlot *slot, int natts)
elog(ERROR, "getsomeattrs is not required to be called on a virtual tuple table slot");
}
/*
* VirtualTupleTableSlots never provide system attributes (except those
* handled generically, such as tableoid). We generally shouldn't get
* here, but provide a user-friendly message if we do.
*/
static Datum
tts_virtual_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
{
elog(ERROR, "virtual tuple table slot does not have system attributes");
Assert(!TTS_EMPTY(slot));
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot retrieve a system column in this context")));
return 0; /* silence compiler warnings */
}
@ -335,6 +343,15 @@ tts_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Assert(!TTS_EMPTY(slot));
/*
* In some code paths it's possible to get here with a non-materialized
* slot, in which case we can't retrieve system columns.
*/
if (!hslot->tuple)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot retrieve a system column in this context")));
return heap_getsysattr(hslot->tuple, attnum,
slot->tts_tupleDescriptor, isnull);
}
@ -497,7 +514,11 @@ tts_minimal_getsomeattrs(TupleTableSlot *slot, int natts)
static Datum
tts_minimal_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
{
elog(ERROR, "minimal tuple table slot does not have system attributes");
Assert(!TTS_EMPTY(slot));
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot retrieve a system column in this context")));
return 0; /* silence compiler warnings */
}
@ -681,6 +702,15 @@ tts_buffer_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Assert(!TTS_EMPTY(slot));
/*
* In some code paths it's possible to get here with a non-materialized
* slot, in which case we can't retrieve system columns.
*/
if (!bslot->base.tuple)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot retrieve a system column in this context")));
return heap_getsysattr(bslot->base.tuple, attnum,
slot->tts_tupleDescriptor, isnull);
}