From 1a679358844017c6f1b153630fbcfe935c26fd1f Mon Sep 17 00:00:00 2001 From: am11 <3840695+am11@users.noreply.github.com> Date: Sun, 8 Nov 2026 23:26:26 +0200 Subject: [PATCH 1/4] Delete FString and coreclr PAL's wchar.cpp Follow-up to #136973. * Replace the FString wrapper with direct minipal UTF-8 conversions in SString, CQuickBytes and JitHost. * Delete pal/src/cruntime/wchar.cpp. Its users within the PAL are inlined; the u16_strtoul, u16_strtoui64 and u16_strtod implementations move to coreclr minipal (dn-u16). * Add u16_stricmp and u16_strnicmp to dn-u16 and use them in place of _wcsicmp/_wcsnicmp. * Delete the corresponding PAL tests. Co-authored-by: Cursor --- .../dlls/mscordac/mscordac_unixexports.src | 11 - src/coreclr/ilasm/main.cpp | 4 +- src/coreclr/ildasm/dasm.cpp | 2 +- src/coreclr/ildasm/dman.cpp | 4 +- src/coreclr/inc/corhlprpriv.h | 71 +- src/coreclr/inc/eventtracebase.h | 8 +- src/coreclr/inc/fstring.h | 44 - src/coreclr/inc/sstring.inl | 4 +- src/coreclr/minipal/Unix/dn-u16.cpp | 132 ++- src/coreclr/minipal/Windows/dn-u16.cpp | 10 + src/coreclr/minipal/dn-u16.h | 2 + src/coreclr/pal/inc/pal.h | 27 - src/coreclr/pal/src/CMakeLists.txt | 1 - src/coreclr/pal/src/cruntime/wchar.cpp | 906 ------------------ src/coreclr/pal/src/debug/debug.cpp | 6 +- .../lttngprovider/eventproviderhelpers.cpp | 7 +- src/coreclr/pal/src/include/pal/corunix.hpp | 2 +- src/coreclr/pal/src/include/pal/cruntime.h | 32 - src/coreclr/pal/src/include/pal/palinternal.h | 1 + src/coreclr/pal/src/loader/module.cpp | 12 +- src/coreclr/pal/src/misc/dbgmsg.cpp | 1 - src/coreclr/pal/src/misc/environ.cpp | 12 +- src/coreclr/pal/src/misc/fmtmessage.cpp | 18 +- src/coreclr/pal/src/misc/utils.cpp | 2 +- .../pal/src/objmgr/listedobjectmanager.cpp | 5 +- src/coreclr/pal/src/thread/thread.cpp | 4 +- src/coreclr/pal/tests/palsuite/CMakeLists.txt | 20 - .../c_runtime/_wcsicmp/test1/test1.cpp | 67 -- .../c_runtime/_wcslwr_s/test1/test1.cpp | 5 +- .../c_runtime/_wcsnicmp/test1/test1.cpp | 94 -- .../palsuite/c_runtime/_wtoi/test1/test1.cpp | 78 -- .../palsuite/c_runtime/sscanf_s/sscanf_s.h | 4 +- .../palsuite/c_runtime/wcscat/test1/test1.cpp | 67 -- .../palsuite/c_runtime/wcschr/test1/test1.cpp | 50 - .../palsuite/c_runtime/wcscmp/test1/test1.cpp | 56 -- .../palsuite/c_runtime/wcscpy/test1/test1.cpp | 46 - .../palsuite/c_runtime/wcslen/test1/test1.cpp | 48 - .../c_runtime/wcsncmp/test1/test1.cpp | 72 -- .../c_runtime/wcsncpy/test1/test1.cpp | 83 -- .../c_runtime/wcsrchr/test1/test1.cpp | 47 - .../palsuite/c_runtime/wcsstr/test1/test1.cpp | 71 -- .../palsuite/c_runtime/wcstod/test1/test1.cpp | 78 -- .../palsuite/c_runtime/wcstod/test2/test2.cpp | 58 -- .../c_runtime/wcstoul/test1/test1.cpp | 48 - .../c_runtime/wcstoul/test2/test2.cpp | 48 - .../c_runtime/wcstoul/test3/test3.cpp | 48 - .../c_runtime/wcstoul/test4/test4.cpp | 51 - .../c_runtime/wcstoul/test5/test5.cpp | 68 -- .../c_runtime/wcstoul/test6/test6.cpp | 82 -- .../pal/tests/palsuite/common/palsuite.cpp | 42 +- .../pal/tests/palsuite/common/palsuite.h | 29 - .../pal/tests/palsuite/compilableTests.txt | 20 - .../FormatMessageW/test1/test.cpp | 3 +- .../FormatMessageW/test2/test.cpp | 3 +- .../FormatMessageW/test3/test.cpp | 3 +- .../FormatMessageW/test4/test.cpp | 3 +- .../FormatMessageW/test5/test.cpp | 3 +- .../FormatMessageW/test6/test.cpp | 3 +- .../GetEnvironmentStringsW/test1/test.cpp | 11 +- .../GetEnvironmentVariableW/test4/test.cpp | 3 +- .../GetEnvironmentVariableW/test5/test5.cpp | 5 +- .../GetEnvironmentVariableW/test6/test6.cpp | 3 +- .../SetEnvironmentVariableW/test1/test.cpp | 5 +- .../SetEnvironmentVariableW/test3/test3.cpp | 5 +- .../SetEnvironmentVariableW/test4/test4.cpp | 3 +- .../pal/tests/palsuite/paltestlist.txt | 20 - src/coreclr/tools/metainfo/mdobj.cpp | 6 +- src/coreclr/utilcode/CMakeLists.txt | 1 - src/coreclr/utilcode/fstring.cpp | 305 ------ src/coreclr/utilcode/sstring.cpp | 28 +- src/coreclr/vm/classhash.cpp | 1 - src/coreclr/vm/codeman.cpp | 6 +- src/coreclr/vm/eeconfig.cpp | 4 +- src/coreclr/vm/excep.cpp | 2 +- src/coreclr/vm/interoputil.cpp | 2 +- src/coreclr/vm/jithost.cpp | 14 +- 76 files changed, 275 insertions(+), 2875 deletions(-) delete mode 100644 src/coreclr/inc/fstring.h delete mode 100644 src/coreclr/pal/src/cruntime/wchar.cpp delete mode 100644 src/coreclr/pal/src/include/pal/cruntime.h delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcscat/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcschr/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcslen/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcstod/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcstod/test2/test2.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.cpp delete mode 100644 src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.cpp delete mode 100644 src/coreclr/utilcode/fstring.cpp diff --git a/src/coreclr/dlls/mscordac/mscordac_unixexports.src b/src/coreclr/dlls/mscordac/mscordac_unixexports.src index b21c32431ad380..c449259306207a 100644 --- a/src/coreclr/dlls/mscordac/mscordac_unixexports.src +++ b/src/coreclr/dlls/mscordac/mscordac_unixexports.src @@ -36,19 +36,8 @@ nativeStringResourceTable_mscorrc #PAL_InitializeDLL #PAL_TerminateEx #PAL_ProbeMemory -#PAL__wcstoui64 -#PAL_wcstoul -#PAL_wcstod #PAL_VirtualUnwindOutOfProc -#PAL_wcslen -#PAL_wcsncmp -#PAL_wcsrchr -#PAL_wcscmp -#PAL_wcschr -#PAL_wcscat -#PAL_wcsstr -#_wcsicmp #sprintf_s #vsprintf_s #_snprintf_s diff --git a/src/coreclr/ilasm/main.cpp b/src/coreclr/ilasm/main.cpp index ae417d4363850d..3d1e8e7ad0d173 100644 --- a/src/coreclr/ilasm/main.cpp +++ b/src/coreclr/ilasm/main.cpp @@ -271,9 +271,9 @@ extern "C" int _cdecl wmain(int argc, _In_ WCHAR **argv) WCHAR wzSubOpt[8]; wcsncpy_s(wzSubOpt,8,pStr,3); wzSubOpt[3] = 0; - if(0 == _wcsicmp(wzSubOpt,W("OPT"))) + if(0 == u16_stricmp(wzSubOpt,W("OPT"))) pAsm->m_dwIncludeDebugInfo = 0x3; - else if(0 == _wcsicmp(wzSubOpt,W("IMP"))) + else if(0 == u16_stricmp(wzSubOpt,W("IMP"))) pAsm->m_dwIncludeDebugInfo = 0x103; else { diff --git a/src/coreclr/ildasm/dasm.cpp b/src/coreclr/ildasm/dasm.cpp index 27a3c006947a72..19dea3a5ad0db7 100644 --- a/src/coreclr/ildasm/dasm.cpp +++ b/src/coreclr/ildasm/dasm.cpp @@ -6764,7 +6764,7 @@ void DumpMetaInfo(_In_ __nullterminated const WCHAR* pwzFileName, _In_opt_z_ con DumpMI((char*)GUICookie); // initialize the print function for DumpMetaInfo - if(pch && (!_wcsicmp(pch+1,W("lib")) || !_wcsicmp(pch+1,W("obj")))) + if(pch && (!u16_stricmp(pch+1,W("lib")) || !u16_stricmp(pch+1,W("obj")))) { // This works only when all the rest does not // Init and run. if (SUCCEEDED(CreateMetaDataDispenser(IID_IMetaDataDispenserEx, (void **)&g_pDisp))) diff --git a/src/coreclr/ildasm/dman.cpp b/src/coreclr/ildasm/dman.cpp index 7ca18ae832a2a8..74bbe1e2c68944 100644 --- a/src/coreclr/ildasm/dman.cpp +++ b/src/coreclr/ildasm/dman.cpp @@ -627,7 +627,7 @@ static BOOL ConvertToLegalFileNameInPlace(__inout LPWSTR wzName) for (size_t i = 0; i < (sizeof(rwzReserved) / sizeof(WCHAR *)); i++) { _ASSERTE(u16_strlen(rwzReserved[i]) == 3); - if (_wcsnicmp(wzName, rwzReserved[i], 3) == 0) + if (u16_strnicmp(wzName, rwzReserved[i], 3) == 0) { LPWSTR pwc = wzName + 3; @@ -856,7 +856,7 @@ void DumpManifestResources(void* GUICookie) for (ULONG i = 0; i < (ix + 2); i++) { WCHAR *wzPreviousName = (WCHAR *)qbNameArray[i].Ptr(); - if (wzPreviousName && _wcsicmp(wzName, wzPreviousName) == 0) + if (wzPreviousName && u16_stricmp(wzName, wzPreviousName) == 0) { // resource with the same name as another resource // or with the same name as the output IL/RES file diff --git a/src/coreclr/inc/corhlprpriv.h b/src/coreclr/inc/corhlprpriv.h index cd056e5b4704a0..cc42e7453f9783 100644 --- a/src/coreclr/inc/corhlprpriv.h +++ b/src/coreclr/inc/corhlprpriv.h @@ -11,7 +11,9 @@ #define __CORHLPRPRIV_H__ #include "corhlpr.h" -#include "fstring.h" +#include +#include +#include #if defined(_MSC_VER) && defined(HOST_X86) #pragma optimize("y", on) // If routines don't get inlined, don't pay the EBP frame penalty @@ -274,70 +276,39 @@ class CQuickMemoryBase } - // Convert UTF8 string to UNICODE string, optimized for speed - HRESULT ConvertUtf8_UnicodeNoThrow(const char * utf8str) - { - bool allAscii; - DWORD length; - - HRESULT hr = FString::Utf8_Unicode_Length(utf8str, & allAscii, & length); - - if (SUCCEEDED(hr)) - { - LPWSTR buffer = (LPWSTR) AllocNoThrow((length + 1) * sizeof(WCHAR)); - - if (buffer == NULL) - { - hr = E_OUTOFMEMORY; - } - else - { - hr = FString::Utf8_Unicode(utf8str, allAscii, buffer, length); - } - } - - return hr; - } - - // Convert UTF8 string to UNICODE string, optimized for speed + // Convert UTF8 string to UNICODE string void ConvertUtf8_Unicode(const char * utf8str) { - bool allAscii; - DWORD length; - - HRESULT hr = FString::Utf8_Unicode_Length(utf8str, & allAscii, & length); - - if (SUCCEEDED(hr)) + size_t sourceLength = strlen(utf8str) + 1; + size_t length = minipal_get_length_utf8_to_utf16(utf8str, sourceLength, 0); + if (length == 0) { - LPWSTR buffer = (LPWSTR) AllocThrows((length + 1) * sizeof(WCHAR)); - - hr = FString::Utf8_Unicode(utf8str, allAscii, buffer, length); + ThrowHR(HRESULT_FROM_WIN32(errno)); } - if (FAILED(hr)) + CHAR16_T* buffer = (CHAR16_T*) AllocThrows(length * sizeof(WCHAR)); + + if (minipal_convert_utf8_to_utf16(utf8str, sourceLength, buffer, length, 0) == 0) { - ThrowHR(hr); + ThrowHR(HRESULT_FROM_WIN32(errno)); } } - // Convert UNICODE string to UTF8 string, optimized for speed + // Convert UNICODE string to UTF8 string void ConvertUnicode_Utf8(const WCHAR * pString) { - bool allAscii; - DWORD length; - - HRESULT hr = FString::Unicode_Utf8_Length(pString, & allAscii, & length); - - if (SUCCEEDED(hr)) + size_t sourceLength = u16_strlen(pString) + 1; + size_t length = minipal_get_length_utf16_to_utf8((const CHAR16_T*)pString, sourceLength, 0); + if (length == 0) { - LPSTR buffer = (LPSTR) AllocThrows((length + 1) * sizeof(char)); - - hr = FString::Unicode_Utf8(pString, allAscii, buffer, length); + ThrowHR(HRESULT_FROM_WIN32(errno)); } - if (FAILED(hr)) + LPSTR buffer = (LPSTR) AllocThrows(length); + + if (minipal_convert_utf16_to_utf8((const CHAR16_T*)pString, sourceLength, buffer, length, 0) == 0) { - ThrowHR(hr); + ThrowHR(HRESULT_FROM_WIN32(errno)); } } diff --git a/src/coreclr/inc/eventtracebase.h b/src/coreclr/inc/eventtracebase.h index 9f2192c2a51422..6cf29375a22038 100644 --- a/src/coreclr/inc/eventtracebase.h +++ b/src/coreclr/inc/eventtracebase.h @@ -378,10 +378,10 @@ class XplatEventLoggerConfiguration uint32_t ParseLevel(ComponentSpan const & component) const { - int level = TRACE_LEVEL_VERBOSE; // Verbose + uint32_t level = TRACE_LEVEL_VERBOSE; // Verbose if ((component.End - component.Start) != 0) { - level = _wtoi(component.Start); + level = u16_strtoul(component.Start, nullptr, 10); } return level; } @@ -423,7 +423,7 @@ class XplatEventLoggerController auto providerName = config.GetProviderName(); auto enabledKeywordsMask = config.GetEnabledKeywordsMask(); auto level = config.GetLevel(); - if (_wcsicmp(providerName, W("*")) == 0 && enabledKeywordsMask == (ULONGLONG)(-1) && level == TRACE_LEVEL_VERBOSE) + if (u16_stricmp(providerName, W("*")) == 0 && enabledKeywordsMask == (ULONGLONG)(-1) && level == TRACE_LEVEL_VERBOSE) { ActivateAllKeywordsOfAllProviders(); } @@ -461,7 +461,7 @@ class XplatEventLoggerController auto length = u16_strlen(providerName); for (auto provider : ALL_LTTNG_PROVIDERS_CONTEXT) { - if (_wcsicmp(provider->Name, providerName) == 0) + if (u16_stricmp(provider->Name, providerName) == 0) { return provider; } diff --git a/src/coreclr/inc/fstring.h b/src/coreclr/inc/fstring.h deleted file mode 100644 index 1be37e242974c3..00000000000000 --- a/src/coreclr/inc/fstring.h +++ /dev/null @@ -1,44 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// --------------------------------------------------------------------------- -// FString.h (Fast String) -// - -// --------------------------------------------------------------------------- - -// ------------------------------------------------------------------------------------------ -// FString is fast string handling namespace - - -// 1) Simple -// 2) No C++ exception -// 3) Optimized for speed - - -#ifndef _FSTRING_H_ -#define _FSTRING_H_ - -namespace FString -{ - // Note: All "length" parameters do not count the space for the null terminator. - // Caller of Unicode_Utf8 and Utf8_Unicode must pass in a buffer of size at least length + 1. - - // Scan for ASCII only string, calculate result UTF8 string length - HRESULT Unicode_Utf8_Length(_In_z_ LPCWSTR pString, _Out_ bool * pAllAscii, _Out_ DWORD * pLength); - - // Convert UNICODE string to UTF8 string. Direct/fast conversion if ASCII - HRESULT Unicode_Utf8(_In_z_ LPCWSTR pString, bool allAscii, _Out_writes_bytes_(length) LPSTR pBuffer, DWORD length); - - // Scan for ASCII string, calculate result UNICODE string length - HRESULT Utf8_Unicode_Length(_In_z_ LPCSTR pString, _Out_ bool * pAllAscii, _Out_ DWORD * pLength); - - // Convert UTF8 string to UNICODE. Direct/fast conversion if ASCII - HRESULT Utf8_Unicode(_In_z_ LPCSTR pString, bool allAscii, _Out_writes_bytes_(length) LPWSTR pBuffer, DWORD length); - - HRESULT ConvertUnicode_Utf8(_In_z_ LPCWSTR pString, _Outptr_result_z_ LPSTR * pBuffer); - - HRESULT ConvertUtf8_Unicode(_In_z_ LPCSTR pString, _Outptr_result_z_ LPWSTR * pBuffer); - -} // namespace FString - -#endif // _FSTRING_H_ diff --git a/src/coreclr/inc/sstring.inl b/src/coreclr/inc/sstring.inl index 1d684563c62a80..e7ee28b3de3ca4 100644 --- a/src/coreclr/inc/sstring.inl +++ b/src/coreclr/inc/sstring.inl @@ -741,7 +741,7 @@ inline int SString::_wcsicmp(const WCHAR *buffer1, const WCHAR *buffer2) { WRAPPER_NO_CONTRACT; int returnValue = CaseCompareHelper(buffer1, buffer2, 0, TRUE, FALSE); #ifdef VERIFY_CRT_EQUIVALNCE - _ASSERTE((returnValue == 0) == (::_wcsicmp(buffer1, buffer2) == 0)); + _ASSERTE((returnValue == 0) == (u16_stricmp(buffer1, buffer2) == 0)); #endif return returnValue; @@ -752,7 +752,7 @@ inline int SString::_wcsnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_ WRAPPER_NO_CONTRACT; int returnValue = CaseCompareHelper(buffer1, buffer2, count, TRUE, TRUE); #ifdef VERIFY_CRT_EQUIVALNCE - _ASSERTE((returnValue == 0) == (::_wcsnicmp(buffer1, buffer2, count) == 0)); + _ASSERTE((returnValue == 0) == (u16_strnicmp(buffer1, buffer2, count) == 0)); #endif return returnValue; } diff --git a/src/coreclr/minipal/Unix/dn-u16.cpp b/src/coreclr/minipal/Unix/dn-u16.cpp index aec3fb1ae66388..ab6e323afb8c31 100644 --- a/src/coreclr/minipal/Unix/dn-u16.cpp +++ b/src/coreclr/minipal/Unix/dn-u16.cpp @@ -4,6 +4,9 @@ typedef char16_t WCHAR; #include +#include +#include +#include #include #include @@ -33,6 +36,33 @@ int u16_strncmp(const WCHAR* str1, const WCHAR* str2, size_t count) return diff; } +static WCHAR ascii_tolower(WCHAR ch) +{ + return (ch >= (WCHAR)'A' && ch <= (WCHAR)'Z') ? (WCHAR)(ch - 'A' + 'a') : ch; +} + +int u16_stricmp(const WCHAR* str1, const WCHAR* str2) +{ + return u16_strnicmp(str1, str2, SIZE_MAX); +} + +// Folds only ASCII letters, like the Windows CRT _wcsnicmp does in the default "C" locale. +int u16_strnicmp(const WCHAR* str1, const WCHAR* str2, size_t count) +{ + int diff = 0; + for (size_t i = 0; i < count; i++) + { + diff = ascii_tolower(str1[i]) - ascii_tolower(str2[i]); + if (diff != 0) + break; + + // stop if we reach the end of the string + if (str1[i] == (WCHAR)'\0') + break; + } + return diff; +} + WCHAR* u16_strcat_s(WCHAR* dst, size_t dstLen, const WCHAR* src) { if (dst == nullptr || src == nullptr) @@ -172,22 +202,110 @@ const WCHAR* u16_strrchr(const WCHAR* str, WCHAR ch) return last; } -// Forward declare PAL function -extern "C" uint32_t PAL_wcstoul(const WCHAR* nptr, WCHAR** endptr, int base); -extern "C" uint64_t PAL__wcstoui64(const WCHAR* nptr, WCHAR** endptr, int base); -extern "C" double PAL_wcstod(const WCHAR* nptr, WCHAR** endptr); +static bool is_ascii(WCHAR ch) +{ + return ch < 0x80; +} + +static bool is_floating_point_char(WCHAR ch) +{ + return ch == '+' || ch == '-' || ch == '.' || (ch >= '0' && ch <= '9') || + ch == 'e' || ch == 'E' || ch == 'd' || ch == 'D'; +} + +// Narrows the leading characters of str that satisfy the predicate into a malloc-ed buffer. +// The characters are ASCII, so offsets into the buffer are also offsets into str. +static char* narrow_prefix(const WCHAR* str, bool (*predicate)(WCHAR)) +{ + size_t length = 0; + while (str[length] != (WCHAR)'\0' && predicate(str[length])) + length++; + + char* buffer = (char*)malloc(length + 1); + if (buffer == nullptr) + return nullptr; + + for (size_t i = 0; i < length; i++) + buffer[i] = (char)str[i]; + + buffer[length] = '\0'; + return buffer; +} uint32_t u16_strtoul(const WCHAR* nptr, WCHAR** endptr, int base) { - return PAL_wcstoul(nptr, endptr, base); + char* buffer = narrow_prefix(nptr, is_ascii); + if (buffer == nullptr) + { + if (endptr != nullptr) + *endptr = (WCHAR*)nptr; + return 0; + } + + char* end; + unsigned long long value = strtoull(buffer, &end, base); + + // Windows' unsigned long is 32-bit. Negative inputs wrap around like they do there, + // unless their magnitude doesn't fit. + const char* p = buffer; + while (isspace((unsigned char)*p)) + p++; + + unsigned long long magnitude = (*p == '-') ? (0 - value) : value; + if (magnitude > UINT32_MAX) + { + value = UINT32_MAX; + errno = ERANGE; + } + + if (endptr != nullptr) + *endptr = (WCHAR*)nptr + (end - buffer); + + free(buffer); + return (uint32_t)value; } uint64_t u16_strtoui64(const WCHAR* nptr, WCHAR** endptr, int base) { - return PAL__wcstoui64(nptr, endptr, base); + char* buffer = narrow_prefix(nptr, is_ascii); + if (buffer == nullptr) + { + if (endptr != nullptr) + *endptr = (WCHAR*)nptr; + return 0; + } + + char* end; + unsigned long long value = strtoull(buffer, &end, base); + + if (endptr != nullptr) + *endptr = (WCHAR*)nptr + (end - buffer); + + free(buffer); + return value; } double u16_strtod(const WCHAR* nptr, WCHAR** endptr) { - return PAL_wcstod(nptr, endptr); + // Restrict the input to decimal notation; the C runtime strtod would also accept hex, "inf" and "nan". + const WCHAR* start = nptr; + while (is_ascii(*start) && isspace((unsigned char)*start)) + start++; + + char* buffer = narrow_prefix(start, is_floating_point_char); + if (buffer == nullptr) + { + if (endptr != nullptr) + *endptr = (WCHAR*)nptr; + return 0.0; + } + + char* end; + double value = strtod(buffer, &end); + + if (endptr != nullptr) + *endptr = (end == buffer) ? (WCHAR*)nptr : (WCHAR*)start + (end - buffer); + + free(buffer); + return value; } diff --git a/src/coreclr/minipal/Windows/dn-u16.cpp b/src/coreclr/minipal/Windows/dn-u16.cpp index c915a8907bb1ca..55a757972bb008 100644 --- a/src/coreclr/minipal/Windows/dn-u16.cpp +++ b/src/coreclr/minipal/Windows/dn-u16.cpp @@ -21,6 +21,16 @@ int u16_strncmp(const WCHAR* str1, const WCHAR* str2, size_t count) return ::wcsncmp(str1, str2, count); } +int u16_stricmp(const WCHAR* str1, const WCHAR* str2) +{ + return ::_wcsicmp(str1, str2); +} + +int u16_strnicmp(const WCHAR* str1, const WCHAR* str2, size_t count) +{ + return ::_wcsnicmp(str1, str2, count); +} + WCHAR* u16_strcpy_s(WCHAR* dst, size_t dstLen, const WCHAR* src) { if (0 != ::wcscpy_s(dst, dstLen, src)) diff --git a/src/coreclr/minipal/dn-u16.h b/src/coreclr/minipal/dn-u16.h index 73279aca16b6c2..28ca6707834932 100644 --- a/src/coreclr/minipal/dn-u16.h +++ b/src/coreclr/minipal/dn-u16.h @@ -11,6 +11,8 @@ size_t u16_strlen(const WCHAR* str); int u16_strcmp(const WCHAR* str1, const WCHAR* str2); int u16_strncmp(const WCHAR* str1, const WCHAR* str2, size_t count); +int u16_stricmp(const WCHAR* str1, const WCHAR* str2); +int u16_strnicmp(const WCHAR* str1, const WCHAR* str2, size_t count); WCHAR* u16_strcat_s(WCHAR* dst, size_t dstLen, const WCHAR* src); WCHAR* u16_strcpy_s(WCHAR* dst, size_t dstLen, const WCHAR* src); WCHAR* u16_strncpy_s(WCHAR* dst, size_t dstLen, const WCHAR* src, size_t count); diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 8e3e3b0b0a4051..8fbcca7ae8cfef 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -2736,29 +2736,13 @@ typedef int errno_t; PALIMPORT DLLEXPORT errno_t __cdecl memcpy_s(void *, size_t, const void *, size_t); PALIMPORT errno_t __cdecl memmove_s(void *, size_t, const void *, size_t); -PALIMPORT DLLEXPORT int __cdecl _wcsicmp(const WCHAR *, const WCHAR*); -PALIMPORT int __cdecl _wcsnicmp(const WCHAR *, const WCHAR *, size_t); PALIMPORT DLLEXPORT int __cdecl _vsnprintf_s(char *, size_t, size_t, const char *, va_list); PALIMPORT DLLEXPORT int __cdecl _snprintf_s(char *, size_t, size_t, const char *, ...); PALIMPORT DLLEXPORT int __cdecl vsprintf_s(char *, size_t, const char *, va_list); PALIMPORT DLLEXPORT int __cdecl sprintf_s(char *, size_t, const char *, ... ); PALIMPORT DLLEXPORT int __cdecl sscanf_s(const char *, const char *, ...); -PALIMPORT DLLEXPORT size_t __cdecl PAL_wcslen(const WCHAR *); -PALIMPORT DLLEXPORT int __cdecl PAL_wcscmp(const WCHAR*, const WCHAR*); -PALIMPORT DLLEXPORT int __cdecl PAL_wcsncmp(const WCHAR *, const WCHAR *, size_t); -PALIMPORT DLLEXPORT WCHAR * __cdecl PAL_wcscat(WCHAR *, const WCHAR *); -PALIMPORT WCHAR * __cdecl PAL_wcscpy(WCHAR *, const WCHAR *); -PALIMPORT WCHAR * __cdecl PAL_wcsncpy(WCHAR *, const WCHAR *, size_t); -PALIMPORT DLLEXPORT const WCHAR * __cdecl PAL_wcschr(const WCHAR *, WCHAR); -PALIMPORT DLLEXPORT const WCHAR * __cdecl PAL_wcsrchr(const WCHAR *, WCHAR); -PALIMPORT DLLEXPORT WCHAR _WConst_return * __cdecl PAL_wcsstr(const WCHAR *, const WCHAR *); -PALIMPORT DLLEXPORT ULONG __cdecl PAL_wcstoul(const WCHAR *, WCHAR **, int); -PALIMPORT DLLEXPORT ULONGLONG __cdecl PAL__wcstoui64(const WCHAR *, WCHAR **, int); -PALIMPORT DLLEXPORT double __cdecl PAL_wcstod(const WCHAR *, WCHAR **); - PALIMPORT errno_t __cdecl _wcslwr_s(WCHAR *, size_t sz); -PALIMPORT int __cdecl _wtoi(const WCHAR *); inline int _stricmp(const char* a, const char* b) { @@ -2779,17 +2763,6 @@ inline char* _strdup(const char* a) // As this allocates on the current stack frame, use a macro instead of an inline function. #define _alloca(x) alloca(x) -#ifdef __cplusplus -extern "C++" { -inline WCHAR *PAL_wcschr(WCHAR* S, WCHAR C) - {return ((WCHAR *)PAL_wcschr((const WCHAR *)S, C)); } -inline WCHAR *PAL_wcsrchr(WCHAR* S, WCHAR C) - {return ((WCHAR *)PAL_wcsrchr((const WCHAR *)S, C)); } -inline WCHAR *PAL_wcsstr(WCHAR* S, const WCHAR* P) - {return ((WCHAR *)PAL_wcsstr((const WCHAR *)S, P)); } -} -#endif - #if !__has_builtin(_rotl) && !defined(_rotl) /*++ Function: diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index 543e6802855237..1e8e8fdb646e01 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -147,7 +147,6 @@ endif() set(SOURCES com/guid.cpp - cruntime/wchar.cpp exception/seh.cpp handlemgr/handleapi.cpp handlemgr/handlemgr.cpp diff --git a/src/coreclr/pal/src/cruntime/wchar.cpp b/src/coreclr/pal/src/cruntime/wchar.cpp deleted file mode 100644 index 7ddcce37ad3e3a..00000000000000 --- a/src/coreclr/pal/src/cruntime/wchar.cpp +++ /dev/null @@ -1,906 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*++ -Module Name: - wchar.c - -Abstract: - Implementation of wide char string functions. ---*/ - -#include "pal/palinternal.h" -#include "pal/cruntime.h" -#include "pal/dbgmsg.h" - -#include "pal/thread.hpp" -#include "pal/threadsusp.hpp" - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -SET_DEFAULT_DEBUG_CHANNEL(CRT); - -/*-- -Function: - _wtoi - -See MSDN doc ---*/ -int -__cdecl -_wtoi( - const wchar_16 *string) -{ - size_t len; - int ret; - char *tempStr; - - PERF_ENTRY(_wtoi); - ENTRY("_wtoi (string=%p)\n", string); - - len = minipal_get_length_utf16_to_utf8((const CHAR16_T*)string, PAL_wcslen(string) + 1, 0); - if (!len) - { - ASSERT("UTF-16 to UTF-8 conversion failed. Error is %d\n", - GetLastError()); - return -1; - } - tempStr = (char *) malloc(len); - if (!tempStr) - { - ERROR("malloc failed\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return -1; - } - len = minipal_convert_utf16_to_utf8((const CHAR16_T*)string, PAL_wcslen(string) + 1, tempStr, len, 0); - if (!len) - { - ASSERT("UTF-16 to UTF-8 conversion failed. Error is %d\n", - GetLastError()); - free(tempStr); - return -1; - } - ret = atoi(tempStr); - - free(tempStr); - LOGEXIT("_wtoi returns int %d\n", ret); - PERF_EXIT(_wtoi); - return ret; -} - - -/*++ -Function: - _wcsnicmp - -Compare characters of two strings without regard to case - -Return Value - -The return value indicates the relationship between the substrings as follows. - -Return Value - -Description - -< 0 string1 substring less than string2 substring - 0 string1 substring identical to string2 substring -> 0 string1 substring greater than string2 substring - -Parameters - -string1, string2 Null-terminated strings to compare -count Number of characters to compare - -Remarks - -The _wcsnicmp function lexicographically compares, at most, the first -count characters of string1 and string2. The comparison is performed -without regard to case; _wcsnicmp is a case-insensitive version of -strncmp. The comparison ends if a terminating null character is -reached in either string before count characters are compared. If the -strings are equal when a terminating null character is reached in -either string before count characters are compared, the shorter string -is lesser. - ---*/ -int -__cdecl -_wcsnicmp( - const wchar_16 *string1, - const wchar_16 *string2, - size_t count) -{ - size_t i; - int diff = 0; - - PERF_ENTRY(_wcsnicmp); - ENTRY("_wcsnicmp (string1=%p (%S), string2=%p (%S), count=%lu)\n", - string1?string1:W16_NULLSTRING, - string1?string1:W16_NULLSTRING, string2?string2:W16_NULLSTRING, string2?string2:W16_NULLSTRING, - (unsigned long) count); - - for (i = 0; i < count; i++) - { - diff = towlower(string1[i]) - towlower(string2[i]); - if (diff != 0 || 0 == string1[i] || 0 == string2[i]) - { - break; - } - } - LOGEXIT("_wcsnicmp returning int %d\n", diff); - PERF_EXIT(_wcsnicmp); - return diff; -} - -/*++ -Function: - _wcsicmp - -Compare characters of two strings without regard to case - -Return Value - -The return value indicates the relationship between the substrings as follows. - -Return Value - -Description - -< 0 string1 substring less than string2 substring - 0 string1 substring identical to string2 substring -> 0 string1 substring greater than string2 substring - -Parameters - -string1, string2 Null-terminated strings to compare - ---*/ -int -__cdecl -_wcsicmp( - const wchar_16 *string1, - const wchar_16 *string2) -{ - int ret; - - PERF_ENTRY(_wcsicmp); - ENTRY("_wcsicmp (string1=%p (%S), string2=%p (%S))\n", - string1?string1:W16_NULLSTRING, - string1?string1:W16_NULLSTRING, string2?string2:W16_NULLSTRING, string2?string2:W16_NULLSTRING); - - ret = _wcsnicmp(string1, string2, 0x7fffffff); - - LOGEXIT("_wcsnicmp returns int %d\n", ret); - PERF_EXIT(_wcsicmp); - return ret; -} - -/*++ -Function: - PAL_wcstoul - -Convert string to an unsigned long-integer value. - -Return Value - -wcstoul returns the converted value, if any, or UINT32_MAX on -overflow. It returns 0 if no conversion can be performed. errno is -set to ERANGE if overflow or underflow occurs. - -Parameters - -nptr Null-terminated string to convert -endptr Pointer to character that stops scan -base Number base to use - -Remarks - -wcstoul stops reading the string nptr at the first character it cannot -recognize as part of a number. This may be the terminating null -character, or it may be the first numeric character greater than or -equal to base. The LC_NUMERIC category setting of the current locale -determines recognition of the radix character in nptr; for more -information, see setlocale. If endptr is not NULL, a pointer to the -character that stopped the scan is stored at the location pointed to -by endptr. If no conversion can be performed (no valid digits were -found or an invalid base was specified), the value of nptr is stored -at the location pointed to by endptr. - -Notes : - MSDN states that only space and tab are accepted as leading whitespace, but - tests indicate that other whitespace characters (newline, carriage return, - etc) are also accepted. This matches the behavior on Unix systems. - - For wcstol and wcstoul, we need to check if the value to be returned - is outside the 32 bit range. If so, the returned value needs to be set - as appropriate, according to the MSDN pages for wcstol and wcstoul, - and in all instances errno must be set to ERANGE (The one exception - is converting a string representing a negative value to unsigned long). - Note that on 64 bit Windows, long's are still 32 bit. Thus, to match - Windows behavior, we must return long's in the 32 bit range. ---*/ - -/* The use of ULONG is by design, to ensure that a 32 bit value is always -returned from this function. If "unsigned long" is used instead of ULONG, -then a 64 bit value could be returned on 64 bit platforms like HP-UX, thus -breaking Windows behavior .*/ -ULONG -__cdecl -PAL_wcstoul( - const wchar_16 *nptr, - wchar_16 **endptr, - int base) -{ - char *s_nptr = 0; - char *s_endptr = 0; - unsigned long res; - size_t size; - DWORD dwLastError = 0; - - PERF_ENTRY(wcstoul); - ENTRY("wcstoul (nptr=%p (%S), endptr=%p, base=%d)\n", nptr?nptr:W16_NULLSTRING, nptr?nptr:W16_NULLSTRING, - endptr, base); - - size = minipal_get_length_utf16_to_utf8((const CHAR16_T*)nptr, PAL_wcslen(nptr) + 1, 0); - if (!size) - { - dwLastError = GetLastError(); - ASSERT("UTF-16 to UTF-8 conversion failed. Error is %d\n", dwLastError); - SetLastError(ERROR_INVALID_PARAMETER); - res = 0; - goto PAL_wcstoulExit; - } - s_nptr = (char *)malloc(size); - if (!s_nptr) - { - ERROR("malloc failed\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - res = 0; - goto PAL_wcstoulExit; - } - size = minipal_convert_utf16_to_utf8((const CHAR16_T*)nptr, PAL_wcslen(nptr) + 1, s_nptr, size, 0); - if (!size) - { - dwLastError = GetLastError(); - ASSERT("UTF-16 to UTF-8 conversion failed. Error is %d\n", dwLastError); - SetLastError(ERROR_INVALID_PARAMETER); - res = 0; - goto PAL_wcstoulExit; - } - - res = strtoul(s_nptr, &s_endptr, base); - -#ifdef HOST_64BIT - if (res > UINT32_MAX) - { - wchar_16 wc = *nptr; - while (iswspace(wc)) - { - wc = *nptr++; - } - /* If the string represents a positive number that is greater than - _UI32_MAX, set errno to ERANGE. Otherwise, don't set errno - to match Windows behavior. */ - if (wc != '-') - { - res = UINT32_MAX; - errno = ERANGE; - } - } -#endif - - /* only ASCII characters will be accepted by strtol, and those always get - mapped to single-byte characters, so the first rejected character will - have the same index in the multibyte and widechar strings */ - if( endptr ) - { - size = s_endptr - s_nptr; - *endptr = (wchar_16 *)&nptr[size]; - } - -PAL_wcstoulExit: - free(s_nptr); - LOGEXIT("wcstoul returning unsigned long %lu\n", res); - PERF_EXIT(wcstoul); - - /* When returning unsigned long res from this function, it will be - implicitly cast to ULONG. This handles situations where a string that - represents a negative number is passed in to wcstoul. The Windows - behavior is analogous to taking the binary equivalent of the negative - value and treating it as a positive number. Returning a ULONG from - this function, as opposed to native unsigned long, allows us to match - this behavior. The explicit case to ULONG below is used to silence any - potential warnings due to the implicit casting. */ - return (ULONG)res; -} - -ULONGLONG -__cdecl -PAL__wcstoui64( - const wchar_16 *nptr, - wchar_16 **endptr, - int base) -{ - char *s_nptr = 0; - char *s_endptr = 0; - unsigned long long res; - size_t size; - DWORD dwLastError = 0; - - PERF_ENTRY(wcstoul); - ENTRY("_wcstoui64 (nptr=%p (%S), endptr=%p, base=%d)\n", nptr?nptr:W16_NULLSTRING, nptr?nptr:W16_NULLSTRING, - endptr, base); - - size = minipal_get_length_utf16_to_utf8((const CHAR16_T*)nptr, PAL_wcslen(nptr) + 1, 0); - if (!size) - { - dwLastError = GetLastError(); - ASSERT("UTF-16 to UTF-8 conversion failed. Error is %d\n", dwLastError); - SetLastError(ERROR_INVALID_PARAMETER); - res = 0; - goto PAL__wcstoui64Exit; - } - s_nptr = (char *)malloc(size); - if (!s_nptr) - { - ERROR("malloc failed\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - res = 0; - goto PAL__wcstoui64Exit; - } - size = minipal_convert_utf16_to_utf8((const CHAR16_T*)nptr, PAL_wcslen(nptr) + 1, s_nptr, size, 0); - if (!size) - { - dwLastError = GetLastError(); - ASSERT("UTF-16 to UTF-8 conversion failed. Error is %d\n", dwLastError); - SetLastError(ERROR_INVALID_PARAMETER); - res = 0; - goto PAL__wcstoui64Exit; - } - - res = strtoull(s_nptr, &s_endptr, base); - - /* only ASCII characters will be accepted by strtoull, and those always get - mapped to single-byte characters, so the first rejected character will - have the same index in the multibyte and widechar strings */ - if( endptr ) - { - size = s_endptr - s_nptr; - *endptr = (wchar_16 *)&nptr[size]; - } - -PAL__wcstoui64Exit: - free(s_nptr); - LOGEXIT("_wcstoui64 returning unsigned long long %llu\n", res); - PERF_EXIT(_wcstoui64); - - return res; -} - -WCHAR * __cdecl PAL_wcsncat(WCHAR *, const WCHAR *, size_t); - -/*++ -Function: - PAL_wcscat - -See MSDN or the man page for mcscat. - ---*/ -wchar_16 * -__cdecl -PAL_wcscat( - wchar_16 *strDestination, - const wchar_16 *strSource) -{ - wchar_16 *ret; - PERF_ENTRY(wcscat); - ENTRY("wcscat (strDestination=%p (%S), strSource=%p (%S))\n", - strDestination?strDestination:W16_NULLSTRING, - strDestination?strDestination:W16_NULLSTRING, strSource?strSource:W16_NULLSTRING, strSource?strSource:W16_NULLSTRING); - - ret = PAL_wcsncat( strDestination, strSource, PAL_wcslen( strSource ) ); - - LOGEXIT("wcscat returnng wchar_t %p (%S)\n", ret, ret); - PERF_EXIT(wcscat); - return ret; -} - - -/*++ -Function: - PAL_wcscpy - -See MSDN or the man page for mcscpy. - ---*/ -wchar_16 * -__cdecl -PAL_wcscpy( - wchar_16 *strDestination, - const wchar_16 *strSource) -{ - wchar_16 *start = strDestination; - - PERF_ENTRY(wcscpy); - ENTRY("wcscpy (strDestination=%p, strSource=%p (%S))\n", - strDestination, strSource ? strSource:W16_NULLSTRING, strSource ? strSource:W16_NULLSTRING); - - if (strDestination == NULL) - { - ERROR("invalid strDestination argument\n"); - LOGEXIT("wcscpy returning wchar_t NULL\n"); - PERF_EXIT(wcscpy); - return NULL; - } - - if (strSource == NULL) - { - ERROR("invalid strSource argument\n"); - LOGEXIT("wcscpy returning wchar_t NULL\n"); - PERF_EXIT(wcscpy); - return NULL; - } - - /* copy source string to destination string */ - while(*strSource) - { - *strDestination++ = *strSource++; - } - - /* add terminating null */ - *strDestination = '\0'; - - LOGEXIT("wcscpy returning wchar_t %p (%S)\n", start, start); - PERF_EXIT(wcscpy); - return start; -} - - -/*++ -Function: - PAL_wcslen - -See MSDN or the man page for wcslen. - ---*/ -size_t -__cdecl -PAL_wcslen( - const wchar_16 *string) -{ - size_t nChar = 0; - - PERF_ENTRY(wcslen); - ENTRY("wcslen (string=%p (%S))\n", string?string:W16_NULLSTRING, string?string:W16_NULLSTRING); - - if ( !string ) - { - LOGEXIT("wcslen returning size_t %u\n", 0); - PERF_EXIT(wcslen); - return 0; - } - while (*string++) - { - nChar++; - } - - LOGEXIT("wcslen returning size_t %u\n", nChar); - PERF_EXIT(wcslen); - return nChar; -} - - -/*++ -Function: - PAL_wcsncmp - -See MSDN or the man page for wcsncmp. ---*/ -int -__cdecl -PAL_wcsncmp( - const wchar_16 *string1, - const wchar_16 *string2, - size_t count) -{ - size_t i; - int diff = 0; - - PERF_ENTRY(wcsncmp); - ENTRY("wcsncmp (string1=%p (%S), string2=%p (%S) count=%lu)\n", - string1?string1:W16_NULLSTRING, - string1?string1:W16_NULLSTRING, string2?string2:W16_NULLSTRING, string2?string2:W16_NULLSTRING, - (unsigned long) count); - - for (i = 0; i < count; i++) - { - diff = string1[i] - string2[i]; - if (diff != 0) - { - break; - } - - /* stop if we reach the end of the string */ - if(string1[i]==0) - { - break; - } - } - LOGEXIT("wcsncmp returning int %d\n", diff); - PERF_EXIT(wcsncmp); - return diff; -} - -/*++ -Function: - PAL_wcscmp - -See MSDN or the man page for wcscmp. ---*/ -int -__cdecl -PAL_wcscmp( - const wchar_16 *string1, - const wchar_16 *string2) -{ - int ret; - - PERF_ENTRY(wcscmp); - ENTRY("wcscmp (string1=%p (%S), string2=%p (%S))\n", - string1?string1:W16_NULLSTRING, - string1?string1:W16_NULLSTRING, string2?string2:W16_NULLSTRING, string2?string2:W16_NULLSTRING); - - ret = PAL_wcsncmp(string1, string2, 0x7fffffff); - - LOGEXIT("wcscmp returns int %d\n", ret); - PERF_EXIT(wcscmp); - return ret; -} - -/*++ -Function: - PAL_wcschr - -See MSDN or man page for wcschr. - ---*/ -wchar_16 _WConst_return * -__cdecl -PAL_wcschr( - const wchar_16 * string, - wchar_16 c) -{ - PERF_ENTRY(wcschr); - ENTRY("wcschr (string=%p (%S), c=%C)\n", string?string:W16_NULLSTRING, string?string:W16_NULLSTRING, c); - - while (*string) - { - if (*string == c) - { - LOGEXIT("wcschr returning wchar_t %p (%S)\n", string, string); - PERF_EXIT(wcschr); - return (wchar_16 *) string; - } - string++; - } - - // Check if the comparand was \000 - if (*string == c) - return (wchar_16 *) string; - - LOGEXIT("wcschr returning wchar_t NULL\n"); - PERF_EXIT(wcschr); - return NULL; -} - - -/*++ -Function: - PAL_wcsrchr - -See MSDN or man page for wcsrchr. - ---*/ -wchar_16 _WConst_return * -__cdecl -PAL_wcsrchr( - const wchar_16 * string, - wchar_16 c) -{ - wchar_16 *last = NULL; - - PERF_ENTRY(wcsrchr); - ENTRY("wcsrchr (string=%p (%S), c=%C)\n", string?string:W16_NULLSTRING, string?string:W16_NULLSTRING, c); - - while (*string) - { - if (*string == c) - { - last = (wchar_16 *) string; - } - string++; - } - - LOGEXIT("wcsrchr returning wchar_t %p (%S)\n", last?last:W16_NULLSTRING, last?last:W16_NULLSTRING); - PERF_EXIT(wcsrchr); - return (wchar_16 *)last; -} - - -/*++ -Function: - PAL_wcsstr - -See MSDN or man page for wcsstr. ---*/ -const wchar_16 * -__cdecl -PAL_wcsstr( - const wchar_16 *string, - const wchar_16 *strCharSet) -{ - wchar_16 *ret = NULL; - int i; - - PERF_ENTRY(wcsstr); - ENTRY("wcsstr (string=%p (%S), strCharSet=%p (%S))\n", - string?string:W16_NULLSTRING, - string?string:W16_NULLSTRING, strCharSet?strCharSet:W16_NULLSTRING, strCharSet?strCharSet:W16_NULLSTRING); - - if (string == NULL) - { - ret = NULL; - goto leave; - } - - if (strCharSet == NULL) - { - ret = NULL; - goto leave; - } - - if (*strCharSet == 0) - { - ret = (wchar_16 *)string; - goto leave; - } - - while (*string != 0) - { - i = 0; - while (1) - { - if (*(strCharSet + i) == 0) - { - ret = (wchar_16 *) string; - goto leave; - } - else if (*(string + i) == 0) - { - ret = NULL; - goto leave; - } - else if (*(string + i) != *(strCharSet + i)) - { - break; - } - - i++; - } - string++; - } - - leave: - LOGEXIT("wcsstr returning wchar_t %p (%S)\n", ret?ret:W16_NULLSTRING, ret?ret:W16_NULLSTRING); - PERF_EXIT(wcsstr); - return ret; -} - -/*++ -Function : - - PAL_wcsncpy - -see msdn doc. ---*/ -wchar_16 * -__cdecl -PAL_wcsncpy( wchar_16 * strDest, const wchar_16 *strSource, size_t count ) -{ - UINT length = sizeof( wchar_16 ) * count; - PERF_ENTRY(wcsncpy); - ENTRY("wcsncpy( strDest:%p, strSource:%p (%S), count:%lu)\n", - strDest, strSource, strSource, (unsigned long) count); - - memset( strDest, 0, length ); - length = std::min( count, PAL_wcslen( strSource ) ) * sizeof( wchar_16 ); - memcpy( strDest, strSource, length ); - - LOGEXIT("wcsncpy returning (wchar_16*): %p\n", strDest); - PERF_EXIT(wcsncpy); - return strDest; -} - -/*++ -Function : - - wcsncat - -see msdn doc. ---*/ -wchar_16 * -__cdecl -PAL_wcsncat( wchar_16 * strDest, const wchar_16 *strSource, size_t count ) -{ - wchar_16 *start = strDest; - UINT LoopCount = 0; - UINT StrSourceLength = 0; - - PERF_ENTRY(wcsncat); - ENTRY( "wcsncat (strDestination=%p (%S), strSource=%p (%S), count=%lu )\n", - strDest ? strDest : W16_NULLSTRING, - strDest ? strDest : W16_NULLSTRING, - strSource ? strSource : W16_NULLSTRING, - strSource ? strSource : W16_NULLSTRING, (unsigned long) count); - - if ( strDest == NULL ) - { - ERROR("invalid strDest argument\n"); - LOGEXIT("wcsncat returning wchar_t NULL\n"); - PERF_EXIT(wcsncat); - return NULL; - } - - if ( strSource == NULL ) - { - ERROR("invalid strSource argument\n"); - LOGEXIT("wcsncat returning wchar_t NULL\n"); - PERF_EXIT(wcsncat); - return NULL; - } - - /* find end of source string */ - while ( *strDest ) - { - strDest++; - } - - StrSourceLength = PAL_wcslen( strSource ); - if ( StrSourceLength < count ) - { - count = StrSourceLength; - } - - /* concatenate new string */ - while( *strSource && LoopCount < count ) - { - *strDest++ = *strSource++; - LoopCount++; - } - - /* add terminating null */ - *strDest = '\0'; - - LOGEXIT("wcsncat returning wchar_t %p (%S)\n", start, start); - PERF_EXIT(wcsncat); - return start; -} - -static BOOL MISC_CRT_WCSTOD_IsValidCharacter( WCHAR c ) -{ - if ( c == '+' || c == '-' || c == '.' || ( c >= '0' && c <= '9' ) || - c == 'e' || c == 'E' || c == 'd' || c == 'D' ) - { - return TRUE; - } - return FALSE; -} - -/*++ -Function : - - wcstod - - There is a slight difference between the Windows version of wcstod - and the BSD versio of wcstod. - - Under Windows the string " -1b " returns -1.000000 stop char = 'b' - Under BSD the same string returns 0.000000 stop ' ' - -see msdn doc. ---*/ -double -__cdecl -PAL_wcstod( const wchar_16 * nptr, wchar_16 **endptr ) -{ - double RetVal = 0.0; - LPSTR lpStringRep = NULL; - LPWSTR lpStartOfExpression = (LPWSTR)nptr; - LPWSTR lpEndOfExpression = NULL; - UINT Length = 0; - - PERF_ENTRY(wcstod); - ENTRY( "wcstod( %p (%S), %p (%S) )\n", nptr, nptr, endptr , endptr ); - - if ( !nptr ) - { - ERROR( "nptr is invalid.\n" ); - LOGEXIT( "wcstod returning 0.0\n" ); - PERF_EXIT(wcstod); - return 0.0; - } - - /* Eat white space. */ - while ( iswspace( *lpStartOfExpression ) ) - { - lpStartOfExpression++; - } - - /* Get the end of the expression. */ - lpEndOfExpression = lpStartOfExpression; - while ( *lpEndOfExpression ) - { - if ( !MISC_CRT_WCSTOD_IsValidCharacter( *lpEndOfExpression ) ) - { - break; - } - lpEndOfExpression++; - } - - if ( lpEndOfExpression != lpStartOfExpression ) - { - Length = lpEndOfExpression - lpStartOfExpression; - lpStringRep = (LPSTR)malloc( Length + 1); - - if ( lpStringRep ) - { - if ( minipal_convert_utf16_to_utf8( (const CHAR16_T*)lpStartOfExpression, Length, - lpStringRep, Length + 1, 0 ) != 0 ) - { - LPSTR ScanStop = NULL; - lpStringRep[Length]= 0; - RetVal = strtod( lpStringRep, &ScanStop ); - - /* See if strtod failed. */ - if ( RetVal == 0.0 && ScanStop == lpStringRep ) - { - ASSERT( "An error occurred in the conversion.\n" ); - lpEndOfExpression = (LPWSTR)nptr; - } - } - else - { - ASSERT( "Wide char to multibyte conversion failed.\n" ); - lpEndOfExpression = (LPWSTR)nptr; - } - } - else - { - ERROR( "Not enough memory.\n" ); - lpEndOfExpression = (LPWSTR)nptr; - } - } - else - { - ERROR( "Malformed expression.\n" ); - lpEndOfExpression = (LPWSTR)nptr; - } - - /* Set the stop scan character. */ - if ( endptr != NULL ) - { - *endptr = lpEndOfExpression; - } - - free( lpStringRep ); - LOGEXIT( "wcstod returning %f.\n", RetVal ); - PERF_EXIT(wcstod); - return RetVal; -} diff --git a/src/coreclr/pal/src/debug/debug.cpp b/src/coreclr/pal/src/debug/debug.cpp index 0a7097bbccdcf6..5663b7120eb41b 100644 --- a/src/coreclr/pal/src/debug/debug.cpp +++ b/src/coreclr/pal/src/debug/debug.cpp @@ -184,7 +184,7 @@ OutputDebugStringW( goto EXIT; } - if ((strLen = minipal_get_length_utf16_to_utf8((const CHAR16_T*)lpOutputString, PAL_wcslen(lpOutputString) + 1, 0)) + if ((strLen = minipal_get_length_utf16_to_utf8((const CHAR16_T*)lpOutputString, minipal_u16_strlen((const CHAR16_T*)lpOutputString) + 1, 0)) == 0) { ASSERT("failed to get wide chars length\n"); @@ -200,7 +200,7 @@ OutputDebugStringW( goto EXIT; } - if(! minipal_convert_utf16_to_utf8((const CHAR16_T*)lpOutputString, PAL_wcslen(lpOutputString) + 1, + if(! minipal_convert_utf16_to_utf8((const CHAR16_T*)lpOutputString, minipal_u16_strlen((const CHAR16_T*)lpOutputString) + 1, lpOutputStringA, strLen, 0)) { ASSERT("failed to convert wide chars to multibytes\n"); @@ -321,7 +321,7 @@ DebugBreakCommand() if (exe_module.lib_name != NULL) { - libNameLength = PAL_wcslen(exe_module.lib_name); + libNameLength = minipal_u16_strlen((const CHAR16_T*)exe_module.lib_name); } SIZE_T dwexe_buf = strlen(EXE_TEXT) + libNameLength + 1; diff --git a/src/coreclr/pal/src/eventprovider/lttngprovider/eventproviderhelpers.cpp b/src/coreclr/pal/src/eventprovider/lttngprovider/eventproviderhelpers.cpp index 41f7f8627cb518..1b807b55a31a50 100644 --- a/src/coreclr/pal/src/eventprovider/lttngprovider/eventproviderhelpers.cpp +++ b/src/coreclr/pal/src/eventprovider/lttngprovider/eventproviderhelpers.cpp @@ -53,7 +53,12 @@ bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, s bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) { if(!str) return true; - size_t byteCount = (PAL_wcslen(str) + 1) * sizeof(*str); + size_t length = 0; + while (str[length] != '\0') + { + length++; + } + size_t byteCount = (length + 1) * sizeof(*str); if (offset + byteCount > size) { diff --git a/src/coreclr/pal/src/include/pal/corunix.hpp b/src/coreclr/pal/src/include/pal/corunix.hpp index 1fc99579a16a82..104a3a1d49339d 100644 --- a/src/coreclr/pal/src/include/pal/corunix.hpp +++ b/src/coreclr/pal/src/include/pal/corunix.hpp @@ -84,7 +84,7 @@ namespace CorUnix const WCHAR *pwsz ) { - SetStringWithLength(pwsz, PAL_wcslen(pwsz)); + SetStringWithLength(pwsz, minipal_u16_strlen((const CHAR16_T*)pwsz)); }; void diff --git a/src/coreclr/pal/src/include/pal/cruntime.h b/src/coreclr/pal/src/include/pal/cruntime.h deleted file mode 100644 index b09559565fd153..00000000000000 --- a/src/coreclr/pal/src/include/pal/cruntime.h +++ /dev/null @@ -1,32 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*++ - - - -Module Name: - - include/pal/cruntime.h - -Abstract: - - Header file for C runtime utility functions. - - - ---*/ - -#ifndef _PAL_CRUNTIME_H_ -#define _PAL_CRUNTIME_H_ - -#include -#include -#include - -#ifdef __cplusplus -typedef char16_t wchar_16; // __wchar_16 (which is defined in palinternal.h) is defined as wchar_16_cpp. - -#endif // __cplusplus - -#endif /* _PAL_CRUNTIME_H_ */ diff --git a/src/coreclr/pal/src/include/pal/palinternal.h b/src/coreclr/pal/src/include/pal/palinternal.h index 0f14fc3bee1788..aa04db994f7276 100644 --- a/src/coreclr/pal/src/include/pal/palinternal.h +++ b/src/coreclr/pal/src/include/pal/palinternal.h @@ -156,6 +156,7 @@ function_name() to call the system's implementation #endif #include +#include #include "pal.h" #include "palprivate.h" diff --git a/src/coreclr/pal/src/loader/module.cpp b/src/coreclr/pal/src/loader/module.cpp index d0159ffad21a48..6905af66b78191 100644 --- a/src/coreclr/pal/src/loader/module.cpp +++ b/src/coreclr/pal/src/loader/module.cpp @@ -188,7 +188,7 @@ LoadLibraryExW( goto done; } - lpstr = pathstr.OpenStringBuffer((PAL_wcslen(lpLibFileName)+1) * MaxWCharToAcpLengthFactor); + lpstr = pathstr.OpenStringBuffer((minipal_u16_strlen((const CHAR16_T*)lpLibFileName)+1) * MaxWCharToAcpLengthFactor); if (nullptr == lpstr) { goto done; @@ -406,7 +406,7 @@ GetModuleFileNameA( /* Convert module name to Ascii, place it in the supplied buffer */ - converted = minipal_convert_utf16_to_utf8((const CHAR16_T*)wide_name, PAL_wcslen(wide_name) + 1, lpFileName, nSize, 0); + converted = minipal_convert_utf16_to_utf8((const CHAR16_T*)wide_name, minipal_u16_strlen((const CHAR16_T*)wide_name) + 1, lpFileName, nSize, 0); if (converted == 0) { TRACE("Buffer too small to copy module's file name.\n"); @@ -473,7 +473,7 @@ GetModuleFileNameW( /* Copy module name into supplied buffer */ - name_length = PAL_wcslen(wide_name); + name_length = minipal_u16_strlen((const CHAR16_T*)wide_name); if (name_length >= (INT)nSize) { TRACE("Buffer too small (%u) to copy module's file name (%u).\n", nSize, name_length); @@ -559,7 +559,7 @@ PAL_LoadLibraryDirect( goto done; } - lpstr = pathstr.OpenStringBuffer((PAL_wcslen(lpLibFileName)+1) * MaxWCharToAcpLengthFactor); + lpstr = pathstr.OpenStringBuffer((minipal_u16_strlen((const CHAR16_T*)lpLibFileName)+1) * MaxWCharToAcpLengthFactor); if (nullptr == lpstr) { goto done; @@ -1294,8 +1294,8 @@ static bool LOADConvertLibraryPathWideStringToMultibyteString( _ASSERTE(multibyteLibraryPathLengthRef != nullptr); _ASSERTE(wideLibraryPath != nullptr); - size_t length = (PAL_wcslen(wideLibraryPath)+1) * MaxWCharToAcpLengthFactor; - size_t converted = minipal_convert_utf16_to_utf8((const CHAR16_T*)wideLibraryPath, PAL_wcslen(wideLibraryPath) + 1, multibyteLibraryPath, length, 0); + size_t length = (minipal_u16_strlen((const CHAR16_T*)wideLibraryPath)+1) * MaxWCharToAcpLengthFactor; + size_t converted = minipal_convert_utf16_to_utf8((const CHAR16_T*)wideLibraryPath, minipal_u16_strlen((const CHAR16_T*)wideLibraryPath) + 1, multibyteLibraryPath, length, 0); *multibyteLibraryPathLengthRef = (INT)converted; if (*multibyteLibraryPathLengthRef == 0) diff --git a/src/coreclr/pal/src/misc/dbgmsg.cpp b/src/coreclr/pal/src/misc/dbgmsg.cpp index 015cb277b42974..f1d5f21a51e5ae 100644 --- a/src/coreclr/pal/src/misc/dbgmsg.cpp +++ b/src/coreclr/pal/src/misc/dbgmsg.cpp @@ -16,7 +16,6 @@ Module Name: #include "config.h" #include "pal/dbgmsg.h" -#include "pal/cruntime.h" #include "pal/environ.h" /* standard headers */ diff --git a/src/coreclr/pal/src/misc/environ.cpp b/src/coreclr/pal/src/misc/environ.cpp index a42ccb1c8c0396..fe659d840abcae 100644 --- a/src/coreclr/pal/src/misc/environ.cpp +++ b/src/coreclr/pal/src/misc/environ.cpp @@ -163,7 +163,7 @@ GetEnvironmentVariableW( lpName ? lpName : W16_NULLSTRING, lpName ? lpName : W16_NULLSTRING, lpBuffer, nSize); - inBuffSize = lpName != nullptr ? minipal_get_length_utf16_to_utf8((const CHAR16_T*)lpName, PAL_wcslen(lpName) + 1, 0) : 0; + inBuffSize = lpName != nullptr ? minipal_get_length_utf16_to_utf8((const CHAR16_T*)lpName, minipal_u16_strlen((const CHAR16_T*)lpName) + 1, 0) : 0; if (0 == inBuffSize) { ERROR("lpName has to be a valid parameter\n"); @@ -190,7 +190,7 @@ GetEnvironmentVariableW( } } - if (0 == minipal_convert_utf16_to_utf8((const CHAR16_T*)lpName, PAL_wcslen(lpName) + 1, inBuff, inBuffSize, 0)) + if (0 == minipal_convert_utf16_to_utf8((const CHAR16_T*)lpName, minipal_u16_strlen((const CHAR16_T*)lpName) + 1, inBuff, inBuffSize, 0)) { ASSERT("UTF-16 to UTF-8 conversion failed!\n"); SetLastError(ERROR_INTERNAL_ERROR); @@ -290,7 +290,7 @@ SetEnvironmentVariableW( lpName?lpName:W16_NULLSTRING, lpName?lpName:W16_NULLSTRING, lpValue?lpValue:W16_NULLSTRING, lpValue?lpValue:W16_NULLSTRING); - if ((nameSize = lpName != nullptr ? minipal_get_length_utf16_to_utf8((const CHAR16_T*)lpName, PAL_wcslen(lpName) + 1, 0) : 0) == 0) + if ((nameSize = lpName != nullptr ? minipal_get_length_utf16_to_utf8((const CHAR16_T*)lpName, minipal_u16_strlen((const CHAR16_T*)lpName) + 1, 0) : 0) == 0) { ERROR("UTF-16 to UTF-8 conversion failed\n"); SetLastError(ERROR_INVALID_PARAMETER); @@ -305,7 +305,7 @@ SetEnvironmentVariableW( goto done; } - if (0 == minipal_convert_utf16_to_utf8((const CHAR16_T*)lpName, PAL_wcslen(lpName) + 1, name, nameSize, 0)) + if (0 == minipal_convert_utf16_to_utf8((const CHAR16_T*)lpName, minipal_u16_strlen((const CHAR16_T*)lpName) + 1, name, nameSize, 0)) { ASSERT("UTF-16 to UTF-8 conversion returned 0\n"); SetLastError(ERROR_INTERNAL_ERROR); @@ -314,7 +314,7 @@ SetEnvironmentVariableW( if (lpValue != nullptr) { - if ((valueSize = minipal_get_length_utf16_to_utf8((const CHAR16_T*)lpValue, PAL_wcslen(lpValue) + 1, 0)) == 0) + if ((valueSize = minipal_get_length_utf16_to_utf8((const CHAR16_T*)lpValue, minipal_u16_strlen((const CHAR16_T*)lpValue) + 1, 0)) == 0) { ERROR("UTF-16 to UTF-8 conversion failed\n"); SetLastError(ERROR_INVALID_PARAMETER); @@ -330,7 +330,7 @@ SetEnvironmentVariableW( goto done; } - if (0 == minipal_convert_utf16_to_utf8((const CHAR16_T*)lpValue, PAL_wcslen(lpValue) + 1, value, valueSize, 0)) + if (0 == minipal_convert_utf16_to_utf8((const CHAR16_T*)lpValue, minipal_u16_strlen((const CHAR16_T*)lpValue) + 1, value, valueSize, 0)) { ASSERT("UTF-16 to UTF-8 conversion failed\n"); SetLastError( ERROR_INTERNAL_ERROR ); diff --git a/src/coreclr/pal/src/misc/fmtmessage.cpp b/src/coreclr/pal/src/misc/fmtmessage.cpp index c578639080aa7e..5b92e5b5c91c1e 100644 --- a/src/coreclr/pal/src/misc/fmtmessage.cpp +++ b/src/coreclr/pal/src/misc/fmtmessage.cpp @@ -53,7 +53,7 @@ static LPWSTR FMTMSG_GetMessageString( DWORD dwErrCode ) if (lpErrorString != NULL) { - allocChars = PAL_wcslen(lpErrorString) + 1; + allocChars = minipal_u16_strlen((const CHAR16_T*)lpErrorString) + 1; } else { @@ -66,7 +66,7 @@ static LPWSTR FMTMSG_GetMessageString( DWORD dwErrCode ) { if (lpErrorString != NULL) { - PAL_wcscpy(lpRetVal, lpErrorString); + memcpy(lpRetVal, lpErrorString, allocChars * sizeof(WCHAR)); } else { @@ -105,7 +105,7 @@ static INT FMTMSG__watoi( LPWSTR str ) { CONST UINT MAX_NUMBER_LENGTH = 3; CHAR buf[ MAX_NUMBER_LENGTH ]; - size_t converted = minipal_convert_utf16_to_utf8((const CHAR16_T*)str, PAL_wcslen(str) + 1, buf, MAX_NUMBER_LENGTH, 0); + size_t converted = minipal_convert_utf16_to_utf8((const CHAR16_T*)str, minipal_u16_strlen((const CHAR16_T*)str) + 1, buf, MAX_NUMBER_LENGTH, 0); if ( converted != 0 ) { @@ -149,7 +149,7 @@ static INT FMTMSG__watoi( LPWSTR str ) } \ \ *lpWorkingString = '\0';\ - PAL_wcscpy( lpTemp, lpReturnString );\ + memcpy( lpTemp, lpReturnString, ( nCount + 1 ) * sizeof( WCHAR ) );\ free( lpReturnString ); \ lpWorkingString = lpReturnString = lpTemp; \ lpWorkingString += nCount; \ @@ -293,7 +293,7 @@ FormatMessageW( goto exit; } - nCount = PAL_wcslen( lpWorkingString ); + nCount = minipal_u16_strlen((const CHAR16_T*)lpWorkingString ); if ( !bIsLocalAlloced && nCount > nSize ) { @@ -452,11 +452,9 @@ FormatMessageW( if ( bIgnoreInserts && *lpSourceString == '!' && *( lpSourceString + 1 ) == 's' ) { - LPWSTR lpLastBang = PAL_wcschr( lpSourceString + 1, '!' ); - - if ( lpLastBang && ( 2 == lpLastBang - lpSourceString ) ) + if ( *( lpSourceString + 2 ) == '!' ) { - lpSourceString = lpLastBang + 1; + lpSourceString += 3; } else { @@ -499,7 +497,7 @@ FormatMessageW( else /* Only delete lpReturnString if the caller has their own buffer.*/ { TRACE( "Copying the string into the buffer.\n" ); - PAL_wcsncpy( lpBuffer, lpReturnString, nCount + 1 ); + memcpy( lpBuffer, lpReturnString, ( nCount + 1 ) * sizeof( WCHAR ) ); free( lpReturnString ); } } diff --git a/src/coreclr/pal/src/misc/utils.cpp b/src/coreclr/pal/src/misc/utils.cpp index 5bd995307518e8..22cdbbf961b2c9 100644 --- a/src/coreclr/pal/src/misc/utils.cpp +++ b/src/coreclr/pal/src/misc/utils.cpp @@ -53,7 +53,7 @@ Return Value : --*/ LPSTR UTIL_WCToMB_Alloc(LPCWSTR lpWideCharStr, int cchWideChar) { - size_t cchSource = cchWideChar < 0 ? PAL_wcslen(lpWideCharStr) + 1 : (size_t)cchWideChar; + size_t cchSource = cchWideChar < 0 ? minipal_u16_strlen((const CHAR16_T*)lpWideCharStr) + 1 : (size_t)cchWideChar; size_t length; LPSTR lpMultiByteStr; diff --git a/src/coreclr/pal/src/objmgr/listedobjectmanager.cpp b/src/coreclr/pal/src/objmgr/listedobjectmanager.cpp index 5b7dc46efffd4a..ecc99da32faa52 100644 --- a/src/coreclr/pal/src/objmgr/listedobjectmanager.cpp +++ b/src/coreclr/pal/src/objmgr/listedobjectmanager.cpp @@ -374,7 +374,7 @@ CListedObjectManager::LocateObject( _ASSERTE(NULL != pthr); _ASSERTE(NULL != psObjectToLocate); _ASSERTE(NULL != psObjectToLocate->GetString()); - _ASSERTE(PAL_wcslen(psObjectToLocate->GetString()) == psObjectToLocate->GetStringLength()); + _ASSERTE(minipal_u16_strlen((const CHAR16_T*)psObjectToLocate->GetString()) == psObjectToLocate->GetStringLength()); _ASSERTE(NULL != ppobj); ENTRY("CListedObjectManager::LocateObject " @@ -411,7 +411,8 @@ CListedObjectManager::LocateObject( continue; } - if (0 != PAL_wcscmp(poa->sObjectName.GetString(), psObjectToLocate->GetString())) + if (0 != memcmp(poa->sObjectName.GetString(), psObjectToLocate->GetString(), + psObjectToLocate->GetStringLength() * sizeof(WCHAR))) { continue; } diff --git a/src/coreclr/pal/src/thread/thread.cpp b/src/coreclr/pal/src/thread/thread.cpp index f5d80cbf0063c4..780157f1829903 100644 --- a/src/coreclr/pal/src/thread/thread.cpp +++ b/src/coreclr/pal/src/thread/thread.cpp @@ -1313,11 +1313,11 @@ SetThreadDescription( // it causes the value returned by Process.ProcessName to change. if ((pid_t)pTargetThread->GetThreadId() != getpid()) { - nameSize = lpThreadDescription != NULL ? minipal_get_length_utf16_to_utf8((const CHAR16_T*)lpThreadDescription, PAL_wcslen(lpThreadDescription) + 1, 0) : 0; + nameSize = lpThreadDescription != NULL ? minipal_get_length_utf16_to_utf8((const CHAR16_T*)lpThreadDescription, minipal_u16_strlen((const CHAR16_T*)lpThreadDescription) + 1, 0) : 0; if (nameSize > 0) { nameBuf = (char *)malloc(nameSize); - if (nameBuf == NULL || minipal_convert_utf16_to_utf8((const CHAR16_T*)lpThreadDescription, PAL_wcslen(lpThreadDescription) + 1, nameBuf, nameSize, 0) != nameSize) + if (nameBuf == NULL || minipal_convert_utf16_to_utf8((const CHAR16_T*)lpThreadDescription, minipal_u16_strlen((const CHAR16_T*)lpThreadDescription) + 1, nameBuf, nameSize, 0) != nameSize) { pThread->SetLastError(ERROR_INSUFFICIENT_BUFFER); } diff --git a/src/coreclr/pal/tests/palsuite/CMakeLists.txt b/src/coreclr/pal/tests/palsuite/CMakeLists.txt index f4c57af54c0ca7..a536f48bfe415b 100644 --- a/src/coreclr/pal/tests/palsuite/CMakeLists.txt +++ b/src/coreclr/pal/tests/palsuite/CMakeLists.txt @@ -55,23 +55,6 @@ add_executable_clr(paltests c_runtime/sscanf_s/test7/test7.cpp c_runtime/sscanf_s/test8/test8.cpp c_runtime/sscanf_s/test9/test9.cpp - c_runtime/wcscat/test1/test1.cpp - c_runtime/wcschr/test1/test1.cpp - c_runtime/wcscmp/test1/test1.cpp - c_runtime/wcscpy/test1/test1.cpp - c_runtime/wcslen/test1/test1.cpp - c_runtime/wcsncmp/test1/test1.cpp - c_runtime/wcsncpy/test1/test1.cpp - c_runtime/wcsrchr/test1/test1.cpp - c_runtime/wcsstr/test1/test1.cpp - c_runtime/wcstod/test1/test1.cpp - c_runtime/wcstod/test2/test2.cpp - c_runtime/wcstoul/test1/test1.cpp - c_runtime/wcstoul/test2/test2.cpp - c_runtime/wcstoul/test3/test3.cpp - c_runtime/wcstoul/test4/test4.cpp - c_runtime/wcstoul/test5/test5.cpp - c_runtime/wcstoul/test6/test6.cpp c_runtime/_vsnprintf_s/test1/test1.cpp c_runtime/_vsnprintf_s/test10/test10.cpp c_runtime/_vsnprintf_s/test11/test11.cpp @@ -88,10 +71,7 @@ add_executable_clr(paltests c_runtime/_vsnprintf_s/test6/test6.cpp c_runtime/_vsnprintf_s/test8/test8.cpp c_runtime/_vsnprintf_s/test9/test9.cpp - c_runtime/_wcsicmp/test1/test1.cpp c_runtime/_wcslwr_s/test1/test1.cpp - c_runtime/_wcsnicmp/test1/test1.cpp - c_runtime/_wtoi/test1/test1.cpp #debug_api/DebugBreak/test1/test1.cpp debug_api/OutputDebugStringW/test1/test1.cpp #exception_handling/pal_except/test1/test1.cpp diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.cpp deleted file mode 100644 index 54f38f32d482f9..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Tests that _wcsicmp correctly compares two strings with -** case insensitivity. -** -** -**==========================================================================*/ - -#include - -/* - * Note: The _wcsicmp is dependent on the LC_CTYPE category of the locale, - * and this is ignored by these tests. - */ -PALTEST(c_runtime__wcsicmp_test1_paltest_wcsicmp_test1, "c_runtime/_wcsicmp/test1/paltest_wcsicmp_test1") -{ - WCHAR str1[] = {'f','o','o',0}; - WCHAR str2[] = {'f','O','o',0}; - WCHAR str3[] = {'f','o','o','_','b','a','r',0}; - WCHAR str4[] = {'f','o','o','b','a','r',0}; - - /* - * Initialize the PAL and return FAIL if this fails - */ - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if (_wcsicmp(str1, str2) != 0) - { - Fail ("ERROR: _wcsicmp returning incorrect value:\n" - "_wcsicmp(\"%S\", \"%S\") != 0\n", str1, str2); - } - - if (_wcsicmp(str2, str3) >= 0) - { - Fail ("ERROR: _wcsicmp returning incorrect value:\n" - "_wcsicmp(\"%S\", \"%S\") >= 0\n", str2, str3); - } - - if (_wcsicmp(str3, str4) >= 0) - { - Fail ("ERROR: _wcsicmp returning incorrect value:\n" - "_wcsicmp(\"%S\", \"%S\") >= 0\n", str3, str4); - } - - if (_wcsicmp(str4, str1) <= 0) - { - Fail ("ERROR: _wcsicmp returning incorrect value:\n" - "_wcsicmp(\"%S\", \"%S\") <= 0\n", str4, str1); - } - - if (_wcsicmp(str3, str2) <= 0) - { - Fail ("ERROR: _wcsicmp returning incorrect value:\n" - "_wcsicmp(\"%S\", \"%S\") <= 0\n", str2, str3); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/_wcslwr_s/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/_wcslwr_s/test1/test1.cpp index 4303e6851f83b0..6ce4992dbe9a94 100644 --- a/src/coreclr/pal/tests/palsuite/c_runtime/_wcslwr_s/test1/test1.cpp +++ b/src/coreclr/pal/tests/palsuite/c_runtime/_wcslwr_s/test1/test1.cpp @@ -13,8 +13,9 @@ **==========================================================================*/ #include +#include -/* uses memcmp,wcslen */ +/* uses memcmp,u16_strlen */ PALTEST(c_runtime__wcslwr_s_test1_paltest_wcslwr_s_test1, "c_runtime/_wcslwr_s/test1/paltest_wcslwr_s_test1") { @@ -33,7 +34,7 @@ PALTEST(c_runtime__wcslwr_s_test1_paltest_wcslwr_s_test1, "c_runtime/_wcslwr_s/t expect_str = convert("asdf 1#"); errno_t ret = _wcslwr_s(test_str, 8); - if (ret != 0 || memcmp(test_str, expect_str, wcslen(expect_str)*2 + 2) != 0) + if (ret != 0 || memcmp(test_str, expect_str, u16_strlen(expect_str)*2 + 2) != 0) { Fail ("ERROR: Expected to get \"%s\", got \"%s\".\n", convertC(expect_str), convertC(test_str)); diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.cpp deleted file mode 100644 index 4baa9476763f21..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Take two wide strings and compare them, giving different lengths. -** Comparing str1 and str2 with str2 length, should return <0 -** Comparing str2 and str1 with str2 length, should return >0 -** Comparing str1 and str2 with str1 length, should return 0 -** Bring in str3, which has a capital, but this function is doing a lower -** case compare. Just ensure that two strings which differ only by capitals -** return 0. -** -** -**==========================================================================*/ - -#include - -/* - * Notes: uses wcslen - */ - -PALTEST(c_runtime__wcsnicmp_test1_paltest_wcsnicmp_test1, "c_runtime/_wcsnicmp/test1/paltest_wcsnicmp_test1") -{ - WCHAR str1[] = {'f','o','o',0}; - WCHAR str2[] = {'f','o','o','x',0}; - WCHAR str3[] = {'f','O','o',0}; - WCHAR str4[] = {'A','B','C','D','E',0}; - WCHAR str5[] = {'A','B','C','D',']',0}; - WCHAR str6[] = {'a','b','c','d','e',0}; - WCHAR str7[] = {'a','b','c','d',']',0}; - char cstr1[] = "foo"; - char cstr2[] = "foox"; - char cstr3[] = "fOo"; - char cstr4[] = "ABCDE"; - char cstr5[] = "ABCD]"; - char cstr6[] = "abcde"; - char cstr7[] = "abcd]"; - - - /* - * Initialize the PAL and return FAIL if this fails - */ - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if (_wcsnicmp(str1, str2, wcslen(str2)) >= 0) - { - Fail ("ERROR: wcsnicmp(\"%s\", \"%s\", %d) returned >= 0\n", cstr1, - cstr2, wcslen(str2)); - } - - if (_wcsnicmp(str2, str1, wcslen(str2)) <= 0) - { - Fail ("ERROR: wcsnicmp(\"%s\", \"%s\", %d) returned <= 0\n", cstr2, - cstr1, wcslen(str2)); - } - - if (_wcsnicmp(str1, str2, wcslen(str1)) != 0) - { - Fail ("ERROR: wcsnicmp(\"%s\", \"%s\", %d) returned != 0\n", cstr1, - cstr2, wcslen(str1)); - } - - if (_wcsnicmp(str1, str3, wcslen(str1)) != 0) - { - Fail ("ERROR: wcsnicmp(\"%s\", \"%s\", %d) returned != 0\n", cstr1, - cstr3, wcslen(str1)); - } - - /* new testing */ - - /* str4 should be greater than str5 */ - if (_wcsnicmp(str4, str5, wcslen(str4)) <= 0) - { - Fail ("ERROR: _wcsnicmp(\"%s\", \"%s\", %d) returned >= 0\n", - cstr4, cstr5, wcslen(str4)); - } - - /* str6 should be greater than str7 */ - if (_wcsnicmp(str6, str7, wcslen(str6)) <= 0) - { - Fail ("ERROR: _wcsnicmp(\"%s\", \"%s\", %d) returned <= 0\n", - cstr6, cstr7, wcslen(str6)); - } - - PAL_Terminate(); - return PASS; -} - diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.cpp deleted file mode 100644 index 3d0ff1f5ed2656..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: test1.c -** -** Purpose: Tests the PAL implementation of the _wtoi function. -** Check to ensure that the different ints are handled properly. -** Exponents and decimals should be treated as invalid characters, -** causing the conversion to quit. Whitespace before the int is valid. -** Check would-be octal/hex digits to ensure they're treated no -** differently than other strings. -** -** -**===================================================================*/ - -#include - - -struct testCase -{ - int IntValue; - char avalue[20]; -}; - -PALTEST(c_runtime__wtoi_test1_paltest_wtoi_test1, "c_runtime/_wtoi/test1/paltest_wtoi_test1") -{ - - int result=0; - int i=0; - WCHAR* temp; - - struct testCase testCases[] = - { - {1234, "1234"}, - {-1234, "-1234"}, - {1234, "+1234"}, - {1234, "1234.44"}, - {1234, "1234e-5"}, - {1234, "1234e+5"}, - {1234, "1234E5"}, - {1234, "\t1234"}, - {0, "0x21"}, - {17, "017"}, - {1234, "1234.657e-8"}, - {1234567, " 1234567e-8 foo"}, - {0, "foo 32 bar"} - }; - - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Loop through each case. Convert the wide string to an int - and then compare to ensure that it is the correct value. - */ - - for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) - { - /* Convert to a wide string, then call _wtoi to convert to an int */ - temp = convert(testCases[i].avalue); - result = _wtoi(temp); - free(temp); - if (testCases[i].IntValue != result) - { - Fail("ERROR: _wtoi misinterpreted \"%s\" as %i instead of %i.\n", - testCases[i].avalue, - result, - testCases[i].IntValue); - } - - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/sscanf_s/sscanf_s.h b/src/coreclr/pal/tests/palsuite/c_runtime/sscanf_s/sscanf_s.h index f4422866781c70..0904069b1a899b 100644 --- a/src/coreclr/pal/tests/palsuite/c_runtime/sscanf_s/sscanf_s.h +++ b/src/coreclr/pal/tests/palsuite/c_runtime/sscanf_s/sscanf_s.h @@ -13,6 +13,8 @@ #ifndef __SSCANF_S_H__ #define __SSCANF_S_H__ +#include + inline void DoVoidTest_scanf_s(char *inputstr, const char *formatstr) { char buf[256] = { 0 }; @@ -72,7 +74,7 @@ inline void DoWStrTest_scanf_s(char *inputstr, const char *formatstr, const WCHA "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); } - if (memcmp(checkstr, buf, wcslen(checkstr)*2 + 2) != 0) + if (memcmp(checkstr, buf, u16_strlen(checkstr)*2 + 2) != 0) { Fail("ERROR: scanned wide string incorrectly from \"%s\" using \"%s\".\n" "Expected \"%s\", got \"%s\".\n", inputstr, formatstr, diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcscat/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcscat/test1/test1.cpp deleted file mode 100644 index 656ebd91ee2d6c..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcscat/test1/test1.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: -** Test to that wcscat correctly concatenates wide strings, including placing -** null pointers. -** -**==========================================================================*/ - -#include - -/* - * Notes: uses memcmp and the (pal) sprintf_s - */ - -PALTEST(c_runtime_wcscat_test1_paltest_wcscat_test1, "c_runtime/wcscat/test1/paltest_wcscat_test1") -{ - WCHAR dest[80]; - WCHAR test[] = {'f','o','o',' ','b','a','r',' ','b','a','z',0}; - WCHAR str1[] = {'f','o','o',' ',0}; - WCHAR str2[] = {'b','a','r',' ',0}; - WCHAR str3[] = {'b','a','z',0}; - WCHAR *ptr; - char buffer[256]; - - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - dest[0] = 0; - - ptr = wcscat(dest, str1); - if (ptr != dest) - { - Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr); - } - - ptr = wcscat(dest, str2); - if (ptr != dest) - { - Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr); - } - - ptr = wcscat(dest, str3); - if (ptr != dest) - { - Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr); - } - - if (memcmp(dest, test, sizeof(test)) != 0) - { - sprintf_s(buffer, ARRAY_SIZE(buffer), "%S", dest); - Fail("ERROR: Expected wcscat to give \"%s\", got \"%s\"\n", - "foo bar baz", buffer); - } - - PAL_Terminate(); - return PASS; -} - diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcschr/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcschr/test1/test1.cpp deleted file mode 100644 index 02276da03a51f4..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcschr/test1/test1.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: -** Tests that wcschr correctly finds the first occurrence of a character in a -** string -** -** -**==========================================================================*/ - - - -#include - -PALTEST(c_runtime_wcschr_test1_paltest_wcschr_test1, "c_runtime/wcschr/test1/paltest_wcschr_test1") -{ - WCHAR str[] = {'f','o','o',' ','b','a','r',' ',0}; - WCHAR c = (WCHAR)' '; - WCHAR c2 = (WCHAR)'$'; - WCHAR *ptr; - - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - ptr = wcschr(str, c); - if (ptr != str + 3) - { - Fail("ERROR: expected wcschr to return pointer to %p, got %p\n", - str + 3, ptr); - } - - ptr = wcschr(str, c2); - if (ptr != NULL) - { - Fail("ERROR: expected wcschr to return pointer to %p, got %p\n", - NULL, ptr); - } - - PAL_Terminate(); - return PASS; -} - diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.cpp deleted file mode 100644 index f7d2c12aa56635..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Tests that wcscmp correctly compares two strings with -** case sensitivity. -** -** -**==========================================================================*/ - -#include - - -PALTEST(c_runtime_wcscmp_test1_paltest_wcscmp_test1, "c_runtime/wcscmp/test1/paltest_wcscmp_test1") -{ - WCHAR str1[] = {'f','o','o',0}; - WCHAR str2[] = {'f','o','o','x',0}; - WCHAR str3[] = {'f','O','o',0}; - char cstr1[] = "foo"; - char cstr2[] = "foox"; - char cstr3[] = "fOo"; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - - if (wcscmp(str1, str2) >= 0) - { - Fail("ERROR: wcscmp(\"%s\", \"%s\") returned >= 0\n", cstr1, cstr2); - } - - if (wcscmp(str2, str1) <= 0) - { - Fail("ERROR: wcscmp(\"%s\", \"%s\") returned <= 0\n", cstr2, cstr1); - } - - if (wcscmp(str1, str3) <= 0) - { - Fail("ERROR: wcscmp(\"%s\", \"%s\") returned >= 0\n", cstr1, cstr3); - } - - if (wcscmp(str3, str1) >= 0) - { - Fail("ERROR: wcscmp(\"%s\", \"%s\") returned >= 0\n", cstr3, cstr1); - } - - PAL_Terminate(); - - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.cpp deleted file mode 100644 index ba8336fa423013..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Tests that wcscpy correctly copies a null-terminated wide string. -** -** -**==========================================================================*/ - - -#include - -/* - * Notes: uses memcmp and sprintf_s. - */ - -PALTEST(c_runtime_wcscpy_test1_paltest_wcscpy_test1, "c_runtime/wcscpy/test1/paltest_wcscpy_test1") -{ - WCHAR str[] = {'f','o','o',0,'b','a','r',0}; - WCHAR dest[80]; - WCHAR result[] = {'f','o','o',0}; - WCHAR *ret; - char buffer[256]; - - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - ret = wcscpy(dest, str); - - if (ret != dest || memcmp(dest, result, sizeof(result)) != 0) - { - sprintf_s(buffer, ARRAY_SIZE(buffer), "%S", dest); - Fail("Expected wcscpy to give \"%s\" with a return value of %p, got \"%s\" " - "with a return value of %p.\n", "foo", dest, buffer, ret); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcslen/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcslen/test1/test1.cpp deleted file mode 100644 index df7613dcae2dcd..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcslen/test1/test1.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: -** Tests that wcslen correctly returns the length (in wide characters, -** not byte) of a wide string -** -** -**==========================================================================*/ - - - -#include - -PALTEST(c_runtime_wcslen_test1_paltest_wcslen_test1, "c_runtime/wcslen/test1/paltest_wcslen_test1") -{ - WCHAR str1[] = {'f','o','o',' ',0}; - WCHAR str2[] = {0}; - int ret; - - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - ret = wcslen(str1); - if (ret != 4) - { - Fail("ERROR: Expected wcslen of \"foo \" to be 4, got %d\n", ret); - } - - ret = wcslen(str2); - if (ret != 0) - { - Fail("ERROR: Expected wcslen of \"\" to be 0, got %d\n", ret); - } - - - PAL_Terminate(); - return PASS; -} - diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.cpp deleted file mode 100644 index ff6a69e57f4f0b..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: -** Tests that wcsncmp case-sensitively compares wide strings, making sure that -** the count argument is handled correctly. -** -** -**==========================================================================*/ - - - -#include - -/* - * Notes: uses wcslen. - */ - -PALTEST(c_runtime_wcsncmp_test1_paltest_wcsncmp_test1, "c_runtime/wcsncmp/test1/paltest_wcsncmp_test1") -{ - WCHAR str1[] = {'f','o','o',0}; - WCHAR str2[] = {'f','o','o','x',0}; - WCHAR str3[] = {'f','O','o',0}; - char cstr1[] = "foo"; - char cstr2[] = "foox"; - char cstr3[] = "fOo"; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - - if (wcsncmp(str1, str2, wcslen(str2)) >= 0) - { - Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned >= 0\n", cstr1, - cstr2, wcslen(str2)); - } - - if (wcsncmp(str2, str1, wcslen(str2)) <= 0) - { - Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned <= 0\n", cstr2, - cstr1, wcslen(str2)); - } - - if (wcsncmp(str1, str2, wcslen(str1)) != 0) - { - Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned != 0\n", cstr1, - cstr2, wcslen(str1)); - } - - if (wcsncmp(str1, str3, wcslen(str1)) <= 0) - { - Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned >= 0\n", cstr1, - cstr3, wcslen(str1)); - } - - if (wcsncmp(str3, str1, wcslen(str1)) >= 0) - { - Fail("ERROR: wcsncmp(\"%s\", \"%s\", %d) returned >= 0\n", cstr3, - cstr1, wcslen(str1)); - } - - PAL_Terminate(); - return PASS; -} - diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.cpp deleted file mode 100644 index 1d514672bc3737..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: -** Tests to see that wcsncpy correctly copies wide strings, including handling -** the count argument correctly (copying no more that count characters, not -** automatically adding a null, and padding if necessary). -** -** -**==========================================================================*/ - -#include - - -PALTEST(c_runtime_wcsncpy_test1_paltest_wcsncpy_test1, "c_runtime/wcsncpy/test1/paltest_wcsncpy_test1") -{ - WCHAR dest[80]; - WCHAR result[] = {'f','o','o','b','a','r',0}; - WCHAR str[] = {'f','o','o','b','a','r',0,'b','a','z',0}; - WCHAR *ret; - int i; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - for (i=0; i<80; i++) - { - dest[i] = 'x'; - } - - ret = wcsncpy(dest, str, 3); - if (ret != dest) - { - Fail("Expected wcsncpy to return %p, got %p!\n", dest, ret); - } - - if (wcsncmp(dest, result, 3) != 0) - { - Fail("Expected wcsncpy to give \"%S\", got \"%S\"!\n", result, dest); - } - - if (dest[3] != (WCHAR)'x') - { - Fail("wcsncpy overflowed!\n"); - } - - ret = wcsncpy(dest, str, 40); - if (ret != dest) - { - Fail("Expected wcsncpy to return %p, got %p!\n", dest, ret); - } - - if (wcscmp(dest, result) != 0) - { - Fail("Expected wcsncpy to give \"%S\", got \"%S\"!\n", result, dest); - } - - for (i=wcslen(str); i<40; i++) - { - if (dest[i] != 0) - { - Fail("wcsncpy failed to pad the destination with NULLs!\n"); - } - } - - if (dest[40] != (WCHAR)'x') - { - Fail("wcsncpy overflowed!\n"); - } - - - - PAL_Terminate(); - - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.cpp deleted file mode 100644 index 052a623b55ad8f..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: -** Tests to see that wcsrchr correctly returns a pointer to the last occurrence -** of a character in a string. -** -** -**==========================================================================*/ - -#include - -PALTEST(c_runtime_wcsrchr_test1_paltest_wcsrchr_test1, "c_runtime/wcsrchr/test1/paltest_wcsrchr_test1") -{ - WCHAR str[] = {'f','o','o',' ','b','a','r',' ','b','a','z',0}; - WCHAR c = (WCHAR)' '; - WCHAR c2 = (WCHAR)'$'; - WCHAR *ptr; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - ptr = wcsrchr(str, c); - if (ptr != str + 7) - { - Fail("ERROR: expected wcsrchr to return pointer to %p, got %p\n", - str + 7, ptr); - } - - ptr = wcsrchr(str, c2); - if (ptr != NULL) - { - Fail("ERROR: expected wcsrchr to return pointer to %p, got %p\n", - NULL, ptr); - } - - PAL_Terminate(); - return PASS; -} - diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.cpp deleted file mode 100644 index 73264f6d127967..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: -** Tests that wcsstr correctly find substrings in wide stings, including -** returning NULL when the substring can't be found. -** -** -**==========================================================================*/ - -#include - -PALTEST(c_runtime_wcsstr_test1_paltest_wcsstr_test1, "c_runtime/wcsstr/test1/paltest_wcsstr_test1") -{ - WCHAR *string; - WCHAR *key1; - WCHAR *key2; - WCHAR key3[] = { 0 }; - WCHAR *key4; - WCHAR *result; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - string = convert("foo bar baz bar"); - key1 = convert("bar"); - key2 = convert("Bar"); - key4 = convert("arggggh!"); - - result = wcsstr(string, key1); - if (result != string + 4) - { - Fail("ERROR: Got incorrect result in scanning \"%s\" for \"%s\".\n" - "Expected to get pointer to %#p, got %#p\n", convertC(string), - convertC(key1), string + 4, result); - } - - - result = wcsstr(string, key2); - if (result != NULL) - { - Fail("ERROR: Got incorrect result in scanning \"%s\" for \"%s\".\n" - "Expected to get pointer to %#p, got %#p\n", convertC(string), - convertC(key2), NULL, result); - } - - result = wcsstr(string, key3); - if (result != string) - { - Fail("ERROR: Got incorrect result in scanning \"%s\" for \"%s\".\n" - "Expected to get pointer to %#p, got %#p\n", convertC(string), - convertC(key3), string, result); - } - - result = wcsstr(string, key4); - if (result != nullptr) - { - Fail("ERROR: Got incorrect result in scanning \"%s\" for \"%s\".\n" - "Expected to get pointer to null, got %#p\n", convertC(string), - convertC(key4), result); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcstod/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcstod/test1/test1.cpp deleted file mode 100644 index b1c1b9557c31f1..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcstod/test1/test1.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: test1.c -** -** Purpose: Tests wcstod with a number of sample strings. -** -** -**===================================================================*/ - -#include - -struct testCase -{ - double CorrectResult; - char string[20]; - int stopChar; -}; - -PALTEST(c_runtime_wcstod_test1_paltest_wcstod_test1, "c_runtime/wcstod/test1/paltest_wcstod_test1") -{ - struct testCase testCases[] = - { - {1234,"1234", 4}, - {-1234,"-1234", 5}, - {1234.44,"1234.44", 7}, - {1234e-5,"1234e-5", 7}, - {1234e+5,"1234e+5", 7}, - {1234E5,"1234E5", 6}, - {1234.657e-8, "1234.657e-8", 11}, - {0, "1e-800", 6}, - {0, "-1e-800", 7}, - {1234567e-8, " 1234567e-8 foo", 13}, - {0, " foo 32 bar", 0}, - }; - - WCHAR *wideStr; - WCHAR *endptr; - double result; - int i; - - if (PAL_Initialize(argc,argv)) - { - return FAIL; - } - - for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) - { - wideStr = convert(testCases[i].string); - result = wcstod(wideStr, &endptr); - - if (testCases[i].CorrectResult != result) - { - free(wideStr); - Fail("ERROR: wcstod misinterpreted \"%s\" as %g instead of " - "%g.\n", - testCases[i].string, - result, - testCases[i].CorrectResult); - } - - if (endptr != wideStr + testCases[i].stopChar) - { - free(wideStr); - Fail("ERROR: wcstod stopped scanning \"%s\" at %p, " - "instead of %p!\n", testCases[i].string, endptr, - wideStr + testCases[i].stopChar); - } - - free(wideStr); - } - - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcstod/test2/test2.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcstod/test2/test2.cpp deleted file mode 100644 index 8da0a902174e5a..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcstod/test2/test2.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: test2.c -** -** Purpose: Tests wcstod with overflows -** -** -**===================================================================*/ - -#include - -PALTEST(c_runtime_wcstod_test2_paltest_wcstod_test2, "c_runtime/wcstod/test2/paltest_wcstod_test2") -{ - /* Representation of positive infinty for a IEEE 64-bit double */ - INT64 PosInifity = (INT64)(0x7ff00000) << 32; - double HugeVal = *(double*) &PosInifity; - char *PosStr = "1E+10000"; - char *NegStr = "-1E+10000"; - WCHAR *wideStr; - double result; - - - if (PAL_Initialize(argc,argv)) - { - return FAIL; - } - - wideStr = convert(PosStr); - result = wcstod(wideStr, NULL); - free(wideStr); - - if (result != HugeVal) - { - Fail("ERROR: wcstod interpreted \"%s\" as %g instead of %g\n", - PosStr, result, HugeVal); - } - - - - wideStr = convert(NegStr); - result = wcstod(wideStr, NULL); - free(wideStr); - - if (result != -HugeVal) - { - Fail("ERROR: wcstod interpreted \"%s\" as %g instead of %g\n", - NegStr, result, -HugeVal); - } - - - PAL_Terminate(); - - return PASS; -} - diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.cpp deleted file mode 100644 index e985ca2103af5d..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Test #1 for the wcstoul function -** -** -**==========================================================================*/ -#include - -/* - * Notes: wcstoul should depend on the current locale's LC_NUMERIC category, - * this is not currently tested. - */ - - -PALTEST(c_runtime_wcstoul_test1_paltest_wcstoul_test1, "c_runtime/wcstoul/test1/paltest_wcstoul_test1") -{ - WCHAR teststr[] = {'1','2','3','4','5',0}; - WCHAR *end; - ULONG result = 27; - ULONG l; - - if (0 != PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - l = wcstoul(teststr, &end, 4); - - if (l != result) - { - Fail("ERROR: Expected wcstoul to return %u, got %u\n", result, l); - } - - if (end != teststr + 3) - { - Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", - teststr + 3, end); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.cpp deleted file mode 100644 index c1b74ca01c77b3..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test2.c -** -** Purpose: Test #2 for the wcstoul function -** -** -**==========================================================================*/ -#include - -/* - * Notes: wcstoul should depend on the current locale's LC_NUMERIC category, - * this is not currently tested. - */ - - -PALTEST(c_runtime_wcstoul_test2_paltest_wcstoul_test2, "c_runtime/wcstoul/test2/paltest_wcstoul_test2") -{ - WCHAR teststr[] = {'1','2','3','4','5',0}; - WCHAR *end; - ULONG result = 12345; - ULONG l; - - if (0 != PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - l = wcstoul((char16_t*)teststr, &end, 10); - - if (l != result) - { - Fail("ERROR: Expected wcstoul to return %u, got %u\n", result, l); - } - - if (end != teststr + 5) - { - Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", - teststr + 5, end); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.cpp deleted file mode 100644 index 5c09075ce9f73f..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test3.c -** -** Purpose: Test #3 for the wcstoul function -** -** -**==========================================================================*/ -#include - -/* - * Notes: wcstoul should depend on the current locale's LC_NUMERIC category, - * this is not currently tested. - */ - - -PALTEST(c_runtime_wcstoul_test3_paltest_wcstoul_test3, "c_runtime/wcstoul/test3/paltest_wcstoul_test3") -{ - WCHAR str[] = {'Z',0}; - WCHAR *end; - ULONG l; - - if (0 != PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - l = wcstoul(str, &end, 10); - - if (l != 0) - { - Fail("ERROR: Expected wcstoul to return %u, got %u\n", 0, l); - } - - if (end != str) - { - Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", - str, end); - } - - PAL_Terminate(); - return PASS; -} - diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.cpp deleted file mode 100644 index 32055fb8bb5ba2..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test4.c -** -** Purpose: Test #4 for the wcstoul function -** -** -**==========================================================================*/ -#include - -/* - * Notes: wcstoul should depend on the current locale's LC_NUMERIC category, - * this is not currently tested. - */ - -PALTEST(c_runtime_wcstoul_test4_paltest_wcstoul_test4, "c_runtime/wcstoul/test4/paltest_wcstoul_test4") -{ - WCHAR maxstr[] = {'4','2','9','4','9','6','7','2','9','5',0}; - ULONG max = 4294967295ul; - WCHAR *end; - ULONG l; - - if (0 != PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - errno = 0; - - l = wcstoul(maxstr, &end, 10); - if (l != max) - { - Fail("ERROR: Expected wcstoul to return %u, got %u\n", max, l); - } - if (end != maxstr + 10) - { - Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", - maxstr + 10, end); - } - if (errno != 0) - { - Fail("ERROR: wcstoul set errno to non-zero (%d)\n", errno); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.cpp deleted file mode 100644 index 428a5f24caa66a..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test5.c -** -** Purpose: Test #5 for the wcstoul function -** -** -**==========================================================================*/ -#include - -/* - * Notes: wcstoul should depend on the current locale's LC_NUMERIC category, - * this is not currently tested. - */ - - -PALTEST(c_runtime_wcstoul_test5_paltest_wcstoul_test5, "c_runtime/wcstoul/test5/paltest_wcstoul_test5") -{ - WCHAR overstr[] = {'4','2','9','4','9','6','7','2','9','6',0}; - WCHAR understr[] = {'-','1',0}; - WCHAR *end; - ULONG l; - - if (0 != PAL_Initialize(argc, argv)) - { - return FAIL; - } - - errno = 0; - l = wcstoul(overstr, &end, 10); - - if (l != UINT32_MAX) - { - Fail("ERROR: Expected wcstoul to return %u, got %u\n", UINT32_MAX, l); - } - if (end != overstr + 10) - { - Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", - overstr + 10, end); - } - if (errno != ERANGE) - { - Fail("ERROR: wcstoul did not set errno to ERANGE (%d)\n", errno); - } - - errno = 0; - l = wcstoul(understr, &end, 10); - - if (l != UINT32_MAX) - { - Fail("ERROR: Expected wcstoul to return %u, got %u\n", UINT32_MAX, l); - } - if (end != understr + 2) - { - Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", - understr + 2, end); - } - if (errno != 0) - { - Fail("ERROR: wcstoul set errno to non-zero (%d)\n", errno); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.cpp deleted file mode 100644 index 8ffd4c0b314db9..00000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================================ -** -** Source: test6.c -** -** Purpose: Test #6 for the wcstoul function. Tests strings with octal/hex -** number specifers -** -** -**==========================================================================*/ -#include - - -/* - * Notes: wcstoul should depend on the current locale's LC_NUMERIC category, - * this is not currently tested. - */ - - -PALTEST(c_runtime_wcstoul_test6_paltest_wcstoul_test6, "c_runtime/wcstoul/test6/paltest_wcstoul_test6") -{ - WCHAR test1[] = {'0','x','1','2', 0}; - WCHAR test2[] = {'0','1','2',0}; - WCHAR *end; - ULONG l; - - if (0 != PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - l = wcstoul(test1, &end, 16); - if (l != 0x12) - { - Fail("ERROR: Expected wcstoul to return %u, got %u\n", 0x12, l); - } - if (end != test1 + 4) - { - Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", - test1 + 4, end); - } - - l = wcstoul(test1, &end, 10); - if (l != 0) - { - Fail("ERROR: Expected wcstoul to return %u, got %u\n", 0, l); - } - if (end != test1+1) - { - Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", - test1+1, end); - } - - l = wcstoul(test2, &end, 8); - if (l != 10) - { - Fail("ERROR: Expected wcstoul to return %u, got %u\n", 10, l); - } - if (end != test2 + 3) - { - Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", - test2 + 3, end); - } - - l = wcstoul(test2, &end, 10); - if (l != 12) - { - Fail("ERROR: Expected wcstoul to return %u, got %u\n", 12, l); - } - - if (end != test2 + 3) - { - Fail("ERROR: Expected wcstoul to give an end value of %p, got %p\n", - test2 + 3, end); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/common/palsuite.cpp b/src/coreclr/pal/tests/palsuite/common/palsuite.cpp index 88fe3fa77a2974..5553a6a3967fbb 100644 --- a/src/coreclr/pal/tests/palsuite/common/palsuite.cpp +++ b/src/coreclr/pal/tests/palsuite/common/palsuite.cpp @@ -12,6 +12,7 @@ #include "palsuite.h" +#include #include "minipal/time.h" #include "minipal/utf8.h" @@ -40,7 +41,7 @@ WCHAR* convert(const char * aString) char* convertC(const WCHAR * wString) { - size_t length = wcslen(wString) + 1; + size_t length = u16_strlen(wString) + 1; size_t size = minipal_get_length_utf16_to_utf8((const CHAR16_T*)wString, length, 0); char * MultiBuffer = (char*) malloc(size); if (MultiBuffer == NULL) @@ -118,45 +119,6 @@ BOOL Cleanup(HANDLE *hArray, DWORD dwIndex) return (bCRet&&bCHRet); } -/* - * Take two wide strings representing file and directory names - * (dirName, fileName), join the strings with the appropriate path - * delimiter and populate a wide character buffer (absPathName) with - * the resulting string. - * - * Returns: The number of wide characters in the resulting string. - * 0 is returned on Error. - */ -int -mkAbsoluteFilenameW ( - LPWSTR dirName, - DWORD dwDirLength, - LPCWSTR fileName, - DWORD dwFileLength, - LPWSTR absPathName ) -{ - const WCHAR szPathDelimW[] = {'/','\0'}; - - DWORD sizeDN, sizeFN, sizeAPN; - - sizeDN = wcslen( dirName ); - sizeFN = wcslen( fileName ); - sizeAPN = (sizeDN + 1 + sizeFN + 1); - - /* ensure ((dirName + DELIM + fileName + \0) =< MAX_PATH ) */ - if ( sizeAPN > MAX_PATH ) - { - return ( 0 ); - } - - wcsncpy(absPathName, dirName, dwDirLength +1); - wcsncpy(absPathName, szPathDelimW, 2); - wcsncpy(absPathName, fileName, dwFileLength +1); - - return (sizeAPN); - -} - /* * Take two wide strings representing file and directory names * (dirName, fileName), join the strings with the appropriate path diff --git a/src/coreclr/pal/tests/palsuite/common/palsuite.h b/src/coreclr/pal/tests/palsuite/common/palsuite.h index c53a8732f8e6c3..b1663b38d696e9 100644 --- a/src/coreclr/pal/tests/palsuite/common/palsuite.h +++ b/src/coreclr/pal/tests/palsuite/common/palsuite.h @@ -132,23 +132,6 @@ BOOL Cleanup(HANDLE *hArray, DWORD dwIndex); extern HANDLE hToken[NUM_TOKENS]; -/* - * Take two wide strings representing file and directory names - * (dirName, fileName), join the strings with the appropriate path - * delimiter and populate a wide character buffer (absPathName) with - * the resulting string. - * - * Returns: The number of wide characters in the resulting string. - * 0 is returned on Error. - */ -int -mkAbsoluteFilenameW ( - LPWSTR dirName, - DWORD dwDirLength, - LPCWSTR fileName, - DWORD dwFileLength, - LPWSTR absPathName ); - /* * Take two wide strings representing file and directory names * (dirName, fileName), join the strings with the appropriate path @@ -166,16 +149,4 @@ mkAbsoluteFilenameA ( DWORD dwFileLength, LPSTR absPathName ); -#define wcstod PAL_wcstod -#define wcstoul PAL_wcstoul -#define wcscat PAL_wcscat -#define wcscpy PAL_wcscpy -#define wcslen PAL_wcslen -#define wcsncmp PAL_wcsncmp -#define wcschr PAL_wcschr -#define wcsrchr PAL_wcsrchr -#define wcsstr PAL_wcsstr -#define wcscmp PAL_wcscmp -#define wcsncpy PAL_wcsncpy - #endif diff --git a/src/coreclr/pal/tests/palsuite/compilableTests.txt b/src/coreclr/pal/tests/palsuite/compilableTests.txt index b358bd693f36f3..b9231f4ed0bca6 100644 --- a/src/coreclr/pal/tests/palsuite/compilableTests.txt +++ b/src/coreclr/pal/tests/palsuite/compilableTests.txt @@ -15,23 +15,6 @@ c_runtime/sscanf_s/test6/paltest_sscanf_test6 c_runtime/sscanf_s/test7/paltest_sscanf_test7 c_runtime/sscanf_s/test8/paltest_sscanf_test8 c_runtime/sscanf_s/test9/paltest_sscanf_test9 -c_runtime/wcscat/test1/paltest_wcscat_test1 -c_runtime/wcschr/test1/paltest_wcschr_test1 -c_runtime/wcscmp/test1/paltest_wcscmp_test1 -c_runtime/wcscpy/test1/paltest_wcscpy_test1 -c_runtime/wcslen/test1/paltest_wcslen_test1 -c_runtime/wcsncmp/test1/paltest_wcsncmp_test1 -c_runtime/wcsncpy/test1/paltest_wcsncpy_test1 -c_runtime/wcsrchr/test1/paltest_wcsrchr_test1 -c_runtime/wcsstr/test1/paltest_wcsstr_test1 -c_runtime/wcstod/test1/paltest_wcstod_test1 -c_runtime/wcstod/test2/paltest_wcstod_test2 -c_runtime/wcstoul/test1/paltest_wcstoul_test1 -c_runtime/wcstoul/test2/paltest_wcstoul_test2 -c_runtime/wcstoul/test3/paltest_wcstoul_test3 -c_runtime/wcstoul/test4/paltest_wcstoul_test4 -c_runtime/wcstoul/test5/paltest_wcstoul_test5 -c_runtime/wcstoul/test6/paltest_wcstoul_test6 c_runtime/_vsnprintf_s/test1/paltest_vsnprintf_test1 c_runtime/_vsnprintf_s/test10/paltest_vsnprintf_test10 c_runtime/_vsnprintf_s/test11/paltest_vsnprintf_test11 @@ -48,10 +31,7 @@ c_runtime/_vsnprintf_s/test4/paltest_vsnprintf_test4 c_runtime/_vsnprintf_s/test6/paltest_vsnprintf_test6 c_runtime/_vsnprintf_s/test8/paltest_vsnprintf_test8 c_runtime/_vsnprintf_s/test9/paltest_vsnprintf_test9 -c_runtime/_wcsicmp/test1/paltest_wcsicmp_test1 c_runtime/_wcslwr_s/test1/paltest_wcslwr_s_test1 -c_runtime/_wcsnicmp/test1/paltest_wcsnicmp_test1 -c_runtime/_wtoi/test1/paltest_wtoi_test1 debug_api/OutputDebugStringW/test1/paltest_outputdebugstringw_test1 exception_handling/RaiseException/test1/paltest_raiseexception_test1 exception_handling/RaiseException/test2/paltest_raiseexception_test2 diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.cpp index 9c1955355008e7..417127a052a503 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.cpp @@ -12,6 +12,7 @@ #define UNICODE #include +#include PALTEST(miscellaneous_FormatMessageW_test1_paltest_formatmessagew_test1, "miscellaneous/FormatMessageW/test1/paltest_formatmessagew_test1") @@ -49,7 +50,7 @@ PALTEST(miscellaneous_FormatMessageW_test1_paltest_formatmessagew_test1, "miscel ", with no formatters in it."); } - if(memcmp(OutBuffer,TheString,wcslen(OutBuffer)*2+2) != 0) + if(memcmp(OutBuffer,TheString,u16_strlen(OutBuffer)*2+2) != 0) { Fail("ERROR: The formatted string should be %s but is really %s.", convertC(TheString), diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.cpp index e7b30213f2332d..eb01147701d953 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.cpp @@ -12,6 +12,7 @@ #define UNICODE #include +#include WCHAR OutBuffer_FormatMessageW_test2[1024]; @@ -47,7 +48,7 @@ int test1(int num, ...) } if(memcmp(OutBuffer_FormatMessageW_test2, convert("Pal INSERT Testing"), - wcslen(OutBuffer_FormatMessageW_test2)*2+2) != 0) + u16_strlen(OutBuffer_FormatMessageW_test2)*2+2) != 0) { Fail("ERROR: The formatted string should have been 'Pal INSERT " "Testing' but '%s' was returned.", diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.cpp index 47474477c87ee1..3b23a9dcac3840 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.cpp @@ -12,6 +12,7 @@ #define UNICODE #include +#include PALTEST(miscellaneous_FormatMessageW_test3_paltest_formatmessagew_test3, "miscellaneous/FormatMessageW/test3/paltest_formatmessagew_test3") @@ -65,7 +66,7 @@ PALTEST(miscellaneous_FormatMessageW_test3_paltest_formatmessagew_test3, "miscel */ if(memcmp(OutBuffer, (CorrectString = convert("Pal %1!u! %2!i! %3 Testing")), - wcslen(OutBuffer)*2+2) != 0) + u16_strlen(OutBuffer)*2+2) != 0) { free(TheString); free(CorrectString); diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.cpp index 0760a849550711..ed0650c6beb57f 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.cpp @@ -12,6 +12,7 @@ #define UNICODE #include +#include PALTEST(miscellaneous_FormatMessageW_test4_paltest_formatmessagew_test4, "miscellaneous/FormatMessageW/test4/paltest_formatmessagew_test4") @@ -60,7 +61,7 @@ PALTEST(miscellaneous_FormatMessageW_test4_paltest_formatmessagew_test4, "miscel if(memcmp(OutBuffer, convert("Pal Foo Bar FooBar Testing"), - wcslen(OutBuffer)*2+2) != 0) + u16_strlen(OutBuffer)*2+2) != 0) { Fail("ERROR: Since the FORMAT_MESSAGE_ARGUMENT_ARRAY flag was set, " "the result should have been 'Pal Foo Bar FooBar Testing' but was" diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.cpp index b7a21c496e8f9a..c3cf46efb32160 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.cpp @@ -13,6 +13,7 @@ #define UNICODE #include +#include PALTEST(miscellaneous_FormatMessageW_test5_paltest_formatmessagew_test5, "miscellaneous/FormatMessageW/test5/paltest_formatmessagew_test5") { @@ -61,7 +62,7 @@ PALTEST(miscellaneous_FormatMessageW_test5_paltest_formatmessagew_test5, "miscel if(memcmp(OutBuffer, convert("Pal Foo Bar FooBar Testing"), - wcslen(OutBuffer)*2+2) != 0) + u16_strlen(OutBuffer)*2+2) != 0) { Fail("ERROR: Since the FORMAT_MESSAGE_ALLOCATE_BUFFER flag was set, " "the result should have been 'Pal Foo Bar FooBar Testing' but " diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp index 15d94411bb030d..fde2b4268ba3f0 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp @@ -13,6 +13,7 @@ #define UNICODE #include +#include PALTEST(miscellaneous_FormatMessageW_test6_paltest_formatmessagew_test6, "miscellaneous/FormatMessageW/test6/paltest_formatmessagew_test6") @@ -61,7 +62,7 @@ PALTEST(miscellaneous_FormatMessageW_test6_paltest_formatmessagew_test6, "miscel "function failed when trying to Format a FROM_SYSTEM message."); } - if(wcslen(OutBuffer) <= 0) + if(u16_strlen(OutBuffer) <= 0) { Fail("ERROR: There are no characters in the buffer, and when the " "FORMAT_MESSAGE_FROM_SYSTEM flag is used with ERROR_FILE_NOT_FOUND error, " diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.cpp index 332de5f44eda97..0b73e34c5bc287 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.cpp @@ -10,16 +10,17 @@ ** **=========================================================*/ -/* Depends on SetEnvironmentVariable(), wcsstr() and wcslen() */ +/* Depends on SetEnvironmentVariable(), u16_strstr() and u16_strlen() */ #define UNICODE #include +#include PALTEST(miscellaneous_GetEnvironmentStringsW_test1_paltest_getenvironmentstringsw_test1, "miscellaneous/GetEnvironmentStringsW/test1/paltest_getenvironmentstringsw_test1") { LPWSTR CapturedEnvironmentStrings = NULL; - LPWSTR EnviroStringReturned = NULL; + const WCHAR* EnviroStringReturned = NULL; WCHAR EnvironmentVariableBuffer[] = {'P','A','L','T','E','S','T','I','N','G','\0'}; WCHAR EnvironmentValueBuffer[] = {'T','e','s','t','i','n','g','\0'}; @@ -55,9 +56,9 @@ PALTEST(miscellaneous_GetEnvironmentStringsW_test1_paltest_getenvironmentstrings while(*CapturedEnvironmentStrings != 0) { - EnviroStringReturned = wcsstr(CapturedEnvironmentStrings, + EnviroStringReturned = u16_strstr(CapturedEnvironmentStrings, EnvironmentVariableBuffer); - CapturedEnvironmentStrings += wcslen(CapturedEnvironmentStrings)+1; + CapturedEnvironmentStrings += u16_strlen(CapturedEnvironmentStrings)+1; if(EnviroStringReturned != NULL) { break; @@ -68,7 +69,7 @@ PALTEST(miscellaneous_GetEnvironmentStringsW_test1_paltest_getenvironmentstrings { Fail("The memory block returned was searched, but nothing was found to " "prove this was really the environment block. Either this " - "function, SetEnvironmentVariable or wcsstr() is broken.\n"); + "function, SetEnvironmentVariable or u16_strstr() is broken.\n"); } diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.cpp index 1701038377207e..7e0c89ed91c9f8 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.cpp @@ -15,6 +15,7 @@ #define UNICODE #include +#include PALTEST(miscellaneous_GetEnvironmentVariableW_test4_paltest_getenvironmentvariablew_test4, "miscellaneous/GetEnvironmentVariableW/test4/paltest_getenvironmentvariablew_test4") { @@ -49,7 +50,7 @@ PALTEST(miscellaneous_GetEnvironmentVariableW_test4_paltest_getenvironmentvariab pResultBuffer, size); - if(wcsncmp(pResultBuffer,convert("TEST"),wcslen(pResultBuffer) * 2) != 0) + if(u16_strncmp(pResultBuffer,convert("TEST"),u16_strlen(pResultBuffer) * 2) != 0) { Fail("ERROR: The value in the buffer should have been 'TEST' but was " "really '%s'.",convertC(pResultBuffer)); diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.cpp index 3601d22a5f463f..4d84f3bdc203bd 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.cpp @@ -13,6 +13,7 @@ ===========================================================*/ #include +#include PALTEST(miscellaneous_GetEnvironmentVariableW_test5_paltest_getenvironmentvariablew_test5, "miscellaneous/GetEnvironmentVariableW/test5/paltest_getenvironmentvariablew_test5") { @@ -82,7 +83,7 @@ PALTEST(miscellaneous_GetEnvironmentVariableW_test5_paltest_getenvironmentvariab } /* Compare the strings to see that the correct variable was returned */ - if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) + if(u16_strncmp(pResultBuffer,FirstEnvironmentValue,u16_strlen(pResultBuffer)) != 0) { free(pResultBuffer); Fail("ERROR: The value in the buffer should have been '%S' but " @@ -124,7 +125,7 @@ PALTEST(miscellaneous_GetEnvironmentVariableW_test5_paltest_getenvironmentvariab } /* Compare the two strings to confirm that the right value is returned */ - if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) + if(u16_strncmp(pResultBuffer,FirstEnvironmentValue,u16_strlen(pResultBuffer)) != 0) { free(pResultBuffer); Fail("ERROR: The value in the buffer should have been '%S' but " diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.cpp index 533f8e9f0d0809..79ac034d11fe7c 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.cpp @@ -13,6 +13,7 @@ ===========================================================*/ #include +#include PALTEST(miscellaneous_GetEnvironmentVariableW_test6_paltest_getenvironmentvariablew_test6, "miscellaneous/GetEnvironmentVariableW/test6/paltest_getenvironmentvariablew_test6") { @@ -78,7 +79,7 @@ PALTEST(miscellaneous_GetEnvironmentVariableW_test6_paltest_getenvironmentvariab } /* Compare the strings to see that the correct variable was returned */ - if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) + if(u16_strncmp(pResultBuffer,FirstEnvironmentValue,u16_strlen(pResultBuffer)) != 0) { free(pResultBuffer); Fail("ERROR: The value in the buffer should have been '%S' but " diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.cpp index 01107c8b2cb3ca..91d3b9cdf5eb4a 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.cpp @@ -18,6 +18,7 @@ #define BUF_SIZE 128 #include +#include /* Depends on GetEnvironmentVariable */ @@ -63,7 +64,7 @@ PALTEST(miscellaneous_SetEnvironmentVariableW_test1_paltest_setenvironmentvariab variable we set. */ - if(memcmp(NewValue,ValueBuffer,wcslen(ValueBuffer)*sizeof(WCHAR)+2) != 0) + if(memcmp(NewValue,ValueBuffer,u16_strlen(ValueBuffer)*sizeof(WCHAR)+2) != 0) { Fail("ERROR: When retrieving the variable that was just set, a " "difference was found. Instead of the value being '%s' it " @@ -99,7 +100,7 @@ PALTEST(miscellaneous_SetEnvironmentVariableW_test1_paltest_setenvironmentvariab */ if(memcmp(NewValue,SecondValueBuffer, - wcslen(SecondValueBuffer)*sizeof(WCHAR)+2) != 0) + u16_strlen(SecondValueBuffer)*sizeof(WCHAR)+2) != 0) { Fail("ERROR: When retrieving the variable that was just set, a " "difference was found. Instead of the value being '%s' it " diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.cpp index 4c5afe3ab2741b..e1f154f7f5fbf2 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.cpp @@ -13,6 +13,7 @@ ===========================================================*/ #include +#include PALTEST(miscellaneous_SetEnvironmentVariableW_test3_paltest_setenvironmentvariablew_test3, "miscellaneous/SetEnvironmentVariableW/test3/paltest_setenvironmentvariablew_test3") { @@ -94,7 +95,7 @@ PALTEST(miscellaneous_SetEnvironmentVariableW_test3_paltest_setenvironmentvariab } /* Compare the strings to see that the correct variable was returned */ - if(wcscmp(pResultBuffer,FirstEnvironmentValue) != 0) + if(u16_strcmp(pResultBuffer,FirstEnvironmentValue) != 0) { Trace("ERROR: The value in the buffer should have been '%S' but " "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); @@ -125,7 +126,7 @@ PALTEST(miscellaneous_SetEnvironmentVariableW_test3_paltest_setenvironmentvariab } /* Compare the two strings to confirm that the right value is returned */ - if(wcscmp(pResultBuffer,SecondEnvironmentValue) != 0) + if(u16_strcmp(pResultBuffer,SecondEnvironmentValue) != 0) { Trace("ERROR: The value in the buffer should have been '%S' but " "was really '%S'.\n",SecondEnvironmentValue,pResultBuffer); diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.cpp index 92b5ccf1d30d67..a1bcf693545a50 100644 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.cpp +++ b/src/coreclr/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.cpp @@ -13,6 +13,7 @@ ===========================================================*/ #include +#include PALTEST(miscellaneous_SetEnvironmentVariableW_test4_paltest_setenvironmentvariablew_test4, "miscellaneous/SetEnvironmentVariableW/test4/paltest_setenvironmentvariablew_test4") { @@ -77,7 +78,7 @@ PALTEST(miscellaneous_SetEnvironmentVariableW_test4_paltest_setenvironmentvariab } /* Compare the strings to see that the correct variable was returned */ - if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) + if(u16_strncmp(pResultBuffer,FirstEnvironmentValue,u16_strlen(pResultBuffer)) != 0) { Trace("ERROR: The value in the buffer should have been '%S' but " "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); diff --git a/src/coreclr/pal/tests/palsuite/paltestlist.txt b/src/coreclr/pal/tests/palsuite/paltestlist.txt index b348aa0e5fdb26..47c220bf21e274 100644 --- a/src/coreclr/pal/tests/palsuite/paltestlist.txt +++ b/src/coreclr/pal/tests/palsuite/paltestlist.txt @@ -15,23 +15,6 @@ c_runtime/sscanf_s/test6/paltest_sscanf_test6 c_runtime/sscanf_s/test7/paltest_sscanf_test7 c_runtime/sscanf_s/test8/paltest_sscanf_test8 c_runtime/sscanf_s/test9/paltest_sscanf_test9 -c_runtime/wcscat/test1/paltest_wcscat_test1 -c_runtime/wcschr/test1/paltest_wcschr_test1 -c_runtime/wcscmp/test1/paltest_wcscmp_test1 -c_runtime/wcscpy/test1/paltest_wcscpy_test1 -c_runtime/wcslen/test1/paltest_wcslen_test1 -c_runtime/wcsncmp/test1/paltest_wcsncmp_test1 -c_runtime/wcsncpy/test1/paltest_wcsncpy_test1 -c_runtime/wcsrchr/test1/paltest_wcsrchr_test1 -c_runtime/wcsstr/test1/paltest_wcsstr_test1 -c_runtime/wcstod/test1/paltest_wcstod_test1 -c_runtime/wcstod/test2/paltest_wcstod_test2 -c_runtime/wcstoul/test1/paltest_wcstoul_test1 -c_runtime/wcstoul/test2/paltest_wcstoul_test2 -c_runtime/wcstoul/test3/paltest_wcstoul_test3 -c_runtime/wcstoul/test4/paltest_wcstoul_test4 -c_runtime/wcstoul/test5/paltest_wcstoul_test5 -c_runtime/wcstoul/test6/paltest_wcstoul_test6 c_runtime/_vsnprintf_s/test1/paltest_vsnprintf_test1 c_runtime/_vsnprintf_s/test10/paltest_vsnprintf_test10 c_runtime/_vsnprintf_s/test11/paltest_vsnprintf_test11 @@ -48,10 +31,7 @@ c_runtime/_vsnprintf_s/test4/paltest_vsnprintf_test4 c_runtime/_vsnprintf_s/test6/paltest_vsnprintf_test6 c_runtime/_vsnprintf_s/test8/paltest_vsnprintf_test8 c_runtime/_vsnprintf_s/test9/paltest_vsnprintf_test9 -c_runtime/_wcsicmp/test1/paltest_wcsicmp_test1 c_runtime/_wcslwr_s/test1/paltest_wcslwr_s_test1 -c_runtime/_wcsnicmp/test1/paltest_wcsnicmp_test1 -c_runtime/_wtoi/test1/paltest_wtoi_test1 debug_api/OutputDebugStringW/test1/paltest_outputdebugstringw_test1 exception_handling/RaiseException/test1/paltest_raiseexception_test1 exception_handling/RaiseException/test2/paltest_raiseexception_test2 diff --git a/src/coreclr/tools/metainfo/mdobj.cpp b/src/coreclr/tools/metainfo/mdobj.cpp index a4333df63b6147..c6462fa404b8b8 100644 --- a/src/coreclr/tools/metainfo/mdobj.cpp +++ b/src/coreclr/tools/metainfo/mdobj.cpp @@ -209,7 +209,7 @@ void DisplayArchive(_In_z_ WCHAR* szFile, ULONG DumpFilter, _In_opt_z_ WCHAR* sz // Display metadata only for object files. // If szObjName is specified, display metadata only for that one object file. if (!_stricmp(&szName[strlen(szName) - OBJ_EXT_LEN], OBJ_EXT) && - (!szObjName || !_wcsicmp(szObjName, wzName))) + (!szObjName || !u16_stricmp(szObjName, wzName))) { // Try to find the MetaData section in the current object file. hr = FindObjMetaData(pbMapAddress+IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR, &pvMetaData, &cbMetaData); @@ -281,13 +281,13 @@ void DisplayFile(_In_z_ WCHAR* szFile, BOOL isFile, ULONG DumpFilter, _In_opt_z_ if (DumpFilter & MDInfo::dumpValidate) { - if (pExt && (!_wcsicmp(pExt, OBJ_EXT_W) || !_wcsicmp(pExt, LIB_EXT_W))) + if (pExt && (!u16_stricmp(pExt, OBJ_EXT_W) || !u16_stricmp(pExt, LIB_EXT_W))) g_ValModuleType = ValidatorModuleTypeObj; else g_ValModuleType = ValidatorModuleTypePE; } - if (pExt && !_wcsicmp(pExt, LIB_EXT_W)) + if (pExt && !u16_stricmp(pExt, LIB_EXT_W)) DisplayArchive(szFile, DumpFilter, szObjName, pDisplayString); else { diff --git a/src/coreclr/utilcode/CMakeLists.txt b/src/coreclr/utilcode/CMakeLists.txt index 5446bd0fef88a7..7346c1c89b9768 100644 --- a/src/coreclr/utilcode/CMakeLists.txt +++ b/src/coreclr/utilcode/CMakeLists.txt @@ -8,7 +8,6 @@ set(UTILCODE_COMMON_SOURCES ex.cpp sbuffer.cpp sstring_com.cpp - fstring.cpp namespaceutil.cpp makepath.cpp splitpath.cpp diff --git a/src/coreclr/utilcode/fstring.cpp b/src/coreclr/utilcode/fstring.cpp deleted file mode 100644 index 3abe6936657533..00000000000000 --- a/src/coreclr/utilcode/fstring.cpp +++ /dev/null @@ -1,305 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// --------------------------------------------------------------------------- -// FString.cpp -// - -// --------------------------------------------------------------------------- - -#include "stdafx.h" -#include "ex.h" -#include "holder.h" - -#include "fstring.h" - - -namespace FString -{ - -#ifdef _MSC_VER -#pragma optimize("t", on) -#endif // _MSC_VER - -#define MAX_LENGTH 0x1fffff00 - - -HRESULT Unicode_Utf8_Length(_In_z_ LPCWSTR pString, _Out_ bool * pAllAscii, _Out_ DWORD * pLength) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - * pAllAscii = true; - - LPCWSTR p = pString; - - while (true) - { - WCHAR ch = * p; - - // Single check for termination and non ASCII - if (((unsigned) (ch - 1)) >= 0x7F) - { - if (ch != 0) - { - * pAllAscii = false; - } - - break; - } - - p ++; - } - - if (* pAllAscii) - { - if ((p - pString) > MAX_LENGTH) - { - return COR_E_OVERFLOW; - } - - * pLength = (DWORD) (p - pString); - } - else - { - size_t length = minipal_get_length_utf16_to_utf8((const CHAR16_T*)pString, u16_strlen(pString), 0); - - if (length > MAX_LENGTH) - { - return COR_E_OVERFLOW; - } - - * pLength = (DWORD)length; - } - - return S_OK; -} - - -// UNICODE to UTF8 -HRESULT Unicode_Utf8(_In_z_ LPCWSTR pString, bool allAscii, _Out_writes_bytes_(length) LPSTR pBuffer, DWORD length) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - pBuffer[length] = 0; - - if (allAscii) - { - LPCWSTR p = pString; - - LPSTR q = pBuffer; - - LPCWSTR endP = p + length - 8; - - // Unfold to optimize for long string: 8 chars per iteration - while (p < endP) - { - q[0] = (char) p[0]; - q[1] = (char) p[1]; - q[2] = (char) p[2]; - q[3] = (char) p[3]; - - q[4] = (char) p[4]; - q[5] = (char) p[5]; - q[6] = (char) p[6]; - q[7] = (char) p[7]; - - q += 8; - p += 8; - } - - endP += 8; - - while (p < endP) - { - * q ++ = (char) * p ++; - } - } - else - { - if (minipal_convert_utf16_to_utf8((const CHAR16_T*)pString, u16_strlen(pString), pBuffer, length, 0) == 0) - { - return HRESULT_FROM_WIN32(errno); - } - } - - return S_OK; -} - - -HRESULT Utf8_Unicode_Length(_In_z_ LPCSTR pString, _Out_ bool * pAllAscii, _Out_ DWORD * pLength) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - * pAllAscii = true; - - LPCSTR p = pString; - - while (true) - { - char ch = * p; - - // Single check for termination and non ASCII - if (((unsigned) (ch - 1)) >= 0x7F) - { - if (ch != 0) - { - * pAllAscii = false; - } - - break; - } - - p ++; - } - - if (* pAllAscii) - { - if ((p - pString) > MAX_LENGTH) - { - return COR_E_OVERFLOW; - } - - * pLength = (DWORD)(p - pString); - } - else - { - size_t length = minipal_get_length_utf8_to_utf16(pString, strlen(pString), 0); - - if (length > MAX_LENGTH) - { - return COR_E_OVERFLOW; - } - - * pLength = (DWORD)length; - } - - return S_OK; -} - - -// UTF8 to Unicode - -HRESULT Utf8_Unicode(_In_z_ LPCSTR pString, bool allAscii, _Out_writes_bytes_(length) LPWSTR pBuffer, DWORD length) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - pBuffer[length] = 0; - - if (allAscii) - { - LPCSTR p = pString; - - LPWSTR q = pBuffer; - - LPCSTR endP = p + length - 8; - - // Unfold to optimize for long string: 4 chars per iteration - while (p < endP) - { - q[0] = (WCHAR) p[0]; - q[1] = (WCHAR) p[1]; - q[2] = (WCHAR) p[2]; - q[3] = (WCHAR) p[3]; - - q[4] = (WCHAR) p[4]; - q[5] = (WCHAR) p[5]; - q[6] = (WCHAR) p[6]; - q[7] = (WCHAR) p[7]; - - q += 8; - p += 8; - } - - endP += 8; - - while (p < endP) - { - * q ++ = (WCHAR) * p ++; - } - } - else - { - if (minipal_convert_utf8_to_utf16(pString, strlen(pString), (CHAR16_T*)pBuffer, length, 0) == 0) - { - return HRESULT_FROM_WIN32(errno); - } - } - - return S_OK; -} - - -HRESULT ConvertUnicode_Utf8(_In_z_ LPCWSTR pString, _Outptr_result_z_ LPSTR * pBuffer) -{ - bool allAscii; - DWORD length; - - HRESULT hr = Unicode_Utf8_Length(pString, & allAscii, & length); - - if (SUCCEEDED(hr)) - { - * pBuffer = new (nothrow) char[length + 1]; - - if (* pBuffer == NULL) - { - hr = E_OUTOFMEMORY; - } - else - { - hr = Unicode_Utf8(pString, allAscii, * pBuffer, length); - } - } - - return hr; -} - - -HRESULT ConvertUtf8_Unicode(_In_z_ LPCSTR pString, _Outptr_result_z_ LPWSTR * pBuffer) -{ - bool allAscii; - DWORD length; - - HRESULT hr = Utf8_Unicode_Length(pString, & allAscii, & length); - - if (SUCCEEDED(hr)) - { - * pBuffer = new (nothrow) WCHAR[length + 1]; - - if (* pBuffer == NULL) - { - hr = E_OUTOFMEMORY; - } - else - { - hr = Utf8_Unicode(pString, allAscii, * pBuffer, length); - } - } - - return hr; -} - - -#ifdef _MSC_VER -#pragma optimize("", on) -#endif // _MSC_VER - -} // namespace FString diff --git a/src/coreclr/utilcode/sstring.cpp b/src/coreclr/utilcode/sstring.cpp index 8329fbd6bb5964..667e49a69ba033 100644 --- a/src/coreclr/utilcode/sstring.cpp +++ b/src/coreclr/utilcode/sstring.cpp @@ -817,28 +817,24 @@ COUNT_T SString::ConvertToUTF8(SString &s) const UNREACHABLE(); } - // @todo: use WC_NO_BEST_FIT_CHARS - bool allAscii; - DWORD length; + size_t length = minipal_get_length_utf16_to_utf8((const CHAR16_T*)GetRawUnicode(), GetRawCount() + 1, 0); + if (length == 0) + ThrowWin32(errno); - HRESULT hr = FString::Unicode_Utf8_Length(GetRawUnicode(), & allAscii, & length); + if (!FitsIn(length)) + ThrowHR(COR_E_OVERFLOW); - if (SUCCEEDED(hr)) - { - s.Resize(length, REPRESENTATION_UTF8); + s.Resize((COUNT_T)(length - 1), REPRESENTATION_UTF8); - //FString::Unicode_Utf8 expects an array all the time - //we optimize the empty string by replacing it with null for SString above in Resize - if (length > 0) - { - hr = FString::Unicode_Utf8(GetRawUnicode(), allAscii, (LPSTR) s.GetRawUTF8(), length); - } + // Resizing to zero switches to the shared empty buffer, which must not be written to + if (length > 1) + { + if (minipal_convert_utf16_to_utf8((const CHAR16_T*)GetRawUnicode(), GetRawCount() + 1, (LPSTR)s.GetRawUTF8(), length, 0) == 0) + ThrowWin32(errno); } - IfFailThrow(hr); - _ASSERTE(s.IsRepresentation(REPRESENTATION_UTF8)); - return length + 1; + return (COUNT_T)length; } //----------------------------------------------------------------------------- diff --git a/src/coreclr/vm/classhash.cpp b/src/coreclr/vm/classhash.cpp index fe22899131ea3e..b04eaee254227c 100644 --- a/src/coreclr/vm/classhash.cpp +++ b/src/coreclr/vm/classhash.cpp @@ -9,7 +9,6 @@ #include "common.h" #include "classhash.h" #include "dacenumerablehash.inl" -#include "fstring.h" #include "classhash.inl" PTR_EEClassHashEntry EEClassHashEntry::GetEncloser() diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index 833ce943a0a32e..745da22ed82638 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -2297,15 +2297,15 @@ BOOL EEJitManager::LoadJIT() if (altJitOsConfig != NULL) { // We have some inconsistency all over the place with osx vs macos, let's handle both here - if ((_wcsicmp(altJitOsConfig, W("macos")) == 0) || (_wcsicmp(altJitOsConfig, W("osx")) == 0)) + if ((u16_stricmp(altJitOsConfig, W("macos")) == 0) || (u16_stricmp(altJitOsConfig, W("osx")) == 0)) { targetOs = CORINFO_APPLE; } - else if ((_wcsicmp(altJitOsConfig, W("linux")) == 0) || (_wcsicmp(altJitOsConfig, W("unix")) == 0)) + else if ((u16_stricmp(altJitOsConfig, W("linux")) == 0) || (u16_stricmp(altJitOsConfig, W("unix")) == 0)) { targetOs = CORINFO_UNIX; } - else if (_wcsicmp(altJitOsConfig, W("windows")) == 0) + else if (u16_stricmp(altJitOsConfig, W("windows")) == 0) { targetOs = CORINFO_WINNT; } diff --git a/src/coreclr/vm/eeconfig.cpp b/src/coreclr/vm/eeconfig.cpp index e3fad8b98437aa..c87632f32a3fc1 100644 --- a/src/coreclr/vm/eeconfig.cpp +++ b/src/coreclr/vm/eeconfig.cpp @@ -433,11 +433,11 @@ HRESULT EEConfig::sync() IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_DOTNET_MODIFIABLE_ASSEMBLIES, &wszModifiableAssemblies)); if (wszModifiableAssemblies) { - if (_wcsicmp(wszModifiableAssemblies, W("debug")) == 0) + if (u16_stricmp(wszModifiableAssemblies, W("debug")) == 0) { modifiableAssemblies = MODIFIABLE_ASSM_DEBUG; } - else if (_wcsicmp(wszModifiableAssemblies, W("none")) == 0) + else if (u16_stricmp(wszModifiableAssemblies, W("none")) == 0) { modifiableAssemblies = MODIFIABLE_ASSM_NONE; } diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index 2e4e3b3b4dd9b1..db57dfb01c9e87 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -4002,7 +4002,7 @@ static bool s_useEntryPointFilterCorhostProperty = false; void ParseUseEntryPointFilter(LPCWSTR value) { // set s_useEntryPointFilter true if value != "0" - if (value && (_wcsicmp(value, W("0")) != 0)) + if (value && (u16_stricmp(value, W("0")) != 0)) { s_useEntryPointFilterCorhostProperty = true; } diff --git a/src/coreclr/vm/interoputil.cpp b/src/coreclr/vm/interoputil.cpp index 9e96bf28f006aa..207a9d50fcaa57 100644 --- a/src/coreclr/vm/interoputil.cpp +++ b/src/coreclr/vm/interoputil.cpp @@ -2570,7 +2570,7 @@ DISPID ExtractStandardDispId(_In_z_ LPWSTR strStdDispIdMemberName) COMPlusThrow(kArgumentException, IDS_EE_INVALID_STD_DISPID_NAME); // Extract the number from the standard DISPID member name. - return _wtoi(strDispId); + return (int)u16_strtoul(strDispId, NULL, 10); } // Filter for calls out from the 'vm' to native code, if there's a possibility of SEH exceptions diff --git a/src/coreclr/vm/jithost.cpp b/src/coreclr/vm/jithost.cpp index 22ee13e4283344..48c940f4813b54 100644 --- a/src/coreclr/vm/jithost.cpp +++ b/src/coreclr/vm/jithost.cpp @@ -59,22 +59,20 @@ const char* JitHost::getStringConfigValue(const char* name) return nullptr; } - bool allAscii; - DWORD length; - HRESULT hr = FString::Unicode_Utf8_Length(allocatedStr, &allAscii, &length); - if (FAILED(hr)) + size_t sourceLength = u16_strlen(allocatedStr) + 1; + size_t length = minipal_get_length_utf16_to_utf8((const CHAR16_T*)allocatedStr, sourceLength, 0); + if (length == 0) { CLRConfig::FreeConfigString(allocatedStr); return nullptr; } - AStringHolder utf8Result(new char[length + 1]); - hr = FString::Unicode_Utf8(allocatedStr, allAscii, utf8Result, length); - utf8Result[length] = '\0'; + AStringHolder utf8Result(new char[length]); + size_t converted = minipal_convert_utf16_to_utf8((const CHAR16_T*)allocatedStr, sourceLength, utf8Result, length, 0); CLRConfig::FreeConfigString(allocatedStr); - if (FAILED(hr)) + if (converted == 0) { return nullptr; } From ba79ef8ce38da7f46a1cbd86f15ca83e5a4c394e Mon Sep 17 00:00:00 2001 From: am11 <3840695+am11@users.noreply.github.com> Date: Mon, 9 Nov 2026 00:25:33 +0200 Subject: [PATCH 2/4] Preserve the PAL semantics of the dn-u16 parsers and port their tests * u16_strtoul truncates negative values instead of saturating them, and u16_strtod sets the end pointer past an incomplete exponent, like the deleted PAL wcstoul and wcstod did. * u16_strnicmp lowers characters with towlower, like the deleted PAL _wcsnicmp did. * Keep calling _wtoi in the Windows-only COM interop code. * Port the deleted PAL wide string tests to src/tests/minipal. Co-authored-by: Cursor --- src/coreclr/minipal/Unix/dn-u16.cpp | 64 +-- src/coreclr/vm/interoputil.cpp | 2 +- src/tests/minipal/CMakeLists.txt | 13 +- src/tests/minipal/NativeMinipalTests.cs | 1 + .../minipal/native-minipal-tests-driver.c | 2 + src/tests/minipal/u16-tests.cpp | 421 ++++++++++++++++++ 6 files changed, 471 insertions(+), 32 deletions(-) create mode 100644 src/tests/minipal/u16-tests.cpp diff --git a/src/coreclr/minipal/Unix/dn-u16.cpp b/src/coreclr/minipal/Unix/dn-u16.cpp index ab6e323afb8c31..ffe7d93f408445 100644 --- a/src/coreclr/minipal/Unix/dn-u16.cpp +++ b/src/coreclr/minipal/Unix/dn-u16.cpp @@ -6,8 +6,10 @@ typedef char16_t WCHAR; #include #include #include +#include #include #include +#include #include size_t u16_strlen(const WCHAR* str) @@ -36,23 +38,17 @@ int u16_strncmp(const WCHAR* str1, const WCHAR* str2, size_t count) return diff; } -static WCHAR ascii_tolower(WCHAR ch) -{ - return (ch >= (WCHAR)'A' && ch <= (WCHAR)'Z') ? (WCHAR)(ch - 'A' + 'a') : ch; -} - int u16_stricmp(const WCHAR* str1, const WCHAR* str2) { - return u16_strnicmp(str1, str2, SIZE_MAX); + return u16_strnicmp(str1, str2, 0x7fffffff); } -// Folds only ASCII letters, like the Windows CRT _wcsnicmp does in the default "C" locale. int u16_strnicmp(const WCHAR* str1, const WCHAR* str2, size_t count) { int diff = 0; for (size_t i = 0; i < count; i++) { - diff = ascii_tolower(str1[i]) - ascii_tolower(str2[i]); + diff = (int)towlower(str1[i]) - (int)towlower(str2[i]); if (diff != 0) break; @@ -243,20 +239,24 @@ uint32_t u16_strtoul(const WCHAR* nptr, WCHAR** endptr, int base) } char* end; - unsigned long long value = strtoull(buffer, &end, base); - - // Windows' unsigned long is 32-bit. Negative inputs wrap around like they do there, - // unless their magnitude doesn't fit. - const char* p = buffer; - while (isspace((unsigned char)*p)) - p++; + unsigned long value = strtoul(buffer, &end, base); - unsigned long long magnitude = (*p == '-') ? (0 - value) : value; - if (magnitude > UINT32_MAX) +#if ULONG_MAX > UINT32_MAX + // Windows' unsigned long is 32-bit, so positive values that don't fit in it saturate. + // Negative values are truncated instead, regardless of their magnitude. + if (value > UINT32_MAX) { - value = UINT32_MAX; - errno = ERANGE; + const char* p = buffer; + while (isspace((unsigned char)*p)) + p++; + + if (*p != '-') + { + value = UINT32_MAX; + errno = ERANGE; + } } +#endif if (endptr != nullptr) *endptr = (WCHAR*)nptr + (end - buffer); @@ -285,26 +285,32 @@ uint64_t u16_strtoui64(const WCHAR* nptr, WCHAR** endptr, int base) return value; } +// Only decimal notation is accepted; the C runtime strtod would also accept hex, "inf" and "nan". +// The end pointer is set past all the characters that can be part of a decimal number, even +// the ones strtod didn't consume, e.g. past the "e" of "1.5e". double u16_strtod(const WCHAR* nptr, WCHAR** endptr) { - // Restrict the input to decimal notation; the C runtime strtod would also accept hex, "inf" and "nan". + if (nptr == nullptr) + return 0.0; + const WCHAR* start = nptr; - while (is_ascii(*start) && isspace((unsigned char)*start)) + while (iswspace(*start)) start++; + double value = 0.0; + const WCHAR* stop = nptr; + char* buffer = narrow_prefix(start, is_floating_point_char); - if (buffer == nullptr) + if (buffer != nullptr && buffer[0] != '\0') { - if (endptr != nullptr) - *endptr = (WCHAR*)nptr; - return 0.0; + char* end; + value = strtod(buffer, &end); + if (value != 0.0 || end != buffer) + stop = start + strlen(buffer); } - char* end; - double value = strtod(buffer, &end); - if (endptr != nullptr) - *endptr = (end == buffer) ? (WCHAR*)nptr : (WCHAR*)start + (end - buffer); + *endptr = (WCHAR*)stop; free(buffer); return value; diff --git a/src/coreclr/vm/interoputil.cpp b/src/coreclr/vm/interoputil.cpp index 207a9d50fcaa57..9e96bf28f006aa 100644 --- a/src/coreclr/vm/interoputil.cpp +++ b/src/coreclr/vm/interoputil.cpp @@ -2570,7 +2570,7 @@ DISPID ExtractStandardDispId(_In_z_ LPWSTR strStdDispIdMemberName) COMPlusThrow(kArgumentException, IDS_EE_INVALID_STD_DISPID_NAME); // Extract the number from the standard DISPID member name. - return (int)u16_strtoul(strDispId, NULL, 10); + return _wtoi(strDispId); } // Filter for calls out from the 'vm' to native code, if there's a possibility of SEH exceptions diff --git a/src/tests/minipal/CMakeLists.txt b/src/tests/minipal/CMakeLists.txt index 445487d2000ce8..9191d9c3ded57a 100644 --- a/src/tests/minipal/CMakeLists.txt +++ b/src/tests/minipal/CMakeLists.txt @@ -8,13 +8,22 @@ endif() include_directories(${CLR_SRC_NATIVE_DIR}) set(NATIVE_TEST_COMMON_DIR ../tracing/eventpipe/native/common) +set(CORECLR_MINIPAL_DIR ${CLR_REPO_ROOT_DIR}/src/coreclr/minipal) + +if(CLR_CMAKE_HOST_WIN32) + set(DN_U16_SOURCE ${CORECLR_MINIPAL_DIR}/Windows/dn-u16.cpp) +else() + set(DN_U16_SOURCE ${CORECLR_MINIPAL_DIR}/Unix/dn-u16.cpp) +endif() add_executable(NativeMinipalTestsDriver ${NATIVE_TEST_COMMON_DIR}/driver.c ${NATIVE_TEST_COMMON_DIR}/test.c native-minipal-tests-driver.c - utf8-tests.c) + utf8-tests.c + u16-tests.cpp + ${DN_U16_SOURCE}) -target_include_directories(NativeMinipalTestsDriver PRIVATE ${NATIVE_TEST_COMMON_DIR}) +target_include_directories(NativeMinipalTestsDriver PRIVATE ${NATIVE_TEST_COMMON_DIR} ${CORECLR_MINIPAL_DIR}) target_link_libraries(NativeMinipalTestsDriver PRIVATE minipal) install(TARGETS NativeMinipalTestsDriver DESTINATION bin) diff --git a/src/tests/minipal/NativeMinipalTests.cs b/src/tests/minipal/NativeMinipalTests.cs index 23a678bad86c18..346308eca2bb31 100644 --- a/src/tests/minipal/NativeMinipalTests.cs +++ b/src/tests/minipal/NativeMinipalTests.cs @@ -8,6 +8,7 @@ public class NativeMinipalTests { [Theory] [InlineData("utf8")] + [InlineData("u16")] public static void RunSuite(string group) { (int exitCode, string output, string error) = NativeTestProcess.Run("NativeMinipalTestsDriver", group); diff --git a/src/tests/minipal/native-minipal-tests-driver.c b/src/tests/minipal/native-minipal-tests-driver.c index 59899dba334103..9863410c21143f 100644 --- a/src/tests/minipal/native-minipal-tests-driver.c +++ b/src/tests/minipal/native-minipal-tests-driver.c @@ -4,9 +4,11 @@ #include "test.h" DEFINE_TEST_GROUP_INIT_H(minipal_utf8_tests_init); +DEFINE_TEST_GROUP_INIT_H(minipal_u16_tests_init); static const Group test_groups[] = { {"utf8", minipal_utf8_tests_init}, + {"u16", minipal_u16_tests_init}, {NULL, NULL} }; diff --git a/src/tests/minipal/u16-tests.cpp b/src/tests/minipal/u16-tests.cpp new file mode 100644 index 00000000000000..7f5ff6bb0df071 --- /dev/null +++ b/src/tests/minipal/u16-tests.cpp @@ -0,0 +1,421 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +extern "C" +{ +#include "test.h" +} + +#include +#include +#include +#include +#include + +#ifdef _WIN32 +typedef wchar_t WCHAR; +#else +typedef char16_t WCHAR; +#endif + +#include + +#define W(str) ((const WCHAR*)u##str) + +// A value the parsers never set, to see whether they touch errno +#define ERRNO_SENTINEL 12345 + +static RESULT test_u16_strlen(void) +{ + if (u16_strlen(W("foo ")) != 4) + return FAILED("u16_strlen(\"foo \") != 4"); + + if (u16_strlen(W("")) != 0) + return FAILED("u16_strlen(\"\") != 0"); + + return OK; +} + +static RESULT test_u16_strcmp(void) +{ + if (u16_strcmp(W("foo"), W("foo")) != 0) + return FAILED("u16_strcmp(\"foo\", \"foo\") != 0"); + + if (u16_strcmp(W("foo"), W("foox")) >= 0) + return FAILED("u16_strcmp(\"foo\", \"foox\") >= 0"); + + if (u16_strcmp(W("foox"), W("foo")) <= 0) + return FAILED("u16_strcmp(\"foox\", \"foo\") <= 0"); + + if (u16_strcmp(W("foo"), W("fOo")) <= 0) + return FAILED("u16_strcmp(\"foo\", \"fOo\") <= 0"); + + if (u16_strcmp(W("fOo"), W("foo")) >= 0) + return FAILED("u16_strcmp(\"fOo\", \"foo\") >= 0"); + + return OK; +} + +static RESULT test_u16_strncmp(void) +{ + if (u16_strncmp(W("foo"), W("foox"), 4) >= 0) + return FAILED("u16_strncmp(\"foo\", \"foox\", 4) >= 0"); + + if (u16_strncmp(W("foox"), W("foo"), 4) <= 0) + return FAILED("u16_strncmp(\"foox\", \"foo\", 4) <= 0"); + + if (u16_strncmp(W("foo"), W("foox"), 3) != 0) + return FAILED("u16_strncmp(\"foo\", \"foox\", 3) != 0"); + + if (u16_strncmp(W("foo"), W("fOo"), 3) <= 0) + return FAILED("u16_strncmp(\"foo\", \"fOo\", 3) <= 0"); + + if (u16_strncmp(W("fOo"), W("foo"), 3) >= 0) + return FAILED("u16_strncmp(\"fOo\", \"foo\", 3) >= 0"); + + if (u16_strncmp(W("abc"), W("xyz"), 0) != 0) + return FAILED("u16_strncmp(\"abc\", \"xyz\", 0) != 0"); + + return OK; +} + +static RESULT test_u16_stricmp(void) +{ + if (u16_stricmp(W("foo"), W("fOo")) != 0) + return FAILED("u16_stricmp(\"foo\", \"fOo\") != 0"); + + if (u16_stricmp(W("fOo"), W("foo_bar")) >= 0) + return FAILED("u16_stricmp(\"fOo\", \"foo_bar\") >= 0"); + + if (u16_stricmp(W("foo_bar"), W("foobar")) >= 0) + return FAILED("u16_stricmp(\"foo_bar\", \"foobar\") >= 0"); + + if (u16_stricmp(W("foobar"), W("foo")) <= 0) + return FAILED("u16_stricmp(\"foobar\", \"foo\") <= 0"); + + if (u16_stricmp(W("foo_bar"), W("fOo")) <= 0) + return FAILED("u16_stricmp(\"foo_bar\", \"fOo\") <= 0"); + + if (u16_stricmp(W(""), W("")) != 0) + return FAILED("u16_stricmp(\"\", \"\") != 0"); + + return OK; +} + +static RESULT test_u16_strnicmp(void) +{ + if (u16_strnicmp(W("foo"), W("foox"), 4) >= 0) + return FAILED("u16_strnicmp(\"foo\", \"foox\", 4) >= 0"); + + if (u16_strnicmp(W("foox"), W("foo"), 4) <= 0) + return FAILED("u16_strnicmp(\"foox\", \"foo\", 4) <= 0"); + + if (u16_strnicmp(W("foo"), W("foox"), 3) != 0) + return FAILED("u16_strnicmp(\"foo\", \"foox\", 3) != 0"); + + if (u16_strnicmp(W("foo"), W("fOo"), 3) != 0) + return FAILED("u16_strnicmp(\"foo\", \"fOo\", 3) != 0"); + + // ']' sorts between the upper and lower case letters, so these show that both sides are lowered + if (u16_strnicmp(W("ABCDE"), W("ABCD]"), 5) <= 0) + return FAILED("u16_strnicmp(\"ABCDE\", \"ABCD]\", 5) <= 0"); + + if (u16_strnicmp(W("abcde"), W("abcd]"), 5) <= 0) + return FAILED("u16_strnicmp(\"abcde\", \"abcd]\", 5) <= 0"); + + if (u16_strnicmp(W("api-ms-win"), W("API-xx"), 4) != 0) + return FAILED("u16_strnicmp(\"api-ms-win\", \"API-xx\", 4) != 0"); + + if (u16_strnicmp(W("ab"), W("AB"), 10) != 0) + return FAILED("u16_strnicmp(\"ab\", \"AB\", 10) != 0"); + + return OK; +} + +static RESULT test_u16_strchr(void) +{ + const WCHAR* str = W("foo bar "); + + if (u16_strchr(str, (WCHAR)' ') != str + 3) + return FAILED("u16_strchr didn't find the first ' '"); + + if (u16_strchr(str, (WCHAR)'$') != NULL) + return FAILED("u16_strchr found a missing character"); + + if (u16_strchr(str, (WCHAR)'\0') != str + 8) + return FAILED("u16_strchr didn't find the null terminator"); + + return OK; +} + +static RESULT test_u16_strrchr(void) +{ + const WCHAR* str = W("foo bar baz"); + + if (u16_strrchr(str, (WCHAR)' ') != str + 7) + return FAILED("u16_strrchr didn't find the last ' '"); + + if (u16_strrchr(str, (WCHAR)'$') != NULL) + return FAILED("u16_strrchr found a missing character"); + + return OK; +} + +static RESULT test_u16_strstr(void) +{ + const WCHAR* str = W("foo bar baz bar"); + + if (u16_strstr(str, W("bar")) != str + 4) + return FAILED("u16_strstr didn't find the first \"bar\""); + + if (u16_strstr(str, W("Bar")) != NULL) + return FAILED("u16_strstr ignored case"); + + if (u16_strstr(str, W("")) != str) + return FAILED("u16_strstr didn't return the string for an empty key"); + + if (u16_strstr(str, W("arggggh!")) != NULL) + return FAILED("u16_strstr found a missing string"); + + return OK; +} + +static RESULT test_u16_strcpy_s(void) +{ + WCHAR dest[80]; + + if (u16_strcpy_s(dest, ARRAY_SIZE(dest), W("foo")) != dest) + return FAILED("u16_strcpy_s didn't return the destination"); + + if (u16_strcmp(dest, W("foo")) != 0) + return FAILED("u16_strcpy_s didn't copy \"foo\""); + + return OK; +} + +static RESULT test_u16_strcat_s(void) +{ + WCHAR dest[80]; + dest[0] = 0; + + if (u16_strcat_s(dest, ARRAY_SIZE(dest), W("foo ")) != dest || + u16_strcat_s(dest, ARRAY_SIZE(dest), W("bar ")) != dest || + u16_strcat_s(dest, ARRAY_SIZE(dest), W("baz")) != dest) + { + return FAILED("u16_strcat_s didn't return the destination"); + } + + if (u16_strcmp(dest, W("foo bar baz")) != 0) + return FAILED("u16_strcat_s didn't give \"foo bar baz\""); + + return OK; +} + +static RESULT test_u16_strncpy_s(void) +{ + WCHAR dest[80]; + for (size_t i = 0; i < ARRAY_SIZE(dest); i++) + dest[i] = (WCHAR)'x'; + + if (u16_strncpy_s(dest, ARRAY_SIZE(dest), W("foobar"), 3) != dest) + return FAILED("u16_strncpy_s didn't return the destination"); + + if (u16_strcmp(dest, W("foo")) != 0) + return FAILED("u16_strncpy_s didn't copy and terminate \"foo\""); + + if (u16_strncpy_s(dest, ARRAY_SIZE(dest), W("foobar"), 40) != dest) + return FAILED("u16_strncpy_s didn't return the destination"); + + if (u16_strcmp(dest, W("foobar")) != 0) + return FAILED("u16_strncpy_s didn't copy \"foobar\""); + + return OK; +} + +typedef struct +{ + const WCHAR* str; + int base; + uint32_t value; + size_t stop; + int error; +} StrToULCase; + +static const StrToULCase strtoul_cases[] = +{ + { W("12345"), 4, 27, 3, 0 }, + { W("12345"), 10, 12345, 5, 0 }, + { W("Z"), 10, 0, 0, 0 }, + { W(""), 10, 0, 0, 0 }, + { W("4294967295"), 10, UINT32_MAX, 10, 0 }, + { W("4294967296"), 10, UINT32_MAX, 10, ERANGE }, + // Beyond 64 bits as well + { W("99999999999999999999"), 10, UINT32_MAX, 20, ERANGE }, + { W("-1"), 10, UINT32_MAX, 2, 0 }, + { W("-4"), 10, 0xFFFFFFFC, 2, 0 }, +#if ULONG_MAX == UINT32_MAX + { W("-4294967296"), 10, UINT32_MAX, 11, ERANGE }, +#else + // Negative values are truncated to 32 bits where unsigned long is 64-bit, like the PAL wcstoul did + { W("-4294967296"), 10, 0, 11, 0 }, + { W("-4294967297"), 10, UINT32_MAX, 11, 0 }, +#endif + { W("0x12"), 16, 0x12, 4, 0 }, + { W("0x12"), 10, 0, 1, 0 }, + { W("012"), 8, 10, 3, 0 }, + { W("012"), 10, 12, 3, 0 }, + { W(" \t42 "), 10, 42, 4, 0 }, + { W("+7"), 10, 7, 2, 0 }, + { W("12\x00E9" "3"), 10, 12, 2, 0 }, +}; + +static RESULT test_u16_strtoul(void) +{ + for (size_t i = 0; i < ARRAY_SIZE(strtoul_cases); i++) + { + const StrToULCase* c = &strtoul_cases[i]; + WCHAR* end; + errno = ERRNO_SENTINEL; + uint32_t value = u16_strtoul(c->str, &end, c->base); + int error = errno == ERRNO_SENTINEL ? 0 : errno; + + if (value != c->value) + return FAILED("u16_strtoul case %zu returned %u instead of %u", i, value, c->value); + + if (end != c->str + c->stop) + return FAILED("u16_strtoul case %zu stopped at %td instead of %zu", i, end - c->str, c->stop); + + if (error != c->error) + return FAILED("u16_strtoul case %zu set errno to %d instead of %d", i, error, c->error); + } + + if (u16_strtoul(W("123"), NULL, 10) != 123) + return FAILED("u16_strtoul didn't accept a null end pointer"); + + return OK; +} + +typedef struct +{ + const WCHAR* str; + int base; + uint64_t value; + size_t stop; + int error; +} StrToUI64Case; + +static const StrToUI64Case strtoui64_cases[] = +{ + { W("12345"), 10, 12345, 5, 0 }, + { W("Z"), 10, 0, 0, 0 }, + { W("4294967296"), 10, 4294967296ull, 10, 0 }, + { W("18446744073709551615"), 10, UINT64_MAX, 20, 0 }, + { W("18446744073709551616"), 10, UINT64_MAX, 20, ERANGE }, + { W("-1"), 10, UINT64_MAX, 2, 0 }, + { W("ffffffffff"), 16, 0xffffffffffull, 10, 0 }, + { W(" 123abc"), 10, 123, 5, 0 }, +}; + +static RESULT test_u16_strtoui64(void) +{ + for (size_t i = 0; i < ARRAY_SIZE(strtoui64_cases); i++) + { + const StrToUI64Case* c = &strtoui64_cases[i]; + WCHAR* end; + errno = ERRNO_SENTINEL; + uint64_t value = u16_strtoui64(c->str, &end, c->base); + int error = errno == ERRNO_SENTINEL ? 0 : errno; + + if (value != c->value) + return FAILED("u16_strtoui64 case %zu returned %llu instead of %llu", i, (unsigned long long)value, (unsigned long long)c->value); + + if (end != c->str + c->stop) + return FAILED("u16_strtoui64 case %zu stopped at %td instead of %zu", i, end - c->str, c->stop); + + if (error != c->error) + return FAILED("u16_strtoui64 case %zu set errno to %d instead of %d", i, error, c->error); + } + + return OK; +} + +typedef struct +{ + const WCHAR* str; + double value; + size_t stop; +} StrToDCase; + +static const StrToDCase strtod_cases[] = +{ + { W("1234"), 1234, 4 }, + { W("-1234"), -1234, 5 }, + { W("1234.44"), 1234.44, 7 }, + { W("1234e-5"), 1234e-5, 7 }, + { W("1234e+5"), 1234e+5, 7 }, + { W("1234E5"), 1234E5, 6 }, + { W("1234.657e-8"), 1234.657e-8, 11 }, + { W("1e-800"), 0, 6 }, + { W("-1e-800"), 0, 7 }, + { W(" 1234567e-8 foo"), 1234567e-8, 13 }, + { W(" foo 32 bar"), 0, 0 }, + { W(" -1b "), -1, 4 }, + { W(""), 0, 0 }, + { W("12\x00E9"), 12, 2 }, +#ifdef _WIN32 + { W("1.5e"), 1.5, 3 }, + { W("1.5e+"), 1.5, 3 }, +#else + // The PAL wcstod skipped past everything that may be part of a number, even an incomplete exponent + { W("1.5e"), 1.5, 4 }, + { W("1.5e+"), 1.5, 5 }, + // and only accepted decimal notation + { W("inf"), 0, 0 }, + { W("0x10"), 0, 1 }, +#endif +}; + +static RESULT test_u16_strtod(void) +{ + for (size_t i = 0; i < ARRAY_SIZE(strtod_cases); i++) + { + const StrToDCase* c = &strtod_cases[i]; + WCHAR* end; + double value = u16_strtod(c->str, &end); + + if (value != c->value) + return FAILED("u16_strtod case %zu returned %g instead of %g", i, value, c->value); + + if (end != c->str + c->stop) + return FAILED("u16_strtod case %zu stopped at %td instead of %zu", i, end - c->str, c->stop); + } + + if (u16_strtod(W("1E+10000"), NULL) != HUGE_VAL) + return FAILED("u16_strtod(\"1E+10000\") isn't infinity"); + + if (u16_strtod(W("-1E+10000"), NULL) != -HUGE_VAL) + return FAILED("u16_strtod(\"-1E+10000\") isn't negative infinity"); + + return OK; +} + +static Test minipal_u16_tests[] = +{ + {"test_u16_strlen", test_u16_strlen}, + {"test_u16_strcmp", test_u16_strcmp}, + {"test_u16_strncmp", test_u16_strncmp}, + {"test_u16_stricmp", test_u16_stricmp}, + {"test_u16_strnicmp", test_u16_strnicmp}, + {"test_u16_strchr", test_u16_strchr}, + {"test_u16_strrchr", test_u16_strrchr}, + {"test_u16_strstr", test_u16_strstr}, + {"test_u16_strcpy_s", test_u16_strcpy_s}, + {"test_u16_strcat_s", test_u16_strcat_s}, + {"test_u16_strncpy_s", test_u16_strncpy_s}, + {"test_u16_strtoul", test_u16_strtoul}, + {"test_u16_strtoui64", test_u16_strtoui64}, + {"test_u16_strtod", test_u16_strtod}, + {NULL, NULL} +}; + +extern "C" DEFINE_TEST_GROUP_INIT(minipal_u16_tests_init, minipal_u16_tests) From c9a1983aab9b48cbd127b3612df82c9681f78233 Mon Sep 17 00:00:00 2001 From: am11 <3840695+am11@users.noreply.github.com> Date: Mon, 9 Nov 2026 00:55:55 +0200 Subject: [PATCH 3/4] Address feedback * Use minipal_u16_strlen in the LTTng event provider helpers. * Don't route u16_strcmp and u16_stricmp through the bounded variants. * Pass all leading ASCII characters to strtod, like to strtoul and strtoull, which makes u16_strtod match the Windows wcstod. * Fix the u16_strtoul comment. Co-authored-by: Cursor --- src/coreclr/minipal/Unix/dn-u16.cpp | 72 ++++++++----------- .../lttngprovider/eventproviderhelpers.cpp | 8 +-- src/tests/minipal/u16-tests.cpp | 11 +-- 3 files changed, 35 insertions(+), 56 deletions(-) diff --git a/src/coreclr/minipal/Unix/dn-u16.cpp b/src/coreclr/minipal/Unix/dn-u16.cpp index ffe7d93f408445..2fd2a2f8614da6 100644 --- a/src/coreclr/minipal/Unix/dn-u16.cpp +++ b/src/coreclr/minipal/Unix/dn-u16.cpp @@ -19,7 +19,13 @@ size_t u16_strlen(const WCHAR* str) int u16_strcmp(const WCHAR* str1, const WCHAR* str2) { - return u16_strncmp(str1, str2, 0x7fffffff); + int diff; + while ((diff = *str1 - *str2) == 0 && *str1 != (WCHAR)'\0') + { + str1++; + str2++; + } + return diff; } int u16_strncmp(const WCHAR* str1, const WCHAR* str2, size_t count) @@ -40,7 +46,13 @@ int u16_strncmp(const WCHAR* str1, const WCHAR* str2, size_t count) int u16_stricmp(const WCHAR* str1, const WCHAR* str2) { - return u16_strnicmp(str1, str2, 0x7fffffff); + int diff; + while ((diff = (int)towlower(*str1) - (int)towlower(*str2)) == 0 && *str1 != (WCHAR)'\0') + { + str1++; + str2++; + } + return diff; } int u16_strnicmp(const WCHAR* str1, const WCHAR* str2, size_t count) @@ -198,23 +210,12 @@ const WCHAR* u16_strrchr(const WCHAR* str, WCHAR ch) return last; } -static bool is_ascii(WCHAR ch) -{ - return ch < 0x80; -} - -static bool is_floating_point_char(WCHAR ch) -{ - return ch == '+' || ch == '-' || ch == '.' || (ch >= '0' && ch <= '9') || - ch == 'e' || ch == 'E' || ch == 'd' || ch == 'D'; -} - -// Narrows the leading characters of str that satisfy the predicate into a malloc-ed buffer. -// The characters are ASCII, so offsets into the buffer are also offsets into str. -static char* narrow_prefix(const WCHAR* str, bool (*predicate)(WCHAR)) +// Narrows the leading ASCII characters of str into a malloc-ed buffer. Numbers consist of ASCII +// characters only, so offsets into the buffer are also offsets into str. +static char* narrow_ascii_prefix(const WCHAR* str) { size_t length = 0; - while (str[length] != (WCHAR)'\0' && predicate(str[length])) + while (str[length] != (WCHAR)'\0' && str[length] < 0x80) length++; char* buffer = (char*)malloc(length + 1); @@ -230,7 +231,7 @@ static char* narrow_prefix(const WCHAR* str, bool (*predicate)(WCHAR)) uint32_t u16_strtoul(const WCHAR* nptr, WCHAR** endptr, int base) { - char* buffer = narrow_prefix(nptr, is_ascii); + char* buffer = narrow_ascii_prefix(nptr); if (buffer == nullptr) { if (endptr != nullptr) @@ -242,8 +243,8 @@ uint32_t u16_strtoul(const WCHAR* nptr, WCHAR** endptr, int base) unsigned long value = strtoul(buffer, &end, base); #if ULONG_MAX > UINT32_MAX - // Windows' unsigned long is 32-bit, so positive values that don't fit in it saturate. - // Negative values are truncated instead, regardless of their magnitude. + // The result is 32-bit like on Windows, where unsigned long is 32-bit. Positive values + // that don't fit saturate, negative values are truncated regardless of their magnitude. if (value > UINT32_MAX) { const char* p = buffer; @@ -267,7 +268,7 @@ uint32_t u16_strtoul(const WCHAR* nptr, WCHAR** endptr, int base) uint64_t u16_strtoui64(const WCHAR* nptr, WCHAR** endptr, int base) { - char* buffer = narrow_prefix(nptr, is_ascii); + char* buffer = narrow_ascii_prefix(nptr); if (buffer == nullptr) { if (endptr != nullptr) @@ -285,32 +286,21 @@ uint64_t u16_strtoui64(const WCHAR* nptr, WCHAR** endptr, int base) return value; } -// Only decimal notation is accepted; the C runtime strtod would also accept hex, "inf" and "nan". -// The end pointer is set past all the characters that can be part of a decimal number, even -// the ones strtod didn't consume, e.g. past the "e" of "1.5e". double u16_strtod(const WCHAR* nptr, WCHAR** endptr) { - if (nptr == nullptr) - return 0.0; - - const WCHAR* start = nptr; - while (iswspace(*start)) - start++; - - double value = 0.0; - const WCHAR* stop = nptr; - - char* buffer = narrow_prefix(start, is_floating_point_char); - if (buffer != nullptr && buffer[0] != '\0') + char* buffer = narrow_ascii_prefix(nptr); + if (buffer == nullptr) { - char* end; - value = strtod(buffer, &end); - if (value != 0.0 || end != buffer) - stop = start + strlen(buffer); + if (endptr != nullptr) + *endptr = (WCHAR*)nptr; + return 0.0; } + char* end; + double value = strtod(buffer, &end); + if (endptr != nullptr) - *endptr = (WCHAR*)stop; + *endptr = (WCHAR*)nptr + (end - buffer); free(buffer); return value; diff --git a/src/coreclr/pal/src/eventprovider/lttngprovider/eventproviderhelpers.cpp b/src/coreclr/pal/src/eventprovider/lttngprovider/eventproviderhelpers.cpp index 1b807b55a31a50..08be1c2b64261b 100644 --- a/src/coreclr/pal/src/eventprovider/lttngprovider/eventproviderhelpers.cpp +++ b/src/coreclr/pal/src/eventprovider/lttngprovider/eventproviderhelpers.cpp @@ -8,6 +8,7 @@ #include "pal_error.h" #include #include +#include bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, bool &fixedBuffer) { @@ -53,12 +54,7 @@ bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, s bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer) { if(!str) return true; - size_t length = 0; - while (str[length] != '\0') - { - length++; - } - size_t byteCount = (length + 1) * sizeof(*str); + size_t byteCount = (minipal_u16_strlen((const CHAR16_T*)str) + 1) * sizeof(*str); if (offset + byteCount > size) { diff --git a/src/tests/minipal/u16-tests.cpp b/src/tests/minipal/u16-tests.cpp index 7f5ff6bb0df071..1aef616e8b8fb9 100644 --- a/src/tests/minipal/u16-tests.cpp +++ b/src/tests/minipal/u16-tests.cpp @@ -362,17 +362,10 @@ static const StrToDCase strtod_cases[] = { W(" -1b "), -1, 4 }, { W(""), 0, 0 }, { W("12\x00E9"), 12, 2 }, -#ifdef _WIN32 { W("1.5e"), 1.5, 3 }, { W("1.5e+"), 1.5, 3 }, -#else - // The PAL wcstod skipped past everything that may be part of a number, even an incomplete exponent - { W("1.5e"), 1.5, 4 }, - { W("1.5e+"), 1.5, 5 }, - // and only accepted decimal notation - { W("inf"), 0, 0 }, - { W("0x10"), 0, 1 }, -#endif + { W("inf"), HUGE_VAL, 3 }, + { W("0x10"), 16, 4 }, }; static RESULT test_u16_strtod(void) From ccce5a75a10c19912b8f43ee33c3b74d0e7a61e6 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Mon, 9 Nov 2026 02:41:31 +0200 Subject: [PATCH 4/4] Implement overflow check for WCHAR length Add overflow check for WCHAR buffer allocation Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/coreclr/inc/corhlprpriv.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/coreclr/inc/corhlprpriv.h b/src/coreclr/inc/corhlprpriv.h index cc42e7453f9783..7a7ab1c490cc60 100644 --- a/src/coreclr/inc/corhlprpriv.h +++ b/src/coreclr/inc/corhlprpriv.h @@ -286,6 +286,11 @@ class CQuickMemoryBase ThrowHR(HRESULT_FROM_WIN32(errno)); } + if (length > SIZE_MAX / sizeof(WCHAR)) + { + ThrowHR(COR_E_OVERFLOW); + } + CHAR16_T* buffer = (CHAR16_T*) AllocThrows(length * sizeof(WCHAR)); if (minipal_convert_utf8_to_utf16(utf8str, sourceLength, buffer, length, 0) == 0)