*** 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,2090 ---- int16 fld_count; ListCell *cur; ! if (!CopyGetInt16(cstate, &fld_count)) { done = true; break; } + + if (fld_count == -1) + { + /* + * Reached EOF. In protocol version 3, we must wait for + * the protocol end of copy (CopyDone/Fail). If we + * receive any more copy data after EOF, complain. + */ + if (cstate->copy_dest == COPY_NEW_FE) + { + 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,