*** a/src/backend/commands/copy.c --- b/src/backend/commands/copy.c *************** *** 2058,2069 **** CopyFrom(CopyState cstate) int16 fld_count; ListCell *cur; ! if (!CopyGetInt16(cstate, &fld_count) || ! fld_count == -1) { done = true; break; } if (fld_count != attr_count) ereport(ERROR, --- 2058,2088 ---- int16 fld_count; ListCell *cur; ! if (!CopyGetInt16(cstate, &fld_count)) { done = true; break; } + + if (fld_count == -1) + { + /* + * Received EOF marker. Check to see if this is really + * the EOF and complain if we find any more data. + * In a V3 protocol copy, this also enforces that we wait + * for the protocol end of copy (CopyDone/Fail). + */ + int8 unused; + if (CopyGetData(cstate, &unused, sizeof(unused), sizeof(unused))) + { + ereport(ERROR, + (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), + errmsg("received copy data after EOF marker"))); + } + + done = true; + break; + } if (fld_count != attr_count) ereport(ERROR,