A suitably-instrumented run of "make installcheck-world" under valgrind turned
up a handful of memory-related bugs:
* memcpy()/strncpy() between overlapping regions
uniqueentry() and dispell_lexize() both deduplicate an array by iteratively
copying elements downward to occlude the duplicates. Before finding a first
duplicate, these functions call memcpy() with identical arguments. Similarly,
resolve_polymorphic_tupdesc() calls TupleDescInitEntry() with an attributeName
pointing directly into the TupleDesc's name bytes, causing the latter to call
strncpy() with identical arguments. The attached mem1v1-memcpy-overlap.patch
fixes these sites by checking for equal pointers before the affected call. For
TupleDescInitEntry(), I considered instead having resolve_polymorphic_tupdesc()
pstrdup() the value.
* read past the end of a Form_pg_type in examine_attribute()
examine_attribute() copies a Form_pg_type naively. Since the nullable columns
at the end of the structure are not present in memory, the memcpy() reads eight
bytes past the end of the source allocation. mem2v1-analyze-overread.patch
updates this code to match how we address the same issue for Form_pg_attribute.
* off-by-one error in shift_jis_20042euc_jis_2004()
This function grabs two bytes at a time, even when only one byte remains; this
makes it read past the end of the input. mem3v1-sjis-offbyone.patch changes it
to not do this and to report an error when the input ends in a byte that would
start a two-byte sequence.
Thanks,
nm
diff --git a/src/backend/access/common/tupdesc.c
b/src/backend/access/common/tupdesc.c
index d78b083..1ed7195 100644
*** a/src/backend/access/common/tupdesc.c
--- b/src/backend/access/common/tupdesc.c
***************
*** 459,468 **** TupleDescInitEntry(TupleDesc desc,
* fill in valid resname values in targetlists, particularly for resjunk
* attributes.
*/
! if (attributeName != NULL)
! namestrcpy(&(att->attname), attributeName);
! else
MemSet(NameStr(att->attname), 0, NAMEDATALEN);
att->attstattarget = -1;
att->attcacheoff = -1;
--- 459,468 ----
* fill in valid resname values in targetlists, particularly for resjunk
* attributes.
*/
! if (attributeName == NULL)
MemSet(NameStr(att->attname), 0, NAMEDATALEN);
+ else if (attributeName != &(att->attname))
+ namestrcpy(&(att->attname), attributeName);
att->attstattarget = -1;
att->attcacheoff = -1;
diff --git a/src/backend/tsearch/dict_ispeindex 31929c0..bfd1732 100644
*** a/src/backend/tsearch/dict_ispell.c
--- b/src/backend/tsearch/dict_ispell.c
***************
*** 139,145 **** dispell_lexize(PG_FUNCTION_ARGS)
}
else
{
! memcpy(cptr, ptr, sizeof(TSLexeme));
cptr++;
ptr++;
}
--- 139,146 ----
}
else
{
! if (ptr != cptr)
! memcpy(cptr, ptr, sizeof(TSLexeme));
cptr++;
ptr++;
}
diff --git a/src/backend/utils/adt/tsvecindex 6810615..6c24850 100644
*** a/src/backend/utils/adt/tsvector.c
--- b/src/backend/utils/adt/tsvector.c
***************
*** 125,131 **** uniqueentry(WordEntryIN *a, int l, char *buf, int *outbuflen)
buflen += res->poslen * sizeof(WordEntryPos) +
sizeof(uint16);
}
res++;
! memcpy(res, ptr, sizeof(WordEntryIN));
}
else if (ptr->entry.haspos)
{
--- 125,132 ----
buflen += res->poslen * sizeof(WordEntryPos) +
sizeof(uint16);
}
res++;
! if (ptr != res)
! memcpy(res, ptr, sizeof(WordEntryIN));
}
else if (ptr->entry.haspos)
{
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index bafdc80..2e0a869 100644
*** a/src/backend/commands/analyze.c
--- b/src/backend/commands/analyze.c
***************
*** 874,881 **** examine_attribute(Relation onerel, int attnum, Node
*index_expr)
typtuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(stats->attrtypid));
if (!HeapTupleIsValid(typtuple))
elog(ERROR, "cache lookup failed for type %u",
stats->attrtypid);
! stats->attrtype = (Form_pg_type) palloc(sizeof(FormData_pg_type));
! memcpy(stats->attrtype, GETSTRUCT(typtuple), sizeof(FormData_pg_type));
ReleaseSysCache(typtuple);
stats->anl_context = anl_context;
stats->tupattnum = attnum;
--- 874,881 ----
typtuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(stats->attrtypid));
if (!HeapTupleIsValid(typtuple))
elog(ERROR, "cache lookup failed for type %u",
stats->attrtypid);
! stats->attrtype = (Form_pg_type) palloc(TYPE_FIXED_PART_SIZE);
! memcpy(stats->attrtype, GETSTRUCT(typtuple), TYPE_FIXED_PART_SIZE);
ReleaseSysCache(typtuple);
stats->anl_context = anl_context;
stats->tupattnum = attnum;
diff --git a/src/include/catalog/pg_tindex 9baed6c..3255897 100644
*** a/src/include/catalog/pg_type.h
--- b/src/include/catalog/pg_type.h
***************
*** 219,224 **** CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71)
BKI_SCHEMA_MACRO
--- 219,228 ----
} FormData_pg_type;
+ /* Size of fixed part of pg_type tuples, not counting var-length fields. */
+ #define TYPE_FIXED_PART_SIZE \
+ (offsetof(FormData_pg_type,typcollation) + sizeof(Oid))
+
/* ----------------
* Form_pg_type corresponds to a pointer to a row with
* the format of pg_type relation.
diff --git
a/src/backend/utils/mb/conversion_procs/euc2004_sjis2004/euc2004_sjis2004.c
b/src/backend/utils/mb/conversion_procs/euc2004_sjis2004/euc2004_sjis2004.c
index 3499f77..868bdbc 100644
*** a/src/backend/utils/mb/conversion_procs/euc2004_sjis2004/euc2004_sjis2004.c
--- b/src/backend/utils/mb/conversion_procs/euc2004_sjis2004/euc2004_sjis2004.c
***************
*** 218,225 **** get_ten(int b, int *ku)
static void
shift_jis_20042euc_jis_2004(const unsigned char *sjis, unsigned char *p, int
len)
{
! int c1,
! c2;
int ku,
ten,
kubun;
--- 218,224 ----
static void
shift_jis_20042euc_jis_2004(const unsigned char *sjis, unsigned char *p, int
len)
{
! int c1;
int ku,
ten,
kubun;
***************
*** 229,235 **** shift_jis_20042euc_jis_2004(const unsigned char *sjis,
unsigned char *p, int len
while (len > 0)
{
c1 = *sjis;
- c2 = sjis[1];
if (!IS_HIGHBIT_SET(c1))
{
--- 228,233 ----
***************
*** 245,251 **** shift_jis_20042euc_jis_2004(const unsigned char *sjis,
unsigned char *p, int len
l = pg_encoding_verifymb(PG_SHIFT_JIS_2004, (const char *)
sjis, len);
! if (l < 0)
report_invalid_encoding(PG_SHIFT_JIS_2004,
(const
char *) sjis, len);
--- 243,249 ----
l = pg_encoding_verifymb(PG_SHIFT_JIS_2004, (const char *)
sjis, len);
! if (l < 0 || l > len)
report_invalid_encoding(PG_SHIFT_JIS_2004,
(const
char *) sjis, len);
***************
*** 257,262 **** shift_jis_20042euc_jis_2004(const unsigned char *sjis,
unsigned char *p, int len
--- 255,262 ----
}
else if (l == 2)
{
+ int c2 = sjis[1];
+
plane = 1;
ku = 1;
ten = 1;
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers