commit 7c586f16d4a720325c1b9fc86b12b94f531956be
Author: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date:   Thu Apr 6 13:57:47 2017 +0530

    No-op tuple conversion in ExecEvalConvertRowtype()
    
    ExecEvalConvertRowtype() returns the tuple as is when no conversion is
    required i.e. no conversion map exists. While doing so it does not
    change the type of the tuple to be the type of the output expected.
    
    The tuple could be an on disk tuple and thus scribbling on it may lead
    to data corruption. I am not sure about this. Hence used
    heap_copy_tuple_as_datum(). I do not know whether that's the correct
    solution. But it fixes the problem.

diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 4fbb5c1..c889905 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -2818,16 +2818,21 @@ ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext
 	}
 
 	/*
-	 * No-op if no conversion needed (not clear this can happen here).
+	 * Following functions needs a HeapTuple not a bare HeapTupleHeader.
 	 */
-	if (op->d.convert_rowtype.map == NULL)
-		return;
+	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
+	tmptup.t_data = tuple;
 
 	/*
-	 * do_convert_tuple needs a HeapTuple not a bare HeapTupleHeader.
+	 * No-op if no conversion needed, but we need to change the type of tuple.
+	 * Since the tuple might come from disk, it's better to copy it and change
+	 * its type.
 	 */
-	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
-	tmptup.t_data = tuple;
+	if (op->d.convert_rowtype.map == NULL)
+	{
+		*op->resvalue = heap_copy_tuple_as_datum(&tmptup, outdesc);
+		return;
+	}
 
 	result = do_convert_tuple(&tmptup, op->d.convert_rowtype.map);
 
