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 static bool
hypertable_constraint_matches_tuple(TupleInfo *ti, const char *hypertable_constraint_name) hypertable_constraint_matches_tuple(TupleInfo *ti, const char *hypertable_constraint_name)
{ {
bool nulls[Natts_chunk_constraint]; bool isnull;
Datum values[Natts_chunk_constraint]; Datum name = slot_getattr(ti->slot, Anum_chunk_constraint_hypertable_constraint_name, &isnull);
bool should_free;
HeapTuple tuple = ts_scanner_fetch_heap_tuple(ti, false, &should_free);
const char *constrname;
bool matches = false;
heap_deform_tuple(tuple, ti->slot->tts_tupleDescriptor, values, nulls); return !isnull && namestrcmp(DatumGetName(name), hypertable_constraint_name) == 0;
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;
} }
static void 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)); init_scan_by_chunk_id(&iterator, DatumGetInt32(chunk_id));
ts_scanner_foreach(&iterator) ts_scanner_foreach(&iterator)
{ {
bool nulls[Natts_chunk_constraint]; TupleInfo *ti = ts_scan_iterator_tuple_info(&iterator);
Datum values[Natts_chunk_constraint]; MemoryContext oldmctx;
bool should_free; bool isnull;
HeapTuple tuple = ts_scan_iterator_fetch_heap_tuple(&iterator, false, &should_free); Datum datum;
char *name;
if (!hypertable_constraint_matches_tuple(ts_scan_iterator_tuple_info(&iterator), if (!hypertable_constraint_matches_tuple(ti, hypertable_constraint_name))
hypertable_constraint_name))
continue; 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); ts_scan_iterator_close(&iterator);
return NameStr(
*DatumGetName(values[AttrNumberGetAttrOffset(Anum_chunk_constraint_constraint_name)])); return name;
} }
return NULL; return NULL;
} }