Eric Pouech : msvcrt: Correctly handle the error cases in strtol and strtoul.

Alexandre Julliard julliard at winehq.org
Tue Sep 1 11:05:39 CDT 2009


Module: wine
Branch: master
Commit: 9eca2f81dc92f6e28ebe757262eb5b603166f3a2
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9eca2f81dc92f6e28ebe757262eb5b603166f3a2

Author: Eric Pouech <eric.pouech at orange.fr>
Date:   Mon Aug 31 21:36:45 2009 +0200

msvcrt: Correctly handle the error cases in strtol and strtoul.

---

 dlls/msvcrt/msvcrt.h       |    3 ++
 dlls/msvcrt/msvcrt.spec    |    4 +-
 dlls/msvcrt/string.c       |   64 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/msvcrt/tests/string.c |   40 +++++++++++++++++++++++++++
 4 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 7edcd6d..502703c 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -41,6 +41,9 @@
 #include "windef.h"
 #include "winbase.h"
 
+#define MSVCRT_LONG_MAX    0x7fffffffL
+#define MSVCRT_ULONG_MAX   0xffffffffUL
+
 typedef unsigned short MSVCRT_wchar_t;
 typedef unsigned short MSVCRT_wint_t;
 typedef unsigned short MSVCRT_wctype_t;
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index fd03647..5c475a0 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -767,8 +767,8 @@
 @ cdecl strstr(str str) ntdll.strstr
 @ cdecl strtod(str ptr) MSVCRT_strtod
 @ cdecl strtok(str str) MSVCRT_strtok
-@ cdecl strtol(str ptr long) ntdll.strtol
-@ cdecl strtoul(str ptr long) ntdll.strtoul
+@ cdecl strtol(str ptr long) MSVCRT_strtol
+@ cdecl strtoul(str ptr long) MSVCRT_strtoul
 @ cdecl strxfrm(ptr str long) MSVCRT_strxfrm
 @ varargs swprintf(ptr wstr) MSVCRT_swprintf
 @ varargs swscanf(wstr wstr) MSVCRT_swscanf
diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c
index 74beefb..aacf114 100644
--- a/dlls/msvcrt/string.c
+++ b/dlls/msvcrt/string.c
@@ -25,6 +25,7 @@
 #include "config.h"
 
 #include <stdlib.h>
+#include <errno.h>
 #include "msvcrt.h"
 #include "wine/debug.h"
 
@@ -250,3 +251,66 @@ int CDECL __STRINGTOLD( MSVCRT__LDOUBLE *value, char **endptr, const char *str,
 #endif
     return 0;
 }
+
+/******************************************************************
+ *		strtol (MSVCRT.@)
+ */
+long int MSVCRT_strtol(const char* nptr, char** end, int base)
+{
+    /* wrapper to forward libc error code to msvcrt's error codes */
+    long ret;
+
+    errno = 0;
+    ret = strtol(nptr, end, base);
+    switch (errno)
+    {
+    case ERANGE:        *MSVCRT__errno() = MSVCRT_ERANGE;       break;
+    case EINVAL:        *MSVCRT__errno() = MSVCRT_EINVAL;       break;
+    default:
+        /* cope with the fact that we may use 64bit long integers on libc
+         * while msvcrt always uses 32bit long integers
+         */
+        if (ret > MSVCRT_LONG_MAX)
+        {
+            ret = MSVCRT_LONG_MAX;
+            *MSVCRT__errno() = MSVCRT_ERANGE;
+        }
+        else if (ret < -MSVCRT_LONG_MAX - 1)
+        {
+            ret = -MSVCRT_LONG_MAX - 1;
+            *MSVCRT__errno() = MSVCRT_ERANGE;
+        }
+        break;
+    }
+
+    return ret;
+}
+
+/******************************************************************
+ *		strtoul (MSVCRT.@)
+ */
+unsigned long int MSVCRT_strtoul(const char* nptr, char** end, int base)
+{
+    /* wrapper to forward libc error code to msvcrt's error codes */
+    unsigned long ret;
+
+    errno = 0;
+    ret = strtoul(nptr, end, base);
+    switch (errno)
+    {
+    case ERANGE:        *MSVCRT__errno() = MSVCRT_ERANGE;       break;
+    case EINVAL:        *MSVCRT__errno() = MSVCRT_EINVAL;       break;
+    default:
+        /* cope with the fact that we may use 64bit long integers on libc
+         * while msvcrt always uses 32bit long integers
+         */
+        if (ret > MSVCRT_ULONG_MAX)
+        {
+            ret = MSVCRT_ULONG_MAX;
+            *MSVCRT__errno() = MSVCRT_ERANGE;
+        }
+        break;
+    }
+
+    return ret;
+}
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c
index 96bcb7f..0999241 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -663,6 +663,45 @@ static void test_strtok(void)
     }
 }
 
+static void test_strtol(void)
+{
+    char* e;
+    long l;
+    unsigned long ul;
+
+    /* errno is only set in case of error, so reset errno to EBADF to check for errno modification */
+    errno = EBADF;
+    l = strtol("-1234", &e, 0);
+    ok(l==-1234, "wrong value %ld\n", l);
+    ok(errno == EBADF, "wrong errno %d\n", errno);
+    errno = EBADF;
+    ul = strtoul("1234", &e, 0);
+    ok(ul==1234, "wrong value %lu\n", ul);
+    ok(errno == EBADF, "wrong errno %d\n", errno);
+
+    errno = EBADF;
+    l = strtol("2147483647L", &e, 0);
+    ok(l==2147483647, "wrong value %ld\n", l);
+    ok(errno == EBADF, "wrong errno %d\n", errno);
+    errno = EBADF;
+    l = strtol("-2147483648L", &e, 0);
+    ok(l==-2147483647L - 1, "wrong value %ld\n", l);
+    ok(errno == EBADF, "wrong errno %d\n", errno);
+    errno = EBADF;
+    ul = strtoul("4294967295UL", &e, 0);
+    ok(ul==4294967295ul, "wrong value %lu\n", ul);
+    ok(errno == EBADF, "wrong errno %d\n", errno);
+
+    errno = 0;
+    l = strtol("9223372036854775807L", &e, 0);
+    ok(l==2147483647, "wrong value %ld\n", l);
+    ok(errno == ERANGE, "wrong errno %d\n", errno);
+    errno = 0;
+    ul = strtoul("9223372036854775807L", &e, 0);
+    ok(ul==4294967295ul, "wrong value %lu\n", ul);
+    ok(errno == ERANGE, "wrong errno %d\n", errno);
+}
+
 START_TEST(string)
 {
     char mem[100];
@@ -706,4 +745,5 @@ START_TEST(string)
     test_mbcjisjms();
     test_strtok();
     test_wcscpy_s();
+    test_strtol();
 }




More information about the wine-cvs mailing list