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

Reply via email to