[pgpool-hackers: 4587] Use safer string functions

Martijn van Duren pgpool at list.imperialat.at
Mon May 5 19:47:34 JST 2025


Hello all,

While I haven't seen any problematic use per se, I'd like to request
to replace some generally accepted unsafe string functions with their
safer counterparts, where avaiable:
sprintf -> snprintf
strcat -> strlcat
strcpy -> strlcpy

There already was an (invalid) check in configure.ac for strlc*, and
there's a copy of strlcpy.c in src/util/, so I don't think there will
be much objection to these. I recon an additional benefit would be
that if an invalid usage ever shows up that a truncated result would
give a user more noticeable errors than a lower chance crash from a
buffer overflow (if not down right an exploit). This could be made
better by checking the return value and compare it to the length of the
buffer, but the diff is big enough as it is.

I haven't looked too in depth how the internal strlcpy is hooked into
the build, so for now I simply went with the HAVE_STRLCPY define as
supplied via configure. If someone can tell me if strlcpy is always
available I don't mind removing that guard entirely.

This also removes a bunch of linker warnings from OpenBSD:
ld: warning: md5.c:399(md5.o:(pool_md5_encrypt)): warning: strcpy() is almost always misused, please use strlcpy()                                                                                                 
ld: warning: pool_path.c:358(pool_path.o:(make_absolute_path)): warning: sprintf() is often misused, please use snprintf()                                                                                         
ld: warning: pool_passwd.c:149(pool_passwd.o:(pool_create_passwdent)): warning: strcat() is almost always misused, please use strlcat()                                                                                                                                                                                                                                                                                                
...

Sincerely,

Martijn van Duren

diff 7649a56611ed05d0a51caf4f39e620e1d08577cd 8473e1d3d8c80159d1e7cfdfb9444e676d1892c3
commit - 7649a56611ed05d0a51caf4f39e620e1d08577cd
commit + 8473e1d3d8c80159d1e7cfdfb9444e676d1892c3
blob - 881966fbc9fcf31ce8edc0d97ad892848f50641c
blob + 34f07ef480cb4e478fba00c4f19737c570167f58
--- configure.ac
+++ configure.ac
@@ -94,7 +94,7 @@ AC_CHECK_LIB(PW,       main)
 AC_CHECK_LIB(resolv,   main)
 AC_CHECK_LIB(crypt,   main)
 
-AC_CHECK_FUNCS([strlcat, strlcpy])
+AC_CHECK_FUNCS([strlcat strlcpy])
 
 dnl Checks for header files.
 AC_HEADER_STDC
blob - c35a0bffb13d7d915d466657c91867e7029c67b6
blob + 2597718c81a0e3e8431b415eefa2afba4e3cbbda
--- src/auth/md5.c
+++ src/auth/md5.c
@@ -396,7 +396,11 @@ pool_md5_encrypt(const char *passwd, const char *salt,
 	 * Place salt at the end because it may be known by users trying to crack
 	 * the MD5 output.
 	 */
+#ifdef HAVE_STRLCPY
+	strlcpy(crypt_buf, passwd, passwd_len + salt_len);
+#else
 	strcpy(crypt_buf, passwd);
+#endif
 	memcpy(crypt_buf + passwd_len, salt, salt_len);
 
 	ret = pool_md5_hash(crypt_buf, passwd_len + salt_len, buf);
blob - 202195b430b3efc534f096b458f734c17d0f36e8
blob + 68bcf62f15c9c9fc9bc45ecd8e55a42ad3a31ecc
--- src/auth/pool_hba.c
+++ src/auth/pool_hba.c
@@ -1916,6 +1916,7 @@ tokenize_inc_file(List *tokens,
 	List	   *inc_lines;
 	ListCell   *inc_line;
 	MemoryContext linecxt;
+	size_t		inc_fullname_len;
 
 	if (is_absolute_path(inc_filename))
 	{
@@ -1924,10 +1925,14 @@ tokenize_inc_file(List *tokens,
 	}
 	else
 	{
+		inc_fullname_len = strlen(outer_filename) + 1 + strlen(inc_filename) + 1;
 		/* relative path is relative to dir of calling file */
-		inc_fullname = (char *) palloc(strlen(outer_filename) + 1 +
-									   strlen(inc_filename) + 1);
+		inc_fullname = (char *) palloc(inc_fullname_len);
+#ifdef HAVE_STRLCPY
+		strlcpy(inc_fullname, outer_filename, inc_fullname_len);
+#else
 		strcpy(inc_fullname, outer_filename);
+#endif
 		get_parent_directory(inc_fullname);
 		join_path_components(inc_fullname, inc_fullname, inc_filename);
 		canonicalize_path(inc_fullname);
blob - cb37fdea41fbadc1fb38d6288e6e400098d3a06c
blob + edea3aa7f8b556f92747cb3851b1002eae3444b2
--- src/auth/pool_passwd.c
+++ src/auth/pool_passwd.c
@@ -106,6 +106,7 @@ pool_create_passwdent(char *username, char *passwd)
 	char 	*writebuf = NULL;
 	int		len;
 	bool 	updated = false;
+	size_t	writebuf_len = 0;
 
 	if (!passwd_fd)
 		ereport(ERROR,
@@ -141,25 +142,40 @@ pool_create_passwdent(char *username, char *passwd)
 		}
 
 		if (writebuf == NULL)
-			writebuf = palloc0(len + 1);
+		{
+			writebuf_len = len + 1;
+			writebuf = palloc0(writebuf_len);
+		}
 		else
 		{
-			writebuf = repalloc(writebuf, (len + strlen(writebuf) + 1));
+			writebuf_len += len;
+			writebuf = repalloc(writebuf, writebuf_len);
 		}
+#ifdef HAVE_STRLCAT
+		strlcat(writebuf, linebuf, writebuf_len);
+#else
 		strcat(writebuf, linebuf);
+#endif
 	}
 
 	if (!updated)
 	{
 		/* password was not update, append this at the end */
 		len = snprintf(linebuf, sizeof(linebuf), "%s:%s\n", username, passwd);
-		if (writebuf == NULL)
-			writebuf = palloc0(len + 1);
+		if (writebuf == NULL) {
+			writebuf_len = len + 1;
+			writebuf = palloc0(writebuf_len);
+		}
 		else
 		{
-			writebuf = repalloc(writebuf, (len + strlen(writebuf) + 1));
+			writebuf_len = len + strlen(writebuf) + 1;
+			writebuf = repalloc(writebuf, writebuf_len);
 		}
+#ifdef HAVE_STRLCAT
+		strlcat(writebuf, linebuf, writebuf_len);
+#else
 		strcat(writebuf, linebuf);
+#endif
 	}
 
 	if(!writebuf)
blob - b1613029351be5a6a11cf5706b2ab169b0ee3744
blob + bb89a59019e43fc1076a48845ffd08e4f663fb24
--- src/config/pool_config.l
+++ src/config/pool_config.l
@@ -351,6 +351,7 @@ ParseConfigFile(const char *config_file, const char *c
 	ConfigVariable *item;
 	char buf[POOLMAXPATHLEN + 1];
 	char *config_filepath;
+	size_t filepath_len;
 
 	/*
 	 * Reject too-deep include nesting depth.
@@ -372,16 +373,25 @@ ParseConfigFile(const char *config_file, const char *c
 	if (calling_file == NULL || is_absolute_path(config_file))
 	{
 		/* absolute path is taken as-is */
-		config_filepath = (char *) palloc(strlen(config_file) + 1);
+		filepath_len = strlen(config_file) + 1;
+		config_filepath = (char *) palloc(filepath_len);
+#ifdef HAVE_STRLCPY
+		strlcpy(config_filepath, config_file, filepath_len);
+#else
 		strcpy(config_filepath, config_file);
+#endif
 		config_filepath[strlen(config_file)] = '\0';
 	}
 	else
 	{
 		/* relative path is relative to dir of calling file */
-		config_filepath = (char *) palloc(strlen(config_file) + 1 +
-									   strlen(calling_file) + 1);
+		filepath_len = strlen(config_file) + 1 + strlen(calling_file) + 1;
+		config_filepath = (char *) palloc(filepath_len);
+#ifdef HAVE_STRLCPY
+		strlcpy(config_filepath, calling_file, filepath_len);
+#else
 		strcpy(config_filepath, calling_file);
+#endif
 		get_parent_directory(config_filepath);
 		join_path_components(config_filepath, config_filepath, config_file);
 		canonicalize_path(config_filepath);
blob - 4fa0396642127a10c647af9aee95c7383d217a89
blob + 867c9964f9f5bb25c843123a1184e887244c6579
--- src/config/pool_config_variables.c
+++ src/config/pool_config_variables.c
@@ -4873,7 +4873,11 @@ config_post_processor(ConfigContext context, int eleve
 					 errdetail("failed to get the local hostname")));
 			return false;
 		}
+#ifdef HAVE_STRLCPY
+		strlcpy(g_pool_config.wd_nodes.wd_node_info[g_pool_config.pgpool_node_id].hostname, localhostname, sizeof(g_pool_config.wd_nodes.wd_node_info[g_pool_config.pgpool_node_id].hostname));
+#else
 		strcpy(g_pool_config.wd_nodes.wd_node_info[g_pool_config.pgpool_node_id].hostname, localhostname);
+#endif
 		return true;
 	}
 	for (i = 0; i < MAX_CONNECTION_SLOTS; i++)
blob - 3b90284973df9af254dcd97eeced5a34d5a2defb
blob + 601586f89f8b773c15ed82e736e775b5e4868fec
--- src/context/pool_query_context.c
+++ src/context/pool_query_context.c
@@ -1547,8 +1547,13 @@ remove_read_write(int len, const char *contents, int *
 
 	rewritten_contents = palloc(*rewritten_len);
 
+#ifdef HAVE_STRLCPY
+	strlcpy(rewritten_contents, name, *rewritten_len);
+	strlcpy(rewritten_contents + strlen(name) + 1, rewritten_query, *rewritten_len - strlen(name) - 1);
+#else
 	strcpy(rewritten_contents, name);
 	strcpy(rewritten_contents + strlen(name) + 1, rewritten_query);
+#endif
 	memcpy(rewritten_contents + strlen(name) + strlen(rewritten_query) + 2,
 		   stmt + strlen(stmt) + 1,
 		   len - (strlen(name) + strlen(stmt) + 2));
blob - f321dad7d09568a0d74a95a443a2a74fd25d454f
blob + 96e83b5be1a3e480536c5fd680ae902b81e17f3c
--- src/include/utils/json.h
+++ src/include/utils/json.h
@@ -294,7 +294,7 @@ extern "C"
 	json_value *json_parse_ex(json_settings * settings,
 							  const json_char * json,
 							  size_t length,
-							  char *error);
+							  char **error);
 
 	void		json_value_free(json_value *);
 
blob - ae831dd6d9acd937da9aa00ed1d4a87a6ebdbddc
blob + 129e97361820d036b198ba1f24e6b57ebedc0bba
--- src/main/health_check.c
+++ src/main/health_check.c
@@ -609,6 +609,7 @@ check_backend_down_request(int node, bool done_request
 	bool		found = false;
 	int			node_id;
 	char		status[MAXLINE];
+	size_t		writebuf_len = 0;
 
 	if (backend_down_request_file[0] == '\0')
 	{
@@ -661,17 +662,26 @@ check_backend_down_request(int node, bool done_request
 
 		if (writebuf == NULL)
 		{
-			writebuf = malloc(strlen(p) + 1);
-			memset(writebuf, 0, strlen(p) + 1);
+			writebuf_len = strlen(p) + 1;
+			writebuf = malloc(writebuf_len);
+			writebuf[0] = '\0';
 		}
 		else
-			writebuf = realloc(writebuf, strlen(p) + strlen(writebuf) + 1);
+		{
+			writebuf_len += strlen(p);
+			writebuf = realloc(writebuf, writebuf_len);
+		}
 		if (!writebuf)
 		{
 			fclose(fd);
 			return false;
 		}
+
+#ifdef HAVE_STRLCAT
+		strlcat(writebuf, p, writebuf_len);
+#else
 		strcat(writebuf, p);
+#endif
 	}
 
 	fclose(fd);
blob - d74cf12b2d2cc1e33a8cb6a77f27789461699ddf
blob + 259d239bcf7b3149e30447fe9059d3e0e49824ac
--- src/main/pgpool_main.c
+++ src/main/pgpool_main.c
@@ -3401,7 +3401,7 @@ write_status_file(void)
 		else
 			status = "unused";
 
-		sprintf(buf, "%s\n", status);
+		snprintf(buf, sizeof(buf), "%s\n", status);
 		if (fwrite(buf, 1, strlen(buf), fd) != strlen(buf))
 		{
 			ereport(WARNING,
blob - 9dbae197c4af66e371922af7de7ef97d943f2d49
blob + 74da6b5af0da718db8285af38aaaa0530ef7a1b0
--- src/parser/wchar.c
+++ src/parser/wchar.c
@@ -3004,9 +3004,9 @@ report_invalid_encoding(int encoding, const char *mbst
 
 	for (j = 0; j < jlimit; j++)
 	{
-		p += sprintf(p, "0x%02x", (unsigned char) mbstr[j]);
+		p += snprintf(p, sizeof(buf) - (p - buf), "0x%02x", (unsigned char) mbstr[j]);
 		if (j < jlimit - 1)
-			p += sprintf(p, " ");
+			p += snprintf(p, sizeof(buf) - (p - buf), " ");
 	}
 
 	ereport(ERROR,
@@ -3037,9 +3037,9 @@ report_untranslatable_char(int src_encoding, int dest_
 
 	for (j = 0; j < jlimit; j++)
 	{
-		p += sprintf(p, "0x%02x", (unsigned char) mbstr[j]);
+		p += snprintf(p, sizeof(buf) - (p - buf), "0x%02x", (unsigned char) mbstr[j]);
 		if (j < jlimit - 1)
-			p += sprintf(p, " ");
+			p += snprintf(p, sizeof(buf) - (p - buf), " ");
 	}
 
 	ereport(ERROR,
blob - cb72e9c54c76cf4b1079f87adc50f236238f0a48
blob + 45f6675ce8432b4afa1224fe98265f1cc26668e0
--- src/protocol/pool_process_query.c
+++ src/protocol/pool_process_query.c
@@ -3930,7 +3930,11 @@ parse_copy_data(char *buf, int len, char delimiter, in
 	{
 		str[j] = '\0';
 		p = palloc(j + 1);
+#ifdef HAVE_STRLCPY
+		strlcpy(p, str, j + 1);
+#else
 		strcpy(p, str);
+#endif
 		p[j] = '\0';
 		ereport(DEBUG1,
 				(errmsg("parsing copy data"),
blob - 59647fe8108c9e94de609b80c7617e396a0d8aba
blob + a09fd57c3028cc00b739d440001e6723de74f0bd
--- src/protocol/pool_proto_modules.c
+++ src/protocol/pool_proto_modules.c
@@ -1055,7 +1055,11 @@ Execute(POOL_CONNECTION * frontend, POOL_CONNECTION_PO
 					alloc_len += STR_ALLOC_SIZE;
 					search_query = repalloc(search_query, alloc_len);
 				}
+#ifdef HAVE_STRLCAT
+				strlcat(search_query, hex_str, alloc_len);
+#else
 				strcat(search_query, hex_str);
+#endif
 				len += hexlen;
 			}
 
@@ -1470,8 +1474,13 @@ Parse(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL
 				contents = repalloc(msg->contents, alloc_len);
 				MemoryContextSwitchTo(oldcxt);
 
+#ifdef HAVE_STRLCPY
+				strlcpy(contents, name, alloc_len);
+				strlcpy(contents + strlen(name) + 1, rewrite_query, alloc_len - strlen(name) - 1);
+#else
 				strcpy(contents, name);
 				strcpy(contents + strlen(name) + 1, rewrite_query);
+#endif
 				memcpy(contents + strlen(name) + strlen(rewrite_query) + 2,
 					   stmt + strlen(stmt) + 1,
 					   len - (strlen(name) + strlen(stmt) + 2));
blob - 4dca05e9fa26b9fe468479323cb3f7948ea0f1b3
blob + 41f7dc25f757438ac9f786a037688886c30f3fad
--- src/rewrite/pool_timestamp.c
+++ src/rewrite/pool_timestamp.c
@@ -1269,7 +1269,11 @@ makeStringConstFromQuery(POOL_CONNECTION_POOL * backen
 
 	len = strlen(res->data[0]) + 1;
 	str = palloc(len);
+#ifdef HAVE_STRLCPY
+	strlcpy(str, res->data[0], len);
+#else
 	strcpy(str, res->data[0]);
+#endif
 	free_select_result(res);
 
 	con = makeNode(A_Const);
blob - 2dee8ce0a72b591d3dd9482c778c8ca8736694f3
blob + 65b977059beb912e3fc2b30ec4f1e78be461193b
--- src/tools/watchdog/wd_cli.c
+++ src/tools/watchdog/wd_cli.c
@@ -585,10 +585,16 @@ load_watchdog_nodes_from_json(char *json_data, int len
 
 		gslifeCheckCluster->lifeCheckNodes[i].nodeState = NODE_EMPTY;
 		gslifeCheckCluster->lifeCheckNodes[i].wdState = nodeInfo->state;
+#if HAVE_STRLCPY
+		strlcpy(gslifeCheckCluster->lifeCheckNodes[i].stateName, nodeInfo->stateName, sizeof(gslifeCheckCluster->lifeCheckNodes[i].stateName));
+		strlcpy(gslifeCheckCluster->lifeCheckNodes[i].hostName, nodeInfo->hostName, sizeof(gslifeCheckCluster->lifeCheckNodes[i].hostName));
+		strlcpy(gslifeCheckCluster->lifeCheckNodes[i].nodeName, nodeInfo->nodeName, sizeof(gslifeCheckCluster->lifeCheckNodes[i].nodeName));
+#else
 		strcpy(gslifeCheckCluster->lifeCheckNodes[i].stateName, nodeInfo->stateName);
-		gslifeCheckCluster->lifeCheckNodes[i].ID = nodeInfo->id;
 		strcpy(gslifeCheckCluster->lifeCheckNodes[i].hostName, nodeInfo->hostName);
 		strcpy(gslifeCheckCluster->lifeCheckNodes[i].nodeName, nodeInfo->nodeName);
+#endif
+		gslifeCheckCluster->lifeCheckNodes[i].ID = nodeInfo->id;
 		gslifeCheckCluster->lifeCheckNodes[i].wdPort = nodeInfo->wd_port;
 		gslifeCheckCluster->lifeCheckNodes[i].pgpoolPort = nodeInfo->pgpool_port;
 		gslifeCheckCluster->lifeCheckNodes[i].retry_lives = pool_config->wd_life_point;
blob - fa420ccd5b778652c5223361794a36b9f1439b51
blob + 2780d11d7559bc6c889cf212b1ee639a8accbead
--- src/utils/json.c
+++ src/utils/json.c
@@ -273,9 +273,8 @@ json_value *
 json_parse_ex(json_settings * settings,
 			  const json_char * json,
 			  size_t length,
-			  char *error_buf)
+			  char **error_buf)
 {
-	json_char	error[json_error_max];
 	const		json_char *end;
 	json_value *top,
 			   *root,
@@ -297,7 +296,8 @@ json_parse_ex(json_settings * settings,
 		length -= 3;
 	}
 
-	error[0] = '\0';
+	if (error_buf)
+		*error_buf = NULL;
 	end = (json + length);
 
 	memcpy(&state.settings, settings, sizeof(json_settings));
@@ -1021,7 +1021,8 @@ e_unknown_value:
 
 e_alloc_failure:
 
-	strcpy(error, "Memory allocation failure");
+	if (error_buf)
+		*error_buf = "Memory allocation failure";
 	goto e_failed;
 
 e_overflow:
@@ -1034,10 +1035,8 @@ e_failed:
 
 	if (error_buf)
 	{
-		if (*error)
-			strcpy(error_buf, error);
-		else
-			strcpy(error_buf, "Unknown error");
+		if (error_buf && *error_buf == NULL)
+			*error_buf = "Unknown error";
 	}
 
 	if (state.first_pass)
blob - fcfea985ff407070c78ae47083e90ad5b5b24d0a
blob + 3b50466d47c17834404cd08973af4038494509bf
--- src/utils/mmgr/mcxt.c
+++ src/utils/mmgr/mcxt.c
@@ -674,7 +674,11 @@ MemoryContextCreate(NodeTag tag, Size size,
 	node->nextchild = NULL;
 	node->isReset = true;
 	node->name = ((char *) node) + size;
+#ifdef HAVE_STRLCPY
+	strlcpy(node->name, name, needed - size);
+#else
 	strcpy(node->name, name);
+#endif
 
 	/* Type-specific routine finishes any other essential initialization */
 	(*node->methods->init) (node);
blob - 3f431597d37430ff467bda32da1a84a8b72889d8
blob + e9a557ac4faaddf511d7c2da0369c553746321f7
--- src/utils/pool_ip.c
+++ src/utils/pool_ip.c
@@ -319,7 +319,11 @@ getaddrinfo_unix(const char *path, const struct addrin
 	aip->ai_addr = (struct sockaddr *) unp;
 	aip->ai_addrlen = sizeof(struct sockaddr_un);
 
+#ifdef HAVE_STRLCPY
+	strlcpy(unp->sun_path, path, sizeof(unp->sun_path));
+#else
 	strcpy(unp->sun_path, path);
+#endif
 
 #ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
 	unp->sun_len = sizeof(struct sockaddr_un);
blob - 43bdb7c5cebc41b86f0c45a1168f1bb1d0c77720
blob + a093a56e7849379abe76ba83652a068b586667b0
--- src/utils/pool_params.c
+++ src/utils/pool_params.c
@@ -118,16 +118,22 @@ int
 pool_add_param(ParamStatus * params, char *name, char *value)
 {
 	int			pos;
+	size_t		value_len;
 	MemoryContext oldContext = MemoryContextSwitchTo(TopMemoryContext);
 
 	if (pool_find_name(params, name, &pos))
 	{
 		/* name already exists */
-		if (strlen(params->values[pos]) < strlen(value))
+		value_len = strlen(value);
+		if (strlen(params->values[pos]) < value_len)
 		{
-			params->values[pos] = repalloc(params->values[pos], strlen(value) + 1);
+			params->values[pos] = repalloc(params->values[pos], value_len + 1);
 		}
+#ifdef HAVE_STRLCPY
+		strlcpy(params->values[pos], value, value_len + 1);
+#else
 		strcpy(params->values[pos], value);
+#endif
 	}
 	else
 	{
blob - 38220ac2c4d552b4ce0c399fe1ee4f9822dc3904
blob + e0781d83180a3eefdab5fd6e570d55616a6715e3
--- src/utils/pool_path.c
+++ src/utils/pool_path.c
@@ -355,7 +355,7 @@ make_absolute_path(const char *path, const char *base_
 			cwd = base_dir;
 
 		new = palloc(strlen(cwd) + strlen(path) + 2);
-		sprintf(new, "%s/%s", cwd, path);
+		snprintf(new, strlen(cwd) + strlen(path) + 2, "%s/%s", cwd, path);
 
 		if (!base_dir)
 			pfree((void *) cwd);
blob - 0b59e11cbf12098f61091b24defb582c7ff548a9
blob + 0c79f57e13e29eebf72931e9ed3bd6856e91af83
--- src/utils/scram-common.c
+++ src/utils/scram-common.c
@@ -223,7 +223,7 @@ scram_build_verifier(const char *salt, int saltlen, in
 
 	result = palloc(maxlen);
 
-	p = result + sprintf(result, "SCRAM-SHA-256$%d:", iterations);
+	p = result + snprintf(result, maxlen, "SCRAM-SHA-256$%d:", iterations);
 
 	p += pg_b64_encode(salt, saltlen, p);
 	*(p++) = '$';
blob - ca6467d30c2cb88e10897d173e94d37c2e147be8
blob + d783a6094259e3d730af284ca389599a801432e4
--- src/watchdog/watchdog.c
+++ src/watchdog/watchdog.c
@@ -791,7 +791,11 @@ wd_cluster_initialize(void)
 		g_cluster.remoteNodes[idx].wd_port = pool_config->wd_nodes.wd_node_info[i].wd_port;
 		g_cluster.remoteNodes[idx].pgpool_node_id = i;
 		g_cluster.remoteNodes[idx].pgpool_port = pool_config->wd_nodes.wd_node_info[i].pgpool_port;
+#ifdef HAVE_STRLCPY
+		strlcpy(g_cluster.remoteNodes[idx].hostname, pool_config->wd_nodes.wd_node_info[i].hostname, sizeof(g_cluster.remoteNodes[idx].hostname));
+#else
 		strcpy(g_cluster.remoteNodes[idx].hostname, pool_config->wd_nodes.wd_node_info[i].hostname);
+#endif
 		g_cluster.remoteNodes[idx].delegate_ip[0] = '\0'; /* this will be
 														 * populated by remote
 														 * node */
blob - 32b330e9659898ea391dd2216944ff300da8311e
blob + a696726de763655dda656a0ff9b4f67c17b64df1
--- src/watchdog/wd_ipc_conn.c
+++ src/watchdog/wd_ipc_conn.c
@@ -61,14 +61,22 @@ void wd_set_ipc_address(char *socket_dir, int port)
 	if (watchdog_ipc_address == NULL)
 	{
 		char		wd_ipc_sock_addr[255];
+#ifndef POOL_PRIVATE
+		size_t		watchdog_ipc_address_len;
+#endif
 
 		snprintf(wd_ipc_sock_addr, sizeof(wd_ipc_sock_addr), "%s/.s.PGPOOLWD_CMD.%d",
 				 socket_dir,
 				 port);
 
 #ifndef POOL_PRIVATE
-		watchdog_ipc_address = pool_shared_memory_segment_get_chunk(strlen(wd_ipc_sock_addr) + 1);
+		watchdog_ipc_address_len = strlen(wd_ipc_sock_addr) + 1;
+		watchdog_ipc_address = pool_shared_memory_segment_get_chunk(watchdog_ipc_address_len);
+#ifdef HAVE_STRLCPY
+		strlcpy(watchdog_ipc_address, wd_ipc_sock_addr, watchdog_ipc_address_len);
+#else
 		strcpy(watchdog_ipc_address, wd_ipc_sock_addr);
+#endif
 #else
 		watchdog_ipc_address = pstrdup(wd_ipc_sock_addr);
 #endif
blob - c399128b4c5f2bd15cdf6b4ea2840ce36b4ef321
blob + 9508b54bf7be592e6e057a0d565e98f726f4075b
--- src/watchdog/wd_lifecheck.c
+++ src/watchdog/wd_lifecheck.c
@@ -627,11 +627,17 @@ load_watchdog_nodes_from_json(char *json_data, int len
 		WDNodeInfo *nodeInfo = parse_watchdog_node_info_from_wd_node_json(value->u.array.values[i]);
 		
 		gslifeCheckCluster->lifeCheckNodes[i].wdState = nodeInfo->state;
+#ifdef HAVE_STRLCPY
+		strlcpy(gslifeCheckCluster->lifeCheckNodes[i].stateName, nodeInfo->stateName, sizeof(gslifeCheckCluster->lifeCheckNodes[i].stateName));
+		strlcpy(gslifeCheckCluster->lifeCheckNodes[i].hostName, nodeInfo->hostName, sizeof(gslifeCheckCluster->lifeCheckNodes[i].hostName));
+		strlcpy(gslifeCheckCluster->lifeCheckNodes[i].nodeName, nodeInfo->nodeName, sizeof(gslifeCheckCluster->lifeCheckNodes[i].nodeName));
+#else
 		strcpy(gslifeCheckCluster->lifeCheckNodes[i].stateName, nodeInfo->stateName);
-		gslifeCheckCluster->lifeCheckNodes[i].nodeState = NODE_EMPTY; /* This is local health check state*/
-		gslifeCheckCluster->lifeCheckNodes[i].ID = nodeInfo->id;
 		strcpy(gslifeCheckCluster->lifeCheckNodes[i].hostName, nodeInfo->hostName);
 		strcpy(gslifeCheckCluster->lifeCheckNodes[i].nodeName, nodeInfo->nodeName);
+#endif
+		gslifeCheckCluster->lifeCheckNodes[i].nodeState = NODE_EMPTY; /* This is local health check state*/
+		gslifeCheckCluster->lifeCheckNodes[i].ID = nodeInfo->id;
 		gslifeCheckCluster->lifeCheckNodes[i].wdPort = nodeInfo->wd_port;
 		gslifeCheckCluster->lifeCheckNodes[i].pgpoolPort = nodeInfo->pgpool_port;
 		gslifeCheckCluster->lifeCheckNodes[i].retry_lives = pool_config->wd_life_point;



More information about the pgpool-hackers mailing list