Fix memory issues when scanning chunk constraints

A function to lookup the name of a chunk constraint returned a pointer
to string without first copying the string into a safe memory
context. This probably worked by chance because everything in the scan
function ran in the current memory context, including the deforming of
the tuple. However, returning pointers to data in deformed tuples can
easily cause memory corruption with the introduction of other changes
(such as improved memory management).

This memory issue is fixed by explicitly reallocating the string in
the memory context that should be used for any returned data.

Changes are also made to avoid unnecessarily deforming tuples multiple
times in the same scan function.
This commit is contained in:
Erik Nordström 2020-07-14 12:32:19 +02:00 committed by Erik Nordström
parent a311f3735d
commit 09d37fa4f7

View File

@ -647,28 +647,10 @@ ts_chunk_constraint_create_on_chunk(Chunk *chunk, Oid constraint_oid)
static bool
hypertable_constraint_matches_tuple(TupleInfo *ti, const char *hypertable_constraint_name)
{
bool nulls[Natts_chunk_constraint];
Datum values[Natts_chunk_constraint];
bool should_free;
HeapTuple tuple = ts_scanner_fetch_heap_tuple(ti, false, &should_free);
const char *constrname;
bool matches = false;
bool isnull;
Datum name = slot_getattr(ti->slot, Anum_chunk_constraint_hypertable_constraint_name, &isnull);
heap_deform_tuple(tuple, ti->slot->tts_tupleDescriptor, values, nulls);
if (!nulls[AttrNumberGetAttrOffset(Anum_chunk_constraint_hypertable_constraint_name)])
{
constrname = NameStr(*DatumGetName(
values[AttrNumberGetAttrOffset(Anum_chunk_constraint_hypertable_constraint_name)]));
if (strcmp(hypertable_constraint_name, constrname) == 0)
matches = true;
}
if (should_free)
heap_freetuple(tuple);
return matches;
return !isnull && namestrcmp(DatumGetName(name), hypertable_constraint_name) == 0;
}
static void
@ -910,20 +892,24 @@ ts_chunk_constraint_get_name_from_hypertable_constraint(Oid chunk_relid,
init_scan_by_chunk_id(&iterator, DatumGetInt32(chunk_id));
ts_scanner_foreach(&iterator)
{
bool nulls[Natts_chunk_constraint];
Datum values[Natts_chunk_constraint];
bool should_free;
HeapTuple tuple = ts_scan_iterator_fetch_heap_tuple(&iterator, false, &should_free);
TupleInfo *ti = ts_scan_iterator_tuple_info(&iterator);
MemoryContext oldmctx;
bool isnull;
Datum datum;
char *name;
if (!hypertable_constraint_matches_tuple(ts_scan_iterator_tuple_info(&iterator),
hypertable_constraint_name))
if (!hypertable_constraint_matches_tuple(ti, hypertable_constraint_name))
continue;
heap_deform_tuple(tuple, ts_scan_iterator_tupledesc(&iterator), values, nulls);
datum = slot_getattr(ti->slot, Anum_chunk_constraint_constraint_name, &isnull);
Assert(!isnull);
oldmctx = MemoryContextSwitchTo(ti->mctx);
name = pstrdup(NameStr(*DatumGetName(datum)));
MemoryContextSwitchTo(oldmctx);
ts_scan_iterator_close(&iterator);
return NameStr(
*DatumGetName(values[AttrNumberGetAttrOffset(Anum_chunk_constraint_constraint_name)]));
return name;
}
return NULL;
}