@@ -60,6 +60,10 @@ static int getNotify(PGconn* conn);
6060static int getCopyStart (PGconn * conn , ExecStatusType copytype );
6161static int getReadyForQuery (PGconn * conn );
6262
63+ #if PG_VERSION_NUM >= 180000
64+ static int getBackendKeyData (PGconn * conn , int msgLength );
65+ #endif
66+
6367/* Glue to simplify working with error reporting between versions */
6468#if PG_VERSION_NUM >= 140000
6569#define updatePQXExpBuffer appendPQExpBuffer
@@ -394,8 +398,12 @@ static void pqxParseInput3(PGconn* conn, const PGresult* description) {
394398 * just as easy to handle it as part of the main loop.
395399 * Save the data and continue processing.
396400 */
401+ #if PG_VERSION_NUM >= 180000
402+ if (getBackendKeyData (conn , msgLength )) return ;
403+ #else
397404 if (pqGetInt (& (conn -> be_pid ), 4 , conn )) return ;
398405 if (pqGetInt (& (conn -> be_key ), 4 , conn )) return ;
406+ #endif
399407 break ;
400408 case 'T' : /* Row Description */
401409 if (conn -> result != NULL &&
@@ -909,6 +917,78 @@ static int getReadyForQuery(PGconn* conn) {
909917 return 0 ;
910918}
911919
920+ #if PG_VERSION_NUM >= 180000
921+ /*
922+ * This is copy-paste of getNotify from fe-protocol3.c
923+ *
924+ * parseInput subroutine to read a BackendKeyData message.
925+ * Entry: 'v' message type and length have already been consumed.
926+ * Exit: returns 0 if successfully consumed message.
927+ * returns EOF if not enough data.
928+ */
929+ static int
930+ getBackendKeyData (PGconn * conn , int msgLength )
931+ {
932+ int cancel_key_len ;
933+
934+ if (conn -> be_cancel_key )
935+ {
936+ free (conn -> be_cancel_key );
937+ conn -> be_cancel_key = NULL ;
938+ conn -> be_cancel_key_len = 0 ;
939+ }
940+
941+ if (pqGetInt (& (conn -> be_pid ), 4 , conn ))
942+ return EOF ;
943+
944+ cancel_key_len = 5 + msgLength - (conn -> inCursor - conn -> inStart );
945+
946+ if (cancel_key_len != 4 && conn -> pversion == PG_PROTOCOL (3 , 0 ))
947+ {
948+ updatePQXExpBuffer (& conn -> errorMessage ,
949+ libpq_gettext ("received invalid BackendKeyData message: cancel key with length %d not allowed in protocol version 3.0 (must be 4 bytes)" ),
950+ cancel_key_len );
951+ pqSaveErrorResult (conn );
952+ return 0 ;
953+ }
954+
955+ if (cancel_key_len < 4 )
956+ {
957+ updatePQXExpBuffer (& conn -> errorMessage ,
958+ libpq_gettext ("received invalid BackendKeyData message: cancel key with length %d is too short (minimum 4 bytes)" ),
959+ cancel_key_len );
960+ pqSaveErrorResult (conn );
961+ return 0 ;
962+ }
963+
964+ if (cancel_key_len > 256 )
965+ {
966+ updatePQXExpBuffer (& conn -> errorMessage ,
967+ libpq_gettext ("received invalid BackendKeyData message: cancel key with length %d is too long (maximum 256 bytes)" ),
968+ cancel_key_len );
969+ pqSaveErrorResult (conn );
970+ return 0 ;
971+ }
972+
973+ conn -> be_cancel_key = malloc (cancel_key_len );
974+ if (conn -> be_cancel_key == NULL )
975+ {
976+ updatePQXExpBufferStr (& conn -> errorMessage ,
977+ libpq_gettext ("out of memory" ));
978+ pqSaveErrorResult (conn );
979+ return 0 ;
980+ }
981+ if (pqGetnchar (conn -> be_cancel_key , cancel_key_len , conn ))
982+ {
983+ free (conn -> be_cancel_key );
984+ conn -> be_cancel_key = NULL ;
985+ return EOF ;
986+ }
987+ conn -> be_cancel_key_len = cancel_key_len ;
988+ return 0 ;
989+ }
990+ #endif
991+
912992/*
913993 * This is copy-paste of getNotify from fe-protocol3.c
914994 *
0 commit comments