Index: trunk/include/iprt/mangling.h
===================================================================
--- trunk/include/iprt/mangling.h	(revision 83885)
+++ trunk/include/iprt/mangling.h	(revision 83886)
@@ -2113,4 +2113,6 @@
 # define RTStrDupNTag                                   RT_MANGLER(RTStrDupNTag)
 # define RTStrDupTag                                    RT_MANGLER(RTStrDupTag)
+# define RTStrEnd                                       RT_MANGLER(RTStrEnd)
+# define RTStrEnd_EndProc                               RT_MANGLER(RTStrEnd_EndProc)
 # define RTStrFormat                                    RT_MANGLER(RTStrFormat)
 # define RTStrFormatNumber                              RT_MANGLER(RTStrFormatNumber)
Index: trunk/include/iprt/string.h
===================================================================
--- trunk/include/iprt/string.h	(revision 83885)
+++ trunk/include/iprt/string.h	(revision 83886)
@@ -2611,6 +2611,4 @@
 RTDECL(int) RTStrNLenEx(const char *pszString, size_t cchMax, size_t *pcch);
 
-RT_C_DECLS_END
-
 /** The maximum size argument of a memchr call. */
 #define RTSTR_MEMCHR_MAX            ((~(size_t)0 >> 1) - 15)
@@ -2625,39 +2623,5 @@
  * @param   cchMax      The max string length.  RTSTR_MAX is fine.
  */
-#if defined(__cplusplus) && !defined(DOXYGEN_RUNNING)
-DECLINLINE(char const *) RTStrEnd(char const *pszString, size_t cchMax)
-{
-    /* Avoid potential issues with memchr seen in glibc.
-     * See sysdeps/x86_64/memchr.S in glibc versions older than 2.11 */
-    while (cchMax > RTSTR_MEMCHR_MAX)
-    {
-        char const *pszRet = (char const *)memchr(pszString, '\0', RTSTR_MEMCHR_MAX);
-        if (RT_LIKELY(pszRet))
-            return pszRet;
-        pszString += RTSTR_MEMCHR_MAX;
-        cchMax    -= RTSTR_MEMCHR_MAX;
-    }
-    return (char const *)memchr(pszString, '\0', cchMax);
-}
-
-DECLINLINE(char *) RTStrEnd(char *pszString, size_t cchMax)
-#else
-DECLINLINE(char *) RTStrEnd(const char *pszString, size_t cchMax)
-#endif
-{
-    /* Avoid potential issues with memchr seen in glibc.
-     * See sysdeps/x86_64/memchr.S in glibc versions older than 2.11 */
-    while (cchMax > RTSTR_MEMCHR_MAX)
-    {
-        char *pszRet = (char *)memchr(pszString, '\0', RTSTR_MEMCHR_MAX);
-        if (RT_LIKELY(pszRet))
-            return pszRet;
-        pszString += RTSTR_MEMCHR_MAX;
-        cchMax    -= RTSTR_MEMCHR_MAX;
-    }
-    return (char *)memchr(pszString, '\0', cchMax);
-}
-
-RT_C_DECLS_BEGIN
+RTDECL(char *) RTStrEnd(char const *pszString, size_t cchMax);
 
 /**
@@ -2677,5 +2641,4 @@
     return psz - pszHaystack;
 }
-
 
 /**
Index: trunk/src/VBox/Additions/common/VBoxGuest/freebsd/Makefile
===================================================================
--- trunk/src/VBox/Additions/common/VBoxGuest/freebsd/Makefile	(revision 83885)
+++ trunk/src/VBox/Additions/common/VBoxGuest/freebsd/Makefile	(revision 83886)
@@ -90,4 +90,5 @@
 	RTStrCopyEx.c \
 	RTStrCopyP.c \
+	RTStrEnd.c \
 	RTStrICmpAscii.c \
 	RTStrNICmpAscii.c \
Index: trunk/src/VBox/Additions/common/VBoxGuest/freebsd/files_vboxguest
===================================================================
--- trunk/src/VBox/Additions/common/VBoxGuest/freebsd/files_vboxguest	(revision 83885)
+++ trunk/src/VBox/Additions/common/VBoxGuest/freebsd/files_vboxguest	(revision 83886)
@@ -126,4 +126,5 @@
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrCopyEx.cpp=>common/string/RTStrCopyEx.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrCopyP.cpp=>common/string/RTStrCopyP.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrEnd.cpp=>common/string/RTStrEnd.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrICmpAscii.cpp=>common/string/RTStrICmpAscii.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrNICmpAscii.cpp=>common/string/RTStrNICmpAscii.c \
Index: trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile
===================================================================
--- trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile	(revision 83885)
+++ trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile	(revision 83886)
@@ -96,4 +96,5 @@
 	common/string/RTStrCopyEx.o \
 	common/string/RTStrCopyP.o \
+	common/string/RTStrEnd.o \
 	common/string/RTStrICmpAscii.o \
 	common/string/RTStrNICmpAscii.o \
Index: trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest
===================================================================
--- trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest	(revision 83885)
+++ trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest	(revision 83886)
@@ -142,4 +142,5 @@
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrCopyEx.cpp=>common/string/RTStrCopyEx.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrCopyP.cpp=>common/string/RTStrCopyP.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrEnd.cpp=>common/string/RTStrEnd.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrICmpAscii.cpp=>common/string/RTStrICmpAscii.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrNICmpAscii.cpp=>common/string/RTStrNICmpAscii.c \
Index: trunk/src/VBox/HostDrivers/Support/freebsd/Makefile
===================================================================
--- trunk/src/VBox/HostDrivers/Support/freebsd/Makefile	(revision 83885)
+++ trunk/src/VBox/HostDrivers/Support/freebsd/Makefile	(revision 83886)
@@ -95,4 +95,5 @@
 	RTStrCopyEx.c \
 	RTStrCopyP.c \
+	RTStrEnd.c \
 	strformat.c \
 	strformatnum.c \
Index: trunk/src/VBox/HostDrivers/Support/freebsd/files_vboxdrv
===================================================================
--- trunk/src/VBox/HostDrivers/Support/freebsd/files_vboxdrv	(revision 83885)
+++ trunk/src/VBox/HostDrivers/Support/freebsd/files_vboxdrv	(revision 83886)
@@ -127,4 +127,5 @@
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrCopy.cpp=>common/string/RTStrCopy.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrCopyEx.cpp=>common/string/RTStrCopyEx.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrEnd.cpp=>common/string/RTStrEnd.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrNCmp.cpp=>common/string/RTStrNCmp.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrNLen.cpp=>common/string/RTStrNLen.c \
Index: trunk/src/VBox/HostDrivers/Support/linux/Makefile
===================================================================
--- trunk/src/VBox/HostDrivers/Support/linux/Makefile	(revision 83885)
+++ trunk/src/VBox/HostDrivers/Support/linux/Makefile	(revision 83886)
@@ -93,4 +93,5 @@
 	common/string/RTStrCopyEx.o \
 	common/string/RTStrCopyP.o \
+	common/string/RTStrEnd.o \
 	common/string/RTStrNCmp.o \
 	common/string/RTStrNLen.o \
Index: trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv
===================================================================
--- trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv	(revision 83885)
+++ trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv	(revision 83886)
@@ -133,4 +133,5 @@
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrCopyEx.cpp=>common/string/RTStrCopyEx.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrCopyP.cpp=>common/string/RTStrCopyP.c \
+    ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrEnd.cpp=>common/string/RTStrEnd.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrNCmp.cpp=>common/string/RTStrNCmp.c \
     ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrNLen.cpp=>common/string/RTStrNLen.c \
Index: trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- trunk/src/VBox/Runtime/Makefile.kmk	(revision 83885)
+++ trunk/src/VBox/Runtime/Makefile.kmk	(revision 83886)
@@ -789,5 +789,6 @@
 	common/dbg/dbgstackdumpself.cpp \
 	common/dbg/dbgstackdumpself-amd64-x86.asm \
-	common/math/bignum-amd64-x86.asm
+	common/math/bignum-amd64-x86.asm \
+       common/string/RTStrEnd.asm
 RuntimeR3_SOURCES.amd64 += \
 	common/asm/ASMCpuIdExSlow.asm \
@@ -813,5 +814,6 @@
 	common/dbg/dbgstackdumpself-amd64-x86.asm \
 	common/math/bignum-amd64-x86.asm \
-	common/math/RTUInt128MulByU64.asm
+	common/math/RTUInt128MulByU64.asm \
+       common/string/RTStrEnd.asm
 
 # Some versions of GCC might require this.
@@ -823,4 +825,13 @@
 	common/asm/ASMAtomicUoReadU64.asm
 
+# Some non-assembly for non-AMD64 / non-x86 targets:
+RuntimeR3_SOURCES.arm32 += \
+	common/string/RTStrEnd.cpp
+RuntimeR3_SOURCES.arm64 += \
+	common/string/RTStrEnd.cpp
+RuntimeR3_SOURCES.sparc32 += \
+	common/string/RTStrEnd.cpp
+RuntimeR3_SOURCES.sparc64 += \
+	common/string/RTStrEnd.cpp
 
 # VBox specific stuff.
@@ -1800,4 +1811,5 @@
 	common/string/RTStrCopyEx.cpp \
 	common/string/RTStrCopyP.cpp \
+	common/string/RTStrEnd.cpp \
 	common/string/RTStrIStartsWith.cpp \
 	common/string/RTStrNCmp.cpp \
@@ -2286,5 +2298,6 @@
 		,$(PATH_SUB_CURRENT)/r3/win/VBoxRT-openssl-1.1plus.def )\
 		$(if-expr "$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)" == "win.x86" && defined(VBOX_WITH_MORE_NT4_COMPAT_BINARIES)\
-		,$(PATH_SUB_CURRENT)/r3/win/VBoxRT-msvcr100-win32.def ,) #$(PATH_SUB_CURRENT)/r3/win/VBoxRT-msvcp100-win32.def
+		,$(PATH_SUB_CURRENT)/r3/win/VBoxRT-msvcr100-win32.def ,) \
+		| $$(dir $$@) #$(PATH_SUB_CURRENT)/r3/win/VBoxRT-msvcp100-win32.def
 	$(RM) -f -- $@
 	$(REDIRECT) -wto $@ -- $(CAT_EXT) $^
@@ -2671,5 +2684,6 @@
 	common/asm/ASMFxRstor.asm \
 	common/asm/ASMRdMsrEx.asm \
-	common/asm/ASMWrMsrEx.asm
+	common/asm/ASMWrMsrEx.asm \
+	common/string/RTStrEnd.asm
 RuntimeR0_SOURCES.amd64 += \
 	common/asm/ASMCpuIdExSlow.asm \
@@ -2688,5 +2702,14 @@
 	common/asm/ASMFxRstor.asm \
 	common/asm/ASMRdMsrEx.asm \
-	common/asm/ASMWrMsrEx.asm
+	common/asm/ASMWrMsrEx.asm \
+	common/string/RTStrEnd.asm
+RuntimeR0_SOURCES.arm32 += \
+	common/string/RTStrEnd.cpp
+RuntimeR0_SOURCES.arm64 += \
+	common/string/RTStrEnd.cpp
+RuntimeR0_SOURCES.sparc32 += \
+	common/string/RTStrEnd.cpp
+RuntimeR0_SOURCES.sparc64 += \
+	common/string/RTStrEnd.cpp
 
 #if1of ($(KBUILD_TARGET_ARCH),amd64 x86)
@@ -2849,5 +2872,6 @@
 	common/asm/ASMWrMsrEx.asm \
 	common/math/bignum-amd64-x86.asm \
-	common/math/RTUInt128MulByU64.asm
+	common/math/RTUInt128MulByU64.asm \
+	common/string/RTStrEnd.asm
 RuntimeR0Drv_SOURCES.x86   = \
 	common/asm/ASMCpuIdExSlow.asm \
@@ -2855,6 +2879,14 @@
 	common/asm/ASMRdMsrEx.asm \
 	common/asm/ASMWrMsrEx.asm \
-	common/math/bignum-amd64-x86.asm
-
+	common/math/bignum-amd64-x86.asm \
+	common/string/RTStrEnd.asm
+RuntimeR0Drv_SOURCES.arm32 += \
+	common/string/RTStrEnd.cpp
+RuntimeR0Drv_SOURCES.arm64 += \
+	common/string/RTStrEnd.cpp
+RuntimeR0Drv_SOURCES.sparc32 += \
+	common/string/RTStrEnd.cpp
+RuntimeR0Drv_SOURCES.sparc64 += \
+	common/string/RTStrEnd.cpp
 
 RuntimeR0Drv_SOURCES.linux = \
@@ -3491,4 +3523,5 @@
  	common/string/RTStrCopy.cpp \
  	common/string/RTStrCopyEx.cpp \
+ 	common/string/RTStrEnd.asm \
  	common/string/RTStrICmpAscii.cpp \
  	common/table/avllu32.cpp \
Index: trunk/src/VBox/Runtime/common/string/RTStrEnd.asm
===================================================================
--- trunk/src/VBox/Runtime/common/string/RTStrEnd.asm	(revision 83886)
+++ trunk/src/VBox/Runtime/common/string/RTStrEnd.asm	(revision 83886)
@@ -0,0 +1,90 @@
+; $Id$
+;; @file
+; IPRT - RTStrEnd - AMD64 & X86.
+;
+
+;
+; Copyright (C) 2006-2020 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; General Public License (GPL) as published by the Free Software
+; Foundation, in version 2 as it comes in the "COPYING" file of the
+; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+; VirtualBox OSE distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+
+%include "iprt/asmdefs.mac"
+
+BEGINCODE
+
+;;
+; @param    pszString   gcc: rdi  msc: rcx  x86:[esp+4]   wcall: eax
+; @param    cchMax      gcc: rsi  msc: rdx  x86:[esp+8]   wcall: edx
+;
+BEGINPROC_EXPORTED RTStrEnd
+        cld
+%ifdef RT_ARCH_AMD64
+ %ifdef ASM_CALL64_MSC
+        or      rdx, rdx
+        jz      .not_found_early
+
+        mov     r9, rdi                 ; save rdi
+        mov     rdi, rcx
+        mov     rcx, rdx
+ %else
+        mov     rcx, rsi
+        jrcxz   .not_found_early
+ %endif
+
+%else
+ %ifdef ASM_CALL32_WATCOM
+        mov     ecx, edx
+        jecxz   .not_found_early
+        mov     edx, edi                ; save rdi
+        mov     edi, eax
+ %else
+        mov     ecx, [esp + 8]
+        jecxz   .not_found_early
+        mov     edx, edi                ; save edi
+        mov     edi, [esp + 4]
+ %endif
+%endif
+        xor     eax, eax                ; we're searching for zero
+
+        ; do the search
+        repne   scasb
+        jne     .not_found
+
+        ; found it
+        lea     xAX, [xDI - 1]
+%ifdef ASM_CALL64_MSC
+        mov     rdi, r9
+%endif
+%ifdef RT_ARCH_X86
+        mov     edi, edx
+%endif
+        ret
+
+.not_found:
+%ifdef ASM_CALL64_MSC
+        mov     rdi, r9
+%endif
+%ifdef RT_ARCH_X86
+        mov     edi, edx
+%endif
+.not_found_early:
+        xor     eax, eax
+        ret
+ENDPROC RTStrEnd
+
Index: trunk/src/VBox/Runtime/common/string/RTStrEnd.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/string/RTStrEnd.cpp	(revision 83886)
+++ trunk/src/VBox/Runtime/common/string/RTStrEnd.cpp	(revision 83886)
@@ -0,0 +1,46 @@
+/* $Id$ */
+/** @file
+ * IPRT - RTStrEnd, C++ version.
+ */
+
+/*
+ * Copyright (C) 2006-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/string.h>
+
+
+RTDECL(char *) RTStrEnd(const char *pszString, size_t cchMax)
+{
+    while (cchMax-- > 0)
+    {
+        if (*pszString)
+        { }
+        else
+            return pszString;
+        pszString++;
+    }
+    return NULL;
+}
+RT_EXPORT_SYMBOL(RTStrEnd);
Index: trunk/src/VBox/Runtime/testcase/tstUtf8.cpp
===================================================================
--- trunk/src/VBox/Runtime/testcase/tstUtf8.cpp	(revision 83885)
+++ trunk/src/VBox/Runtime/testcase/tstUtf8.cpp	(revision 83886)
@@ -1045,4 +1045,43 @@
         RTTESTI_CHECK(RTStrEnd(s_szEmpty, ~i) == &s_szEmpty[0]);
 
+    /* Check the implementation won't ever overshoot the '\0' in the input in
+       anyway that may lead to a SIGSEV. (VC++ 14.1 does this) */
+    size_t const cchStr = 1023;
+    char *pszStr = (char *)RTTestGuardedAllocTail(hTest, cchStr + 1);
+    memset(pszStr, ' ', cchStr);
+    char * const pszStrEnd = &pszStr[cchStr];
+    *pszStrEnd = '\0';
+    RTTEST_CHECK_RETV(hTest, strlen(pszStr) == cchStr);
+
+    for (size_t off = 0; off <= cchStr; off++)
+    {
+        RTTEST_CHECK(hTest, RTStrEnd(&pszStr[off], cchStr + 1 - off) == pszStrEnd);
+        RTTEST_CHECK(hTest, RTStrEnd(&pszStr[off], RTSTR_MAX) == pszStrEnd);
+
+        RTTEST_CHECK(hTest, memchr(&pszStr[off], '\0', cchStr + 1 - off) == pszStrEnd);
+        RTTEST_CHECK(hTest, strchr(&pszStr[off], '\0') == pszStrEnd);
+        RTTEST_CHECK(hTest, strchr(&pszStr[off], '?') == NULL);
+
+        size_t cchMax = 0;
+        for (; cchMax <= cchStr - off; cchMax++)
+        {
+            const char *pszRet = RTStrEnd(&pszStr[off], cchMax);
+            if (pszRet != NULL)
+            {
+                RTTestFailed(hTest, "off=%zu cchMax=%zu: %p, expected NULL\n", off, cchMax, pszRet);
+                break;
+            }
+        }
+        for (; cchMax <= _8K; cchMax++)
+        {
+            const char *pszRet = RTStrEnd(&pszStr[off], cchMax);
+            if (pszRet != pszStrEnd)
+            {
+                RTTestFailed(hTest, "off=%zu cchMax=%zu: off by %p\n", off, cchMax, pszRet);
+                break;
+            }
+        }
+    }
+    RTTestGuardedFree(hTest, pszStr);
 }
 
@@ -1424,7 +1463,8 @@
     if (rc == VINF_SUCCESS)
     {
-        RTTESTI_CHECK(!strcmp(pszOut, pszTest1));
         RTTestIPrintf(RTTESTLVL_ALWAYS, "CurrentCP is UTF-8 or similar (LC_ALL=%s LANG=%s LC_CTYPE=%s)\n",
                       RTEnvGet("LC_ALL"), RTEnvGet("LANG"), RTEnvGet("LC_CTYPE"));
+        if (strcmp(pszOut, pszTest1))
+            RTTestFailed(hTest, "mismatch\nutf8: %.*Rhxs\n got: %.*Rhxs\n", strlen(pszTest1), pszTest1, strlen(pszOut), pszOut);
         RTStrFree(pszOut);
     }
