Avoid strdup in crypto/err/err.c

This makes me sad, but strdup may be more trouble than is worth it?
Being not in C (until C23) and only a (by POSIX standards) recent
addition to POSIX means a lot of folks seem to make it unnecessarily
hard to use:

- MSVC adds a deprecation warning that we have to suppress

- glibc gates it on feature macros; we just don't notice because we
  already have to work around their bad behavior for pthread_rwlock

- musl gates it on feature macros, which was one of the things that
  tripped cl/583161936

Given we only want to use strdup in one file (err.c, which wants to
avoid OPENSSL_malloc), a small reimplementation is probably not the end
of the world.

While I'm here, we can actually make OPENSSL_strdup's implementation a
little simpler.

Change-Id: I4e6c743b3104a67357d7d527c178c615de6bc844
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64047
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/err/err.c b/crypto/err/err.c
index d74144f..6f08e78 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -164,6 +164,17 @@
 extern const size_t kOpenSSLReasonValuesLen;
 extern const char kOpenSSLReasonStringData[];
 
+static char *strdup_libc_malloc(const char *str) {
+  // |strdup| is not in C until C23, so MSVC triggers deprecation warnings, and
+  // glibc and musl gate it on a feature macro. Reimplementing it is easier.
+  size_t len = strlen(str);
+  char *ret = malloc(len + 1);
+  if (ret != NULL) {
+    memcpy(ret, str, len + 1);
+  }
+  return ret;
+}
+
 // err_clear clears the given queued error.
 static void err_clear(struct err_error_st *error) {
   free(error->data);
@@ -174,13 +185,9 @@
   err_clear(dst);
   dst->file = src->file;
   if (src->data != NULL) {
-    // Disable deprecated functions on msvc so it doesn't complain about strdup.
-    OPENSSL_MSVC_PRAGMA(warning(push))
-    OPENSSL_MSVC_PRAGMA(warning(disable : 4996))
     // We can't use OPENSSL_strdup because we don't want to call OPENSSL_malloc,
     // which can affect the error stack.
-    dst->data = strdup(src->data);
-    OPENSSL_MSVC_PRAGMA(warning(pop))
+    dst->data = strdup_libc_malloc(src->data);
   }
   dst->packed = src->packed;
   dst->line = src->line;
@@ -767,13 +774,9 @@
     assert(0);
     return;
   }
-  // Disable deprecated functions on msvc so it doesn't complain about strdup.
-  OPENSSL_MSVC_PRAGMA(warning(push))
-  OPENSSL_MSVC_PRAGMA(warning(disable : 4996))
   // We can not use OPENSSL_strdup because we don't want to call OPENSSL_malloc,
   // which can affect the error stack.
-  char *copy = strdup(data);
-  OPENSSL_MSVC_PRAGMA(warning(pop))
+  char *copy = strdup_libc_malloc(data);
   if (copy != NULL) {
     err_set_error_data(copy);
   }
diff --git a/crypto/mem.c b/crypto/mem.c
index 0f286f8..23d49aa 100644
--- a/crypto/mem.c
+++ b/crypto/mem.c
@@ -398,13 +398,8 @@
   if (s == NULL) {
     return NULL;
   }
-  const size_t len = strlen(s) + 1;
-  char *ret = OPENSSL_malloc(len);
-  if (ret == NULL) {
-    return NULL;
-  }
-  OPENSSL_memcpy(ret, s, len);
-  return ret;
+  // Copy the NUL terminator.
+  return OPENSSL_memdup(s, strlen(s) + 1);
 }
 
 int OPENSSL_isalpha(int c) {