[Tools v2] testbot/TestLauncher: Provide proper replacements for the str*_s() functions.

Francois Gouget fgouget at codeweavers.com
Tue Jun 13 03:34:13 CDT 2017


Simply mapping strncpy_s() to strncpy() means the string will not be
NUL-terminated! So instead provide proper implementations based on
Wine's code.

Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---

Signed!

Windows XP's msvcrt does not have the str*_s() functions but mapping 
them to their non _s() counterparts resulted in the test name sometimes 
not being NUL-terminated. As a result the start and done lines would not 
be recognized.

An alternative solution would be to eschew the buffer safety and switch 
to the non _s() functions with a couple of minor code adjustments. One 
could also provide simpler implementations that provide just enough 
functionality for TestLauncher. But determining this minimal 
implementation may be more work than just reusing Wine's implementation 
so that what I went with. And one day we'll likely be able to just 
assume msvcrt provides what we need.


 testbot/src/TestLauncher/TestLauncher.c | 84 +++++++++++++++++++++++++++++++--
 1 file changed, 81 insertions(+), 3 deletions(-)

diff --git a/testbot/src/TestLauncher/TestLauncher.c b/testbot/src/TestLauncher/TestLauncher.c
index a790470b..52af168a 100644
--- a/testbot/src/TestLauncher/TestLauncher.c
+++ b/testbot/src/TestLauncher/TestLauncher.c
@@ -19,12 +19,90 @@
  */
 
 #include <stdio.h>
+#include <errno.h>
 #include <windows.h>
 
 #ifdef __MINGW32__
-#define strcpy_s(dest, size, src) strcpy((dest), (src))
-#define strncpy_s(dest, size, src, max) strncpy((dest), (src), (max))
-#define strcat_s(dest, size, src) strcat((dest), (src))
+/* These functions are only available in recent msvcrt versions so provide
+ * replacements based on Wine's implementations.
+ */
+int CDECL mystrcpy_s( char* dst, size_t elem, const char* src )
+{
+    size_t i;
+    if(!elem) return EINVAL;
+    if(!dst) return EINVAL;
+    if(!src)
+    {
+        dst[0] = '\0';
+        return EINVAL;
+    }
+
+    for(i = 0; i < elem; i++)
+    {
+        if((dst[i] = src[i]) == '\0') return 0;
+    }
+    dst[0] = '\0';
+    return ERANGE;
+}
+#define strcpy_s(dest, size, src) mystrcpy_s(dest, size, src)
+
+int CDECL mystrncpy_s(char *dest, size_t numberOfElements,
+                    const char *src, size_t count)
+{
+    size_t i, end;
+
+    if(!count) {
+        if(dest && numberOfElements)
+            *dest = 0;
+        return 0;
+    }
+
+    if (dest == NULL || src == NULL || numberOfElements == 0) return EINVAL;
+
+    if(count!=_TRUNCATE && count<numberOfElements)
+        end = count;
+    else
+        end = numberOfElements-1;
+
+    for(i=0; i<end && src[i]; i++)
+        dest[i] = src[i];
+
+    if(!src[i] || end==count || count==_TRUNCATE) {
+        dest[i] = '\0';
+        return 0;
+    }
+
+    dest[0] = '\0';
+    return EINVAL;
+}
+#define strncpy_s(dest, size, src, max) mystrncpy_s(dest, size, src, max)
+
+int CDECL mystrcat_s( char* dst, size_t elem, const char* src )
+{
+    size_t i, j;
+    if(!dst) return EINVAL;
+    if(elem == 0) return EINVAL;
+    if(!src)
+    {
+        dst[0] = '\0';
+        return EINVAL;
+    }
+
+    for(i = 0; i < elem; i++)
+    {
+        if(dst[i] == '\0')
+        {
+            for(j = 0; (j + i) < elem; j++)
+            {
+                if((dst[j + i] = src[j]) == '\0') return 0;
+            }
+        }
+    }
+    /* Set the first element to 0, not the first element after the skipped part */
+    dst[0] = '\0';
+    return ERANGE;
+}
+#define strcat_s(dest, size, src) mystrcat_s(dest, size, src)
 #endif
 #define countof(Array) (sizeof(Array) / sizeof(Array[0]))
 
-- 
2.11.0



More information about the wine-patches mailing list