From fffd651e83ccbd6191a76be6ec7c6b1b27888fde Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 10 Oct 2017 14:42:16 -0700
Subject: [PATCH] Rewrite strnlen replacement implementation from 8a241792f96.

The previous placement of the fallback implementation in libpgcommon
was problematic, because libpqport functions need strnlen
functionality.

Move replacement into libpgport. Provide strnlen() under its posix
name, instead of pg_strnlen(). Fix stupid configure bug, executing the
test only when compiled with threading support.

Author: Andres Freund
Discussion: https://postgr.es/m/E1e1gR2-0005fB-SI@gemulon.postgresql.org
---
 configure                     | 25 ++++++++++++++++++++++++-
 configure.in                  |  6 +++---
 src/backend/utils/mmgr/mcxt.c |  3 +--
 src/common/string.c           | 20 --------------------
 src/include/common/string.h   | 15 ---------------
 src/include/pg_config.h.in    |  4 ++++
 src/include/pg_config.h.win32 | 10 +++++++---
 src/include/port.h            |  4 ++++
 src/port/snprintf.c           |  4 +---
 src/port/strnlen.c            | 33 +++++++++++++++++++++++++++++++++
 10 files changed, 77 insertions(+), 47 deletions(-)
 create mode 100644 src/port/strnlen.c

diff --git a/configure b/configure
index a1283c05005..b0582657bf4 100755
--- a/configure
+++ b/configure
@@ -8777,7 +8777,7 @@ fi
 
 
 
-for ac_func in strerror_r getpwuid_r gethostbyname_r strnlen
+for ac_func in strerror_r getpwuid_r gethostbyname_r
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -13161,6 +13161,16 @@ fi
 cat >>confdefs.h <<_ACEOF
 #define HAVE_DECL_STRLCPY $ac_have_decl
 _ACEOF
+ac_fn_c_check_decl "$LINENO" "strnlenfrak" "ac_cv_have_decl_strnlen" "$ac_includes_default"
+if test "x$ac_cv_have_decl_strnlen" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_STRNLEN $ac_have_decl
+_ACEOF
 
 # This is probably only present on macOS, but may as well check always
 ac_fn_c_check_decl "$LINENO" "F_FULLFSYNC" "ac_cv_have_decl_F_FULLFSYNC" "#include <fcntl.h>
@@ -13528,6 +13538,19 @@ esac
 
 fi
 
+ac_fn_c_check_func "$LINENO" "strnlenfrak" "ac_cv_func_strnlen"
+if test "x$ac_cv_func_strnlen" = xyes; then :
+  $as_echo "#define HAVE_STRNLEN 1" >>confdefs.h
+
+else
+  case " $LIBOBJS " in
+  *" strnlen.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS strnlen.$ac_objext"
+ ;;
+esac
+
+fi
+
 
 
 case $host_os in
diff --git a/configure.in b/configure.in
index e1381b4ead6..4548db0dd3c 100644
--- a/configure.in
+++ b/configure.in
@@ -961,7 +961,7 @@ LIBS="$LIBS $PTHREAD_LIBS"
 AC_CHECK_HEADER(pthread.h, [], [AC_MSG_ERROR([
 pthread.h not found;  use --disable-thread-safety to disable thread safety])])
 
-AC_CHECK_FUNCS([strerror_r getpwuid_r gethostbyname_r strnlen])
+AC_CHECK_FUNCS([strerror_r getpwuid_r gethostbyname_r])
 
 # Do test here with the proper thread flags
 PGAC_FUNC_STRERROR_R_INT
@@ -1422,7 +1422,7 @@ AC_CHECK_DECLS(posix_fadvise, [], [], [#include <fcntl.h>])
 fi
 
 AC_CHECK_DECLS(fdatasync, [], [], [#include <unistd.h>])
-AC_CHECK_DECLS([strlcat, strlcpy])
+AC_CHECK_DECLS([strlcat, strlcpy, strnlen])
 # This is probably only present on macOS, but may as well check always
 AC_CHECK_DECLS(F_FULLFSYNC, [], [], [#include <fcntl.h>])
 
@@ -1514,7 +1514,7 @@ else
   AC_CHECK_FUNCS([fpclass fp_class fp_class_d class], [break])
 fi
 
-AC_REPLACE_FUNCS([crypt fls getopt getrusage inet_aton mkdtemp random rint srandom strerror strlcat strlcpy])
+AC_REPLACE_FUNCS([crypt fls getopt getrusage inet_aton mkdtemp random rint srandom strerror strlcat strlcpy strnlen])
 
 case $host_os in
 
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index 64e0408d5af..c5c311fad39 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -21,7 +21,6 @@
 
 #include "postgres.h"
 
-#include "common/string.h"
 #include "miscadmin.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
@@ -1089,7 +1088,7 @@ pnstrdup(const char *in, Size len)
 {
 	char	   *out;
 
-	len = pg_strnlen(in, len);
+	len = strnlen(in, len);
 
 	out = palloc(len + 1);
 	memcpy(out, in, len);
diff --git a/src/common/string.c b/src/common/string.c
index 901821f3d87..159d9ea7b62 100644
--- a/src/common/string.c
+++ b/src/common/string.c
@@ -41,23 +41,3 @@ pg_str_endswith(const char *str, const char *end)
 	str += slen - elen;
 	return strcmp(str, end) == 0;
 }
-
-
-/*
- * Portable version of posix' strnlen.
- *
- * Returns the number of characters before a null-byte in the string pointed
- * to by str, unless there's no null-byte before maxlen. In the latter case
- * maxlen is returned.
- */
-#ifndef HAVE_STRNLEN
-size_t
-pg_strnlen(const char *str, size_t maxlen)
-{
-	const char *p = str;
-
-	while (maxlen-- > 0 && *p)
-		p++;
-	return p - str;
-}
-#endif
diff --git a/src/include/common/string.h b/src/include/common/string.h
index 3d46b80918c..5f3ea71d613 100644
--- a/src/include/common/string.h
+++ b/src/include/common/string.h
@@ -12,19 +12,4 @@
 
 extern bool pg_str_endswith(const char *str, const char *end);
 
-/*
- * Portable version of posix' strnlen.
- *
- * Returns the number of characters before a null-byte in the string pointed
- * to by str, unless there's no null-byte before maxlen. In the latter case
- * maxlen is returned.
- *
- * Use the system strnlen if provided, it's likely to be faster.
- */
-#ifdef HAVE_STRNLEN
-#define pg_strnlen(str, maxlen) strnlen(str, maxlen)
-#else
-extern size_t pg_strnlen(const char *str, size_t maxlen);
-#endif
-
 #endif							/* COMMON_STRING_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index d20cc47fde0..b0298cca19c 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -147,6 +147,10 @@
    don't. */
 #undef HAVE_DECL_STRLCPY
 
+/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
+   don't. */
+#undef HAVE_DECL_STRNLEN
+
 /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
    don't. */
 #undef HAVE_DECL_SYS_SIGLIST
diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32
index 58eef0a538e..b76aad02676 100644
--- a/src/include/pg_config.h.win32
+++ b/src/include/pg_config.h.win32
@@ -99,6 +99,10 @@
    don't. */
 #define HAVE_DECL_SNPRINTF 1
 
+/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
+   don't. */
+#define HAVE_DECL_STRNLEN 1
+
 /* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you
    don't. */
 #define HAVE_DECL_VSNPRINTF 1
@@ -255,6 +259,9 @@
 /* Define to 1 if you have the <pam/pam_appl.h> header file. */
 /* #undef HAVE_PAM_PAM_APPL_H */
 
+/* Define to 1 if you have the `strnlen' function. */
+#define HAVE_STRNLEN 1
+
 /* Define to 1 if you have the `poll' function. */
 /* #undef HAVE_POLL */
 
@@ -345,9 +352,6 @@
 /* Define to 1 if you have the <string.h> header file. */
 #define HAVE_STRING_H 1
 
-/* Define to 1 if you have the `strnlen' function. */
-#define HAVE_STRNLEN
-
 /* Define to use have a strong random number source */
 #define HAVE_STRONG_RANDOM 1
 
diff --git a/src/include/port.h b/src/include/port.h
index b1ba645655f..17a7710a5e2 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -406,6 +406,10 @@ extern size_t strlcat(char *dst, const char *src, size_t siz);
 extern size_t strlcpy(char *dst, const char *src, size_t siz);
 #endif
 
+#if !HAVE_DECL_STRNLEN
+extern size_t strnlen(const char *str, size_t maxlen);
+#endif
+
 #if !defined(HAVE_RANDOM)
 extern long random(void);
 #endif
diff --git a/src/port/snprintf.c b/src/port/snprintf.c
index 531d2c5ee35..43c17e702e2 100644
--- a/src/port/snprintf.c
+++ b/src/port/snprintf.c
@@ -43,8 +43,6 @@
 #endif
 #include <sys/param.h>
 
-#include "common/string.h"
-
 #ifndef NL_ARGMAX
 #define NL_ARGMAX 16
 #endif
@@ -804,7 +802,7 @@ fmtstr(char *value, int leftjust, int minlen, int maxwidth,
 	 * than that.
 	 */
 	if (pointflag)
-		vallen = pg_strnlen(value, maxwidth);
+		vallen = strnlen(value, maxwidth);
 	else
 		vallen = strlen(value);
 
diff --git a/src/port/strnlen.c b/src/port/strnlen.c
new file mode 100644
index 00000000000..260b883368b
--- /dev/null
+++ b/src/port/strnlen.c
@@ -0,0 +1,33 @@
+/*-------------------------------------------------------------------------
+ *
+ * strnlen.c
+ *		Fallback implementation of strnlen().
+ *
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *	  src/port/strnlen.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+/*
+ * Implementation of posix' strnlen for systems where it's not available.
+ *
+ * Returns the number of characters before a null-byte in the string pointed
+ * to by str, unless there's no null-byte before maxlen. In the latter case
+ * maxlen is returned.
+ */
+size_t
+strnlen(const char *str, size_t maxlen)
+{
+	const char *p = str;
+
+	while (maxlen-- > 0 && *p)
+		p++;
+	return p - str;
+}
-- 
2.14.1.536.g6867272d5b.dirty

