diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 4b295f8da5..8027498b73 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -2981,7 +2981,9 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
 		 *
 		 * (Typically, newslot was also generated by ExecGetUpdateNewTuple, so
 		 * that epqslot_clean will be that same slot and the copy step below
-		 * is not needed.)
+		 * is not needed.  Though we need to materialize newslot in this case,
+		 * since its tuple might share the oldslot's buffer, which might
+		 * be freed on fetching trigtuple from oldslot.)
 		 */
 		if (epqslot_candidate != NULL)
 		{
@@ -2992,6 +2994,8 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
 
 			if (newslot != epqslot_clean)
 				ExecCopySlot(newslot, epqslot_clean);
+			else
+				ExecMaterializeSlot(newslot);
 		}
 
 		trigtuple = ExecFetchSlotHeapTuple(oldslot, true, &should_free_trig);
