From 69d2cbd0a43d673b03cb80b680b4c919a27057c7 Mon Sep 17 00:00:00 2001
From: Mats Kindahl <mats@timescale.com>
Date: Thu, 8 Dec 2022 10:00:23 +0100
Subject: Check return value of strdup when starting backend

Inside `BackendInitialize`, if `strdup` returns NULL because it is out
of memory, this will later trigger a server crash because of
dereferencing a null pointer.

This commit fixes this by checking the return values of `strdup` and
exit the backend with exit status 1 if any of the allocations failed.
This will be handled as a normal shutdown in the postmaster, which will
report the exiting backend and continue executing.
---
 src/backend/postmaster/postmaster.c | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index f459dab360..e7739794ae 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -420,6 +420,7 @@ static pid_t StartChildProcess(AuxProcType type);
 static void StartAutovacuumWorker(void);
 static void MaybeStartWalReceiver(void);
 static void InitPostmasterDeathWatchHandle(void);
+static char *safe_strdup(const char*);
 
 /*
  * Archiver is allowed to start up at the current postmaster state?
@@ -704,7 +705,7 @@ PostmasterMain(int argc, char *argv[])
 				break;
 
 			case 'C':
-				output_config_variable = strdup(optarg);
+				output_config_variable = safe_strdup(optarg);
 				break;
 
 			case 'c':
@@ -735,7 +736,7 @@ PostmasterMain(int argc, char *argv[])
 				}
 
 			case 'D':
-				userDoption = strdup(optarg);
+				userDoption = safe_strdup(optarg);
 				break;
 
 			case 'd':
@@ -4275,8 +4276,8 @@ BackendInitialize(Port *port)
 	 * Save remote_host and remote_port in port structure (after this, they
 	 * will appear in log_line_prefix data for log messages).
 	 */
-	port->remote_host = strdup(remote_host);
-	port->remote_port = strdup(remote_port);
+	port->remote_host = safe_strdup(remote_host);
+	port->remote_port = safe_strdup(remote_port);
 
 	/* And now we can issue the Log_connections message, if wanted */
 	if (Log_connections)
@@ -4307,7 +4308,10 @@ BackendInitialize(Port *port)
 		ret == 0 &&
 		strspn(remote_host, "0123456789.") < strlen(remote_host) &&
 		strspn(remote_host, "0123456789ABCDEFabcdef:") < strlen(remote_host))
-		port->remote_hostname = strdup(remote_host);
+	{
+		port->remote_hostname = safe_strdup(remote_host);
+	}
+
 
 	/*
 	 * Ready to begin client interaction.  We will give up and _exit(1) after
@@ -6475,3 +6479,13 @@ InitPostmasterDeathWatchHandle(void)
 								 GetLastError())));
 #endif							/* WIN32 */
 }
+
+char *safe_strdup(const char *str) {
+	char *result = strdup(str);
+	if (result == NULL) {
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory")));
+	}
+	return result;
+}
-- 
2.34.1

