From 9eca2f81dc92f6e28ebe757262eb5b603166f3a2 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Mon, 31 Aug 2009 21:36:45 +0200 Subject: [PATCH] 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 7edcd6d427c..502703cef18 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 fd036479e56..5c475a0db4c 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 74beefbd7a4..aacf114829f 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -25,6 +25,7 @@ #include "config.h" #include +#include #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 96bcb7fa926..099924183c4 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(); } -- 2.11.4.GIT