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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers