summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--clr.coreclr.props5
-rw-r--r--cross/arm/tryrun.cmake4
-rw-r--r--cross/arm64/tryrun.cmake4
-rw-r--r--src/binder/assemblybinder.cpp15
-rw-r--r--src/binder/assemblyname.cpp6
-rw-r--r--src/binder/cdebuglog.cpp11
-rw-r--r--src/binder/debuglog.cpp1
-rw-r--r--src/binder/inc/assemblyname.hpp2
-rw-r--r--src/binder/inc/bindertypes.hpp2
-rw-r--r--src/binder/utils.cpp46
-rw-r--r--src/classlibnative/bcltype/system.cpp34
-rw-r--r--src/corefx/System.Globalization.Native/CMakeLists.txt1
-rw-r--r--src/corefx/System.Globalization.Native/collation.cpp269
-rw-r--r--src/debug/ee/debugger.cpp4
-rw-r--r--src/debug/shim/debugshim.cpp4
-rw-r--r--src/dlls/mscoree/mscoree.cpp104
-rw-r--r--src/dlls/mscoree/mscorwks_unixexports.src2
-rw-r--r--src/inc/bbsweep.h4
-rw-r--r--src/inc/clr/fs/path.h2
-rw-r--r--src/inc/clrconfigvalues.h1
-rw-r--r--src/inc/corinfo.h2
-rw-r--r--src/inc/dlwrap.h1
-rw-r--r--src/inc/downlevel.h15
-rw-r--r--src/inc/eventtracebase.h2
-rw-r--r--src/inc/formattype.cpp2
-rw-r--r--src/inc/newapis.h2
-rw-r--r--src/inc/palclr.h1
-rw-r--r--src/inc/sbuffer.h4
-rw-r--r--src/inc/sstring.h9
-rw-r--r--src/inc/stgpool.h4
-rw-r--r--src/inc/sxshelpers.h2
-rw-r--r--src/inc/utilcode.h2
-rw-r--r--src/inc/winrt/windowsstring.h2
-rw-r--r--src/jit/codegenxarch.cpp7
-rw-r--r--src/md/compressedinteger.h2
-rw-r--r--src/md/datablob.h26
-rw-r--r--src/md/datablob.inl9
-rw-r--r--src/md/heaps/blobheap.h2
-rw-r--r--src/md/hotdata/hotheap.h2
-rw-r--r--src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs35
-rw-r--r--src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs173
-rw-r--r--src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs7
-rw-r--r--src/mscorlib/corefx/System/Globalization/TextInfo.cs8
-rw-r--r--src/mscorlib/model.xml2
-rw-r--r--src/mscorlib/mscorlib.shared.sources.props1
-rw-r--r--src/mscorlib/src/System/Collections/Hashtable.cs17
-rw-r--r--src/mscorlib/src/System/Decimal.cs6
-rw-r--r--src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs24
-rw-r--r--src/mscorlib/src/System/String.cs6
-rw-r--r--src/mscorlib/src/System/StringComparer.cs6
-rw-r--r--src/mscorlib/src/System/Threading/ExecutionContext.cs41
-rw-r--r--src/pal/inc/pal.h21
-rw-r--r--src/pal/inc/rt/palrt.h2
-rw-r--r--src/pal/src/CMakeLists.txt2
-rw-r--r--src/pal/src/config.h.in1
-rw-r--r--src/pal/src/configure.cmake16
-rw-r--r--src/pal/src/cruntime/malloc.cpp5
-rw-r--r--src/pal/src/cruntime/wchar.cpp2
-rw-r--r--src/pal/src/exception/seh-unwind.cpp34
-rw-r--r--src/pal/src/include/pal/thread.hpp23
-rw-r--r--src/pal/src/loader/module.cpp405
-rw-r--r--src/pal/src/memory/heap.cpp138
-rw-r--r--src/pal/src/misc/perftrace.cpp2
-rw-r--r--src/pal/src/misc/stackstring.cpp138
-rw-r--r--src/pal/src/thread/thread.cpp117
-rw-r--r--src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.c6
-rw-r--r--src/tools/crossgen/crossgen.cpp18
-rw-r--r--src/utilcode/dlwrap.cpp1
-rw-r--r--src/utilcode/downlevel.cpp1
-rw-r--r--src/utilcode/posterror.cpp2
-rw-r--r--src/utilcode/registrywrapper.cpp2
-rw-r--r--src/utilcode/regutil.cpp4
-rw-r--r--src/utilcode/securitywrapper.cpp3
-rw-r--r--src/utilcode/sortversioning.cpp1
-rw-r--r--src/utilcode/util.cpp2
-rw-r--r--src/utilcode/util_nodependencies.cpp2
-rw-r--r--src/utilcode/utilmessagebox.cpp5
-rw-r--r--src/vm/CMakeLists.txt2
-rw-r--r--src/vm/appdomain.cpp7
-rw-r--r--src/vm/assemblynative.cpp17
-rw-r--r--src/vm/assemblynative.hpp1
-rw-r--r--src/vm/assemblynativeresource.cpp4
-rw-r--r--src/vm/callingconvention.h1
-rw-r--r--src/vm/ceeload.cpp2
-rw-r--r--src/vm/clrprivbinderfusion.cpp2
-rw-r--r--src/vm/clrprivbinderwinrt.cpp2
-rw-r--r--src/vm/comdynamic.cpp2
-rw-r--r--src/vm/comisolatedstorage.cpp2
-rw-r--r--src/vm/compile.cpp6
-rw-r--r--src/vm/comutilnative.cpp27
-rw-r--r--src/vm/comutilnative.h7
-rw-r--r--src/vm/dllimport.cpp80
-rw-r--r--src/vm/dllimport.h5
-rw-r--r--src/vm/dwbucketmanager.hpp2
-rw-r--r--src/vm/ecalllist.h11
-rw-r--r--src/vm/excep.cpp29
-rw-r--r--src/vm/interoputil.h4
-rw-r--r--src/vm/jitinterface.h2
-rw-r--r--src/vm/mdaassistants.cpp6
-rw-r--r--src/vm/profilermetadataemitvalidator.h27
-rw-r--r--src/vm/securitymeta.cpp2
-rw-r--r--src/vm/stubhelpers.h2
-rw-r--r--src/vm/tlbexport.cpp8
-rw-r--r--src/vm/util.cpp2
-rw-r--r--src/vm/wrappers.h2
-rw-r--r--src/zap/zapinfo.h2
-rw-r--r--tests/buildtest.cmd23
-rw-r--r--tests/runtest.cmd24
-rw-r--r--tests/runtest.proj8
-rwxr-xr-x[-rw-r--r--]tests/runtest.sh647
-rw-r--r--tests/src/CLRTest.Execute.Bash.targets26
-rw-r--r--tests/src/CLRTest.Execute.Batch.targets2
-rw-r--r--tests/src/managed/Compilation/Compilation.cs4
-rw-r--r--tests/testsFailingOutsideWindows.txt76
-rw-r--r--tests/testsUnsupportedOutsideWindows.txt11
116 files changed, 2188 insertions, 799 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 543e4ffb23..610e929d33 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -573,9 +573,7 @@ add_definitions(-DFEATURE_MERGE_JIT_AND_ENGINE)
endif(WIN32)
add_definitions(-DFEATURE_NORM_IDNA_ONLY)
add_definitions(-DFEATURE_PREJIT)
-if(WIN32)
- add_definitions(-DFEATURE_RANDOMIZED_STRING_HASHING)
-endif(WIN32)
+add_definitions(-DFEATURE_RANDOMIZED_STRING_HASHING)
add_definitions(-DFEATURE_READYTORUN)
add_definitions(-DFEATURE_STANDALONE_SN)
add_definitions(-DFEATURE_STRONGNAME_DELAY_SIGNING_ALLOWED)
diff --git a/clr.coreclr.props b/clr.coreclr.props
index b47de7b48f..819fd6f829 100644
--- a/clr.coreclr.props
+++ b/clr.coreclr.props
@@ -101,9 +101,6 @@
<ProfilingSupportedBuild>false</ProfilingSupportedBuild>
- <!-- UNIXTODO Enable randomized string hashing -->
- <FeatureRandomizedStringHashing>false</FeatureRandomizedStringHashing>
-
<!-- Windows specific features -->
<FeatureWin32Registry>false</FeatureWin32Registry>
<FeatureAppX>false</FeatureAppX>
@@ -125,4 +122,4 @@
<FeatureCoreFxGlobalization>true</FeatureCoreFxGlobalization>
</PropertyGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/cross/arm/tryrun.cmake b/cross/arm/tryrun.cmake
index bd84ad75b0..0a6d34d44d 100644
--- a/cross/arm/tryrun.cmake
+++ b/cross/arm/tryrun.cmake
@@ -90,10 +90,6 @@ SET( UNGETC_NOT_RETURN_EOF_EXITCODE
0
CACHE STRING "Result from TRY_RUN" FORCE)
-SET( MALLOC_ZERO_RETURNS_NULL_EXITCODE
- 1
- CACHE STRING "Result from TRY_RUN" FORCE)
-
SET( HAS_POSIX_SEMAPHORES_EXITCODE
0
CACHE STRING "Result from TRY_RUN" FORCE)
diff --git a/cross/arm64/tryrun.cmake b/cross/arm64/tryrun.cmake
index bd84ad75b0..0a6d34d44d 100644
--- a/cross/arm64/tryrun.cmake
+++ b/cross/arm64/tryrun.cmake
@@ -90,10 +90,6 @@ SET( UNGETC_NOT_RETURN_EOF_EXITCODE
0
CACHE STRING "Result from TRY_RUN" FORCE)
-SET( MALLOC_ZERO_RETURNS_NULL_EXITCODE
- 1
- CACHE STRING "Result from TRY_RUN" FORCE)
-
SET( HAS_POSIX_SEMAPHORES_EXITCODE
0
CACHE STRING "Result from TRY_RUN" FORCE)
diff --git a/src/binder/assemblybinder.cpp b/src/binder/assemblybinder.cpp
index 3dc1d73e96..ecd34499af 100644
--- a/src/binder/assemblybinder.cpp
+++ b/src/binder/assemblybinder.cpp
@@ -164,7 +164,7 @@ namespace BINDER_SPACE
}
else
{
- PathString fullAssemblyPath;
+ SString fullAssemblyPath;
WCHAR *pwzFullAssemblyPath = fullAssemblyPath.OpenUnicodeBuffer(MAX_LONGPATH);
DWORD dwCCFullAssemblyPath = MAX_LONGPATH + 1; // SString allocates extra byte for null.
@@ -184,9 +184,6 @@ namespace BINDER_SPACE
{
assemblyPath.Set(fullAssemblyPath);
}
-
- // Now turn this path into our canonical representation
- CanonicalizePath(assemblyPath);
}
return hr;
@@ -1228,17 +1225,9 @@ namespace BINDER_SPACE
#ifdef FEATURE_LEGACYNETCF
fWindowsPhone7 = RuntimeIsLegacyNetCF(pApplicationContext->GetAppDomainId()) == TRUE;
#endif
- //
- // Windows Phone 7 Quirk:
- //
- // NetCF allows partial binds to platform assemblies. If we are running a
- // Mango application, skip the PKT check if no Ref version is provided,
- // since there are apps in the Marketplace that do Assembly.Load("System")
- //
+
if (!tpaListAssembly || (fWindowsPhone7 && tpaListAssembly))
{
- dwIncludeFlags |= AssemblyName::EXCLUDE_PUBLIC_KEY_TOKEN_IF_MISSING;
-
//
// On Windows Phone 7, exclude culture comparisons when requesting an uncultured
// assembly for app compat reasons (there are main app assemblies with spurious cultures)
diff --git a/src/binder/assemblyname.cpp b/src/binder/assemblyname.cpp
index f65363de63..a1897e409d 100644
--- a/src/binder/assemblyname.cpp
+++ b/src/binder/assemblyname.cpp
@@ -568,10 +568,10 @@ Exit:
{
fEquals = EqualsCaseInsensitive(GetNormalizedCulture(), pAssemblyName->GetNormalizedCulture());
}
- if (fEquals && ((dwIncludeFlags & EXCLUDE_PUBLIC_KEY_TOKEN_IF_MISSING) == 0 ||
- (pAssemblyName->Have(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN))))
+
+ if (fEquals && (dwIncludeFlags & INCLUDE_PUBLIC_KEY_TOKEN) != 0)
{
- fEquals = (GetPublicKeyTokenBLOB().Equals(pAssemblyName->GetPublicKeyTokenBLOB()));
+ fEquals = (GetPublicKeyTokenBLOB().Equals(pAssemblyName->GetPublicKeyTokenBLOB()));
}
if (fEquals && ((dwIncludeFlags & INCLUDE_ARCHITECTURE) != 0))
diff --git a/src/binder/cdebuglog.cpp b/src/binder/cdebuglog.cpp
index 717fbd2ef9..329d54fcae 100644
--- a/src/binder/cdebuglog.cpp
+++ b/src/binder/cdebuglog.cpp
@@ -56,7 +56,7 @@ namespace BINDER_SPACE
{
HRESULT hr=S_OK;
LPTSTR pszFileName;
- TCHAR szPath[MAX_LONGPATH];
+ PathString szPathString;
DWORD dw = 0;
// _ASSERTE (pszPath ) ;
@@ -65,8 +65,12 @@ namespace BINDER_SPACE
IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW));
}
- IF_FAIL_GO(StringCbCopy(szPath, sizeof(szPath), pszName));
-
+ size_t pszNameLen = wcslen(pszName);
+ WCHAR * szPath = szPathString.OpenUnicodeBuffer(static_cast<COUNT_T>(pszNameLen));
+ size_t cbSzPath = (sizeof(WCHAR)) * (pszNameLen + 1); // SString allocates extra byte for null
+ IF_FAIL_GO(StringCbCopy(szPath, cbSzPath, pszName));
+ szPathString.CloseBuffer(static_cast<COUNT_T>(pszNameLen));
+
pszFileName = PathFindFileName(szPath);
if (pszFileName <= szPath)
@@ -330,7 +334,6 @@ namespace BINDER_SPACE
CombinePath(g_BinderVariables->logPath, sCategory, logFilePath);
CombinePath(logFilePath, m_applicationName, logFilePath);
CombinePath(logFilePath, m_logFileName, logFilePath);
- CanonicalizePath(logFilePath);
BINDER_LOG_STRING(L"logFilePath", logFilePath);
diff --git a/src/binder/debuglog.cpp b/src/binder/debuglog.cpp
index 4f82b7bed9..2c4fd41bfd 100644
--- a/src/binder/debuglog.cpp
+++ b/src/binder/debuglog.cpp
@@ -90,7 +90,6 @@ namespace BINDER_SPACE
kCount2.u.HighPart);
PlatformPath(logFilePath);
- CanonicalizePath(logFilePath);
}
fFileExists = (FileOrDirectoryExists(logFilePath) == S_OK);
diff --git a/src/binder/inc/assemblyname.hpp b/src/binder/inc/assemblyname.hpp
index ac648586e3..474500bc75 100644
--- a/src/binder/inc/assemblyname.hpp
+++ b/src/binder/inc/assemblyname.hpp
@@ -31,7 +31,7 @@ namespace BINDER_SPACE
INCLUDE_ARCHITECTURE = 0x02,
INCLUDE_RETARGETABLE = 0x04,
INCLUDE_CONTENT_TYPE = 0x08,
- EXCLUDE_PUBLIC_KEY_TOKEN_IF_MISSING = 0x10,
+ INCLUDE_PUBLIC_KEY_TOKEN = 0x10,
EXCLUDE_CULTURE = 0x20
} INCLUDE_FLAGS;
diff --git a/src/binder/inc/bindertypes.hpp b/src/binder/inc/bindertypes.hpp
index 3c4bed4514..6fc4574e0f 100644
--- a/src/binder/inc/bindertypes.hpp
+++ b/src/binder/inc/bindertypes.hpp
@@ -32,8 +32,6 @@ class PEAssembly;
namespace BINDER_SPACE
{
- typedef InlineSString<MAX_LONGPATH + 1> PathString;
-
class AssemblyVersion;
class AssemblyName;
class Assembly;
diff --git a/src/binder/utils.cpp b/src/binder/utils.cpp
index 5befa8d629..a6a506d937 100644
--- a/src/binder/utils.cpp
+++ b/src/binder/utils.cpp
@@ -260,37 +260,6 @@ namespace BINDER_SPACE
BINDER_LOG_LEAVE(W("Utils::PlatformPath"));
}
- void CanonicalizePath(SString &path, BOOL fAppendPathSeparator)
- {
- BINDER_LOG_ENTER(W("Utils::CanonicalizePath"));
- BINDER_LOG_STRING(W("input path"), path);
-
- if (!path.IsEmpty())
- {
- WCHAR wszCanonicalPath[MAX_LONGPATH];
- PlatformPath(path);
-
- // This is also defined in rotor pal
- if (PathCanonicalizeW(wszCanonicalPath, path))
- {
- path.Set(wszCanonicalPath);
- }
-
- if (fAppendPathSeparator)
- {
- SString platformPathSeparator(SString::Literal, GetPlatformPathSeparator());
-
- if (!path.EndsWith(platformPathSeparator))
- {
- path.Append(platformPathSeparator);
- }
- }
- }
-
- BINDER_LOG_STRING(W("canonicalized path"), path);
- BINDER_LOG_LEAVE(W("Utils::CanonicalizePath"));
- }
-
void CombinePath(SString &pathA,
SString &pathB,
SString &combinedPath)
@@ -300,17 +269,16 @@ namespace BINDER_SPACE
BINDER_LOG_STRING(W("path A"), pathA);
BINDER_LOG_STRING(W("path B"), pathB);
- WCHAR tempResultPath[MAX_LONGPATH];
- if (PathCombineW(tempResultPath, pathA, pathB))
- {
- combinedPath.Set(tempResultPath);
- BINDER_LOG_STRING(W("combined path"), tempResultPath);
- }
- else
+ SString platformPathSeparator(SString::Literal, GetPlatformPathSeparator());
+ combinedPath.Set(pathA);
+
+ if (!combinedPath.EndsWith(platformPathSeparator))
{
- combinedPath.Clear();
+ combinedPath.Append(platformPathSeparator);
}
+ combinedPath.Append(pathB);
+
BINDER_LOG_LEAVE(W("Utils::CombinePath"));
}
diff --git a/src/classlibnative/bcltype/system.cpp b/src/classlibnative/bcltype/system.cpp
index d5772b2ef5..3f27e07bd7 100644
--- a/src/classlibnative/bcltype/system.cpp
+++ b/src/classlibnative/bcltype/system.cpp
@@ -24,6 +24,7 @@
#include "classnames.h"
#include "system.h"
#include "string.h"
+#include "sstring.h"
#include "eeconfig.h"
#include "assemblynative.hpp"
#include "generics.h"
@@ -288,34 +289,29 @@ FCIMPL0(StringObject*, SystemNative::_GetModuleFileName)
{
FCALL_CONTRACT;
- WCHAR wszFile[MAX_LONGPATH];
- STRINGREF refRetVal = NULL;
- LPCWSTR pFileName = NULL;
- DWORD lgth = 0;
+ STRINGREF refRetVal = NULL;
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refRetVal);
if (g_pCachedModuleFileName)
{
- pFileName = g_pCachedModuleFileName;
- lgth = (DWORD)wcslen(pFileName);
+ refRetVal = StringObject::NewString(g_pCachedModuleFileName);
}
else
{
- HELPER_METHOD_FRAME_BEGIN_RET_1(refRetVal);
- lgth = WszGetModuleFileName(NULL, wszFile, MAX_LONGPATH);
+ SString wszFilePathString;
+
+ WCHAR * wszFile = wszFilePathString.OpenUnicodeBuffer(MAX_LONGPATH);
+ DWORD lgth = WszGetModuleFileName(NULL, wszFile, MAX_LONGPATH);
if (!lgth)
{
COMPlusThrowWin32();
}
- HELPER_METHOD_FRAME_END();
- pFileName = wszFile;
- }
+ wszFilePathString.CloseBuffer(lgth);
- if(lgth)
- {
- HELPER_METHOD_FRAME_BEGIN_RET_1(refRetVal);
- refRetVal = StringObject::NewString(pFileName, lgth);
- HELPER_METHOD_FRAME_END();
+ refRetVal = StringObject::NewString(wszFilePathString.GetUnicode());
}
+ HELPER_METHOD_FRAME_END();
+
return (StringObject*)OBJECTREFToObject(refRetVal);
}
FCIMPLEND
@@ -347,14 +343,16 @@ FCIMPL0(StringObject*, SystemNative::GetRuntimeDirectory)
{
FCALL_CONTRACT;
- wchar_t wszFile[MAX_LONGPATH+1];
STRINGREF refRetVal = NULL;
DWORD dwFile = MAX_LONGPATH+1;
HELPER_METHOD_FRAME_BEGIN_RET_1(refRetVal);
+ SString wszFilePathString;
+ WCHAR * wszFile = wszFilePathString.OpenUnicodeBuffer(dwFile);
HRESULT hr = GetInternalSystemDirectory(wszFile, &dwFile);
-
+ wszFilePathString.CloseBuffer(dwFile);
+
if(FAILED(hr))
COMPlusThrowHR(hr);
diff --git a/src/corefx/System.Globalization.Native/CMakeLists.txt b/src/corefx/System.Globalization.Native/CMakeLists.txt
index 2660e34045..ecf65f2925 100644
--- a/src/corefx/System.Globalization.Native/CMakeLists.txt
+++ b/src/corefx/System.Globalization.Native/CMakeLists.txt
@@ -32,6 +32,7 @@ add_compile_options(-fPIC)
set(NATIVEGLOBALIZATION_SOURCES
calendarData.cpp
casing.cpp
+ collation.cpp
idna.cpp
locale.cpp
localeNumberData.cpp
diff --git a/src/corefx/System.Globalization.Native/collation.cpp b/src/corefx/System.Globalization.Native/collation.cpp
new file mode 100644
index 0000000000..ab670264e8
--- /dev/null
+++ b/src/corefx/System.Globalization.Native/collation.cpp
@@ -0,0 +1,269 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include <assert.h>
+#include <stdint.h>
+#include <unicode/uchar.h>
+#include <unicode/ucol.h>
+#include <unicode/usearch.h>
+#include <unicode/utf16.h>
+
+const int32_t CompareOptionsIgnoreCase = 1;
+// const int32_t CompareOptionsIgnoreNonSpace = 2;
+// const int32_t CompareOptionsIgnoreSymbols = 4;
+// const int32_t CompareOptionsIgnoreKanaType = 8;
+// const int32_t CompareOptionsIgnoreWidth = 0x10;
+// const int32_t CompareOptionsStringSort = 0x20000000;
+
+/*
+ * To collator returned by this function is owned by the callee and must be closed when this method returns
+ * with a U_SUCCESS UErrorCode.
+ *
+ * On error, the return value is undefined.
+ */
+UCollator* GetCollatorForLocaleAndOptions(const char* lpLocaleName, int32_t options, UErrorCode* pErr)
+{
+ UCollator* pColl = nullptr;
+
+ pColl = ucol_open(lpLocaleName, pErr);
+
+ if ((options & CompareOptionsIgnoreCase) == CompareOptionsIgnoreCase)
+ {
+ ucol_setAttribute(pColl, UCOL_STRENGTH, UCOL_SECONDARY, pErr);
+ }
+
+ return pColl;
+}
+
+
+/*
+Function:
+CompareString
+*/
+extern "C" int32_t CompareString(const char* lpLocaleName, const UChar* lpStr1, int32_t cwStr1Length, const UChar* lpStr2, int32_t cwStr2Length, int32_t options)
+{
+ static_assert(UCOL_EQUAL == 0, "managed side requires 0 for equal strings");
+ static_assert(UCOL_LESS < 0, "managed side requires less than zero for a < b");
+ static_assert(UCOL_GREATER > 0, "managed side requires greater than zero for a > b");
+
+ UCollationResult result = UCOL_EQUAL;
+ UErrorCode err = U_ZERO_ERROR;
+ UCollator* pColl = GetCollatorForLocaleAndOptions(lpLocaleName, options, &err);
+
+ if (U_SUCCESS(err))
+ {
+ result = ucol_strcoll(pColl, lpStr1, cwStr1Length, lpStr2, cwStr2Length);
+ ucol_close(pColl);
+ }
+
+ return result;
+}
+
+/*
+Function:
+IndexOf
+*/
+extern "C" int32_t IndexOf(const char* lpLocaleName, const UChar* lpTarget, const UChar* lpSource, int32_t cwSourceLength, int32_t options)
+{
+ static_assert(USEARCH_DONE == -1, "managed side requires -1 for not found");
+
+ int32_t result = USEARCH_DONE;
+ UErrorCode err = U_ZERO_ERROR;
+ UCollator* pColl = GetCollatorForLocaleAndOptions(lpLocaleName, options, &err);
+
+ if (U_SUCCESS(err))
+ {
+ UStringSearch* pSearch = usearch_openFromCollator(lpTarget, -1, lpSource, cwSourceLength, pColl, nullptr, &err);
+
+ if (U_SUCCESS(err))
+ {
+ result = usearch_first(pSearch, &err);
+ usearch_close(pSearch);
+ }
+
+ ucol_close(pColl);
+ }
+
+ return result;
+}
+
+/*
+Function:
+LastIndexOf
+*/
+extern "C" int32_t LastIndexOf(const char* lpLocaleName, const UChar* lpTarget, const UChar* lpSource, int32_t cwSourceLength, int32_t options)
+{
+ static_assert(USEARCH_DONE == -1, "managed side requires -1 for not found");
+
+ int32_t result = USEARCH_DONE;
+ UErrorCode err = U_ZERO_ERROR;
+ UCollator* pColl = GetCollatorForLocaleAndOptions(lpLocaleName, options, &err);
+
+ if (U_SUCCESS(err))
+ {
+ UStringSearch* pSearch = usearch_openFromCollator(lpTarget, -1, lpSource, cwSourceLength, pColl, nullptr, &err);
+
+ if (U_SUCCESS(err))
+ {
+ result = usearch_last(pSearch, &err);
+ usearch_close(pSearch);
+ }
+
+ ucol_close(pColl);
+ }
+
+ return result;
+}
+
+/*
+ Return value is a "Win32 BOOL" (1 = true, 0 = false)
+ */
+extern "C" int32_t StartsWith(const char* lpLocaleName, const UChar* lpTarget, const UChar* lpSource, int32_t cwSourceLength, int32_t options)
+{
+ int32_t result = FALSE;
+ UErrorCode err = U_ZERO_ERROR;
+ UCollator* pColl = GetCollatorForLocaleAndOptions(lpLocaleName, options, &err);
+
+ if (U_SUCCESS(err))
+ {
+ UStringSearch* pSearch = usearch_openFromCollator(lpTarget, -1, lpSource, cwSourceLength, pColl, nullptr, &err);
+ int32_t idx = USEARCH_DONE;
+
+ if (U_SUCCESS(err))
+ {
+ idx = usearch_first(pSearch, &err);
+
+ if (idx == 0)
+ {
+ result = TRUE;
+ }
+ else
+ {
+ UCollationElements* pCollElem = ucol_openElements(pColl, lpSource, idx, &err);
+
+ if (U_SUCCESS(err))
+ {
+ int32_t curCollElem = UCOL_NULLORDER;
+
+ result = TRUE;
+
+ while((curCollElem = ucol_next(pCollElem, &err)) != UCOL_NULLORDER)
+ {
+ if (curCollElem != 0)
+ {
+ // Non ignorable collation element found between start of the string and the first match for lpTarget.
+ result = FALSE;
+ break;
+ }
+ }
+
+ if (U_FAILURE(err))
+ {
+ result = FALSE;
+ }
+
+ ucol_closeElements(pCollElem);
+ }
+ }
+
+ usearch_close(pSearch);
+ }
+
+ ucol_close(pColl);
+ }
+
+ return result;
+}
+
+/*
+ Return value is a "Win32 BOOL" (1 = true, 0 = false)
+ */
+extern "C" int32_t EndsWith(const char* lpLocaleName, const UChar* lpTarget, const UChar* lpSource, int32_t cwSourceLength, int32_t options)
+{
+ int32_t result = FALSE;
+ UErrorCode err = U_ZERO_ERROR;
+ UCollator* pColl = GetCollatorForLocaleAndOptions(lpLocaleName, options, &err);
+
+ if (U_SUCCESS(err))
+ {
+ UStringSearch* pSearch = usearch_openFromCollator(lpTarget, -1, lpSource, cwSourceLength, pColl, nullptr, &err);
+ int32_t idx = USEARCH_DONE;
+
+ if (U_SUCCESS(err))
+ {
+ idx = usearch_last(pSearch, &err);
+
+ if (idx != USEARCH_DONE)
+ {
+ if ((idx + usearch_getMatchedLength(pSearch)) == cwSourceLength)
+ {
+ result = TRUE;
+ }
+
+ // TODO (dotnet/corefx#3467): We should do something similar to what StartsWith does where we can ignore
+ // some collation elements at the end of te string if they are zero.
+ }
+
+ usearch_close(pSearch);
+ }
+
+ ucol_close(pColl);
+ }
+
+ return result;
+}
+
+extern "C" int32_t GetSortKey(const char* lpLocaleName, const UChar* lpStr, int32_t cwStrLength, uint8_t* sortKey, int32_t cbSortKeyLength, int32_t options)
+{
+ UErrorCode err = U_ZERO_ERROR;
+ UCollator* pColl = GetCollatorForLocaleAndOptions(lpLocaleName, options, &err);
+ int32_t result = 0;
+
+ if (U_SUCCESS(err))
+ {
+ result = ucol_getSortKey(pColl, lpStr, cwStrLength, sortKey, cbSortKeyLength);
+
+ ucol_close(pColl);
+ }
+
+ return result;
+}
+
+extern "C" int32_t CompareStringOrdinalIgnoreCase(const UChar* lpStr1, int32_t cwStr1Length, const UChar* lpStr2, int32_t cwStr2Length)
+{
+ assert(lpStr1 != nullptr);
+ assert(cwStr1Length >= 0);
+ assert(lpStr2 != nullptr);
+ assert(cwStr2Length >= 0);
+
+ int32_t str1Idx = 0;
+ int32_t str2Idx = 0;
+
+ while (str1Idx < cwStr1Length && str2Idx < cwStr2Length)
+ {
+ UChar32 str1Codepoint;
+ UChar32 str2Codepoint;
+
+ U16_NEXT(lpStr1, str1Idx, cwStr1Length, str1Codepoint);
+ U16_NEXT(lpStr2, str2Idx, cwStr2Length, str2Codepoint);
+
+ if (str1Codepoint != str2Codepoint && u_toupper(str1Codepoint) != u_toupper(str2Codepoint))
+ {
+ return str1Codepoint < str2Codepoint ? -1 : 1;
+ }
+ }
+
+ if (cwStr1Length < cwStr2Length)
+ {
+ return -1;
+ }
+
+ if (cwStr2Length < cwStr1Length)
+ {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/src/debug/ee/debugger.cpp b/src/debug/ee/debugger.cpp
index 029c62aabe..270615bc1e 100644
--- a/src/debug/ee/debugger.cpp
+++ b/src/debug/ee/debugger.cpp
@@ -15136,7 +15136,8 @@ HRESULT Debugger::InitAppDomainIPC(void)
} hEnsureCleanup(this);
DWORD dwStrLen = 0;
- WCHAR szExeName[MAX_LONGPATH];
+ SString szExeNamePathString;
+ WCHAR * szExeName = szExeNamePathString.OpenUnicodeBuffer(MAX_LONGPATH);
int i;
// all fields in the object can be zero initialized.
@@ -15188,6 +15189,7 @@ HRESULT Debugger::InitAppDomainIPC(void)
szExeName,
MAX_LONGPATH);
+ szExeNamePathString.CloseBuffer(dwStrLen);
// If we couldn't get the name, then use a nice default.
if (dwStrLen == 0)
{
diff --git a/src/debug/shim/debugshim.cpp b/src/debug/shim/debugshim.cpp
index 2d4e63cad5..55b0b36e24 100644
--- a/src/debug/shim/debugshim.cpp
+++ b/src/debug/shim/debugshim.cpp
@@ -84,10 +84,10 @@ STDMETHODIMP CLRDebuggingImpl::OpenVirtualProcess(
HMODULE hDac = NULL;
DWORD dbiTimestamp;
DWORD dbiSizeOfImage;
- WCHAR dbiName[MAX_PATH_FNAME];
+ WCHAR dbiName[MAX_PATH_FNAME] = {0};
DWORD dacTimestamp;
DWORD dacSizeOfImage;
- WCHAR dacName[MAX_PATH_FNAME];
+ WCHAR dacName[MAX_PATH_FNAME] = {0};
CLR_DEBUGGING_VERSION version;
BOOL versionSupportedByCaller = FALSE;
diff --git a/src/dlls/mscoree/mscoree.cpp b/src/dlls/mscoree/mscoree.cpp
index 0be663e9dc..6a1af6d985 100644
--- a/src/dlls/mscoree/mscoree.cpp
+++ b/src/dlls/mscoree/mscoree.cpp
@@ -792,7 +792,12 @@ BOOL PAL_GetPALDirectory(__out_ecount(cchBuffer) LPWSTR pbuffer,
HRESULT hr = S_OK;
- WCHAR pPath[MAX_LONGPATH];
+ WCHAR * pPath = new (nothrow) WCHAR[MAX_LONGPATH];
+ if (pPath == NULL)
+ {
+ return FALSE;
+ }
+
DWORD dwPath = MAX_LONGPATH;
#ifndef CROSSGEN_COMPILE
@@ -800,6 +805,7 @@ BOOL PAL_GetPALDirectory(__out_ecount(cchBuffer) LPWSTR pbuffer,
#endif
dwPath = WszGetModuleFileName(g_pMSCorEE, pPath, dwPath);
+
if(dwPath == 0)
{
hr = HRESULT_FROM_GetLastErrorNA();
@@ -809,7 +815,9 @@ BOOL PAL_GetPALDirectory(__out_ecount(cchBuffer) LPWSTR pbuffer,
DWORD dwLength;
hr = CopySystemDirectory(pPath, pbuffer, cchBuffer, &dwLength);
}
-
+
+ delete [] pPath;
+
return (hr == S_OK);
}
@@ -1002,7 +1010,6 @@ ErrExit:
// S_OK - Output buffer contains the version string.
// HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) - *pdwLength contains required size of the buffer in
// characters.
-//
STDAPI GetCORVersionInternal(
__out_ecount_z_opt(cchBuffer) LPWSTR pBuffer,
@@ -1115,44 +1122,10 @@ __out_ecount_z_opt(cchBuffer) LPWSTR pBuffer,
}
-
#ifndef CROSSGEN_COMPILE
+#ifndef FEATURE_CORECLR
STDAPI LoadLibraryShimInternal(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll)
{
-#ifdef FEATURE_CORECLR
-
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- PRECONDITION(CheckPointer(szDllName, NULL_OK));
- PRECONDITION(CheckPointer(szVersion, NULL_OK));
- PRECONDITION(CheckPointer(pvReserved, NULL_OK));
- PRECONDITION(CheckPointer(phModDll));
- } CONTRACTL_END;
-
- if (szDllName == NULL)
- return E_POINTER;
-
- HRESULT hr = S_OK;
-
- BEGIN_ENTRYPOINT_NOTHROW;
-
- WCHAR szDllPath[MAX_LONGPATH+1];
-
- if (!PAL_GetPALDirectoryW(szDllPath, MAX_LONGPATH)) {
- IfFailGo(HRESULT_FROM_GetLastError());
- }
- wcsncat_s(szDllPath, MAX_LONGPATH+1, szDllName, MAX_LONGPATH - wcslen(szDllPath));
-
- if ((*phModDll = WszLoadLibrary(szDllPath)) == NULL)
- IfFailGo(HRESULT_FROM_GetLastError());
-
-ErrExit:
- END_ENTRYPOINT_NOTHROW;
- return hr;
-
-#else // FEATURE_CORECLR
-
// Simply forward the call to the ICLRRuntimeInfo implementation.
STATIC_CONTRACT_WRAPPER;
if (g_pCLRRuntime)
@@ -1163,7 +1136,7 @@ ErrExit:
{
// no runtime info, probably loaded directly (e.g. from Fusion)
// just look next to ourselves.
- WCHAR wszPath[MAX_LONGPATH];
+ WCHAR wszPath[MAX_PATH];
DWORD dwLength = WszGetModuleFileName(g_hThisInst, wszPath,NumItems(wszPath));
@@ -1188,15 +1161,12 @@ ErrExit:
}
return S_OK;
}
-
-#endif // FEATURE_CORECLR
-
}
-
-#endif // CROSSGEN_COMPILE
+#endif
+#endif
static DWORD g_dwSystemDirectory = 0;
-static WCHAR g_pSystemDirectory[MAX_LONGPATH + 1];
+static WCHAR * g_pSystemDirectory = NULL;
HRESULT GetInternalSystemDirectory(__out_ecount_part_opt(*pdwLength,*pdwLength) LPWSTR buffer, __inout DWORD* pdwLength)
{
@@ -1263,17 +1233,30 @@ HRESULT SetInternalSystemDirectory()
DWORD len;
// use local buffer for thread safety
- WCHAR wzSystemDirectory[COUNTOF(g_pSystemDirectory)];
+ NewArrayHolder<WCHAR> wzSystemDirectory(new (nothrow) WCHAR[MAX_LONGPATH+1]);
+ if (wzSystemDirectory == NULL)
+ {
+ return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
+ }
- hr = GetCORSystemDirectoryInternal(wzSystemDirectory, COUNTOF(wzSystemDirectory), &len);
+ hr = GetCORSystemDirectoryInternal(wzSystemDirectory, MAX_LONGPATH+1, &len);
if(FAILED(hr)) {
- wzSystemDirectory[0] = W('\0');
+ *wzSystemDirectory = W('\0');
len = 1;
}
-
+
+ WCHAR * pSystemDirectory = new (nothrow) WCHAR[len];
+ if (pSystemDirectory == NULL)
+ {
+ return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
+ }
+
+ wcscpy_s(pSystemDirectory, len, wzSystemDirectory);
+
// publish results idempotently with correct memory ordering
- memcpy(g_pSystemDirectory, wzSystemDirectory, len * sizeof(WCHAR));
+ g_pSystemDirectory = pSystemDirectory;
+
(void)InterlockedExchange((LONG *)&g_dwSystemDirectory, len);
}
@@ -1283,10 +1266,21 @@ HRESULT SetInternalSystemDirectory()
#if defined(CROSSGEN_COMPILE) && defined(FEATURE_CORECLR)
void SetMscorlibPath(LPCWSTR wzSystemDirectory)
{
- wcscpy_s(g_pSystemDirectory, COUNTOF(g_pSystemDirectory), wzSystemDirectory);
-
- DWORD len = (DWORD)wcslen(g_pSystemDirectory);
-
+ DWORD len = (DWORD)wcslen(wzSystemDirectory);
+ if (g_dwSystemDirectory < len+1)
+ {
+ delete [] g_pSystemDirectory;
+ g_pSystemDirectory = new (nothrow) WCHAR[len+1];
+
+ if (g_pSystemDirectory == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return;
+ }
+ }
+
+ wcscpy_s(g_pSystemDirectory, len+1, wzSystemDirectory);
+
if(g_pSystemDirectory[len-1] != '\\')
{
g_pSystemDirectory[len] = W('\\');
@@ -1294,6 +1288,8 @@ void SetMscorlibPath(LPCWSTR wzSystemDirectory)
g_dwSystemDirectory = len + 1;
}
else
+ {
g_dwSystemDirectory = len;
+ }
}
#endif
diff --git a/src/dlls/mscoree/mscorwks_unixexports.src b/src/dlls/mscoree/mscorwks_unixexports.src
index fd450304c8..69c140320b 100644
--- a/src/dlls/mscoree/mscorwks_unixexports.src
+++ b/src/dlls/mscoree/mscorwks_unixexports.src
@@ -61,11 +61,13 @@ LockFile
lstrlenA
lstrlenW
MapViewOfFile
+MetaDataGetDispenser
MoveFileExW
MultiByteToWideChar
OpenEventW
OpenMutexW
OpenSemaphoreW
+OutputDebugStringW
PAL_Random
QueryPerformanceCounter
QueryPerformanceFrequency
diff --git a/src/inc/bbsweep.h b/src/inc/bbsweep.h
index 7cebe2000c..f99c36c995 100644
--- a/src/inc/bbsweep.h
+++ b/src/inc/bbsweep.h
@@ -277,8 +277,8 @@ private:
}
#endif // !FEATURE_CORESYSTEM
- WCHAR objectName[MAX_LONGPATH];
- WCHAR objectNamePrefix[MAX_LONGPATH];
+ WCHAR objectName[MAX_LONGPATH] = {0};
+ WCHAR objectNamePrefix[MAX_LONGPATH] = {0};
GetObjectNamePrefix(processID, fromRuntime, objectNamePrefix);
// if there is a non-empty name prefix, append a '\'
if (objectNamePrefix[0] != '\0')
diff --git a/src/inc/clr/fs/path.h b/src/inc/clr/fs/path.h
index 29a70f7260..e90b3188ed 100644
--- a/src/inc/clr/fs/path.h
+++ b/src/inc/clr/fs/path.h
@@ -92,7 +92,7 @@ namespace clr
// result is placed in wzBuffer and the number of chars written is placed in pcchBuffer on
// success; otherwise an error HRESULT is returned.
static HRESULT
- Combine(LPCWSTR wzPathLeft, LPCWSTR wzPathRight, __out DWORD *pcchBuffer, __out_ecount(*pcchBuffer) LPWSTR wzBuffer)
+ Combine(LPCWSTR wzPathLeft, LPCWSTR wzPathRight, __in DWORD *pcchBuffer, __out_ecount(*pcchBuffer) LPWSTR wzBuffer)
{
STATIC_CONTRACT_NOTHROW;
diff --git a/src/inc/clrconfigvalues.h b/src/inc/clrconfigvalues.h
index 391f127ed4..221334d7b7 100644
--- a/src/inc/clrconfigvalues.h
+++ b/src/inc/clrconfigvalues.h
@@ -293,6 +293,7 @@ CONFIG_STRING_INFO(INTERNAL_TestHooks, W("TestHooks"), "Used by tests to get tes
CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_AssertOnFailFast, W("AssertOnFailFast"), "")
RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_legacyCorruptedStateExceptionsPolicy, W("legacyCorruptedStateExceptionsPolicy"), 0, "Enabled Pre-V4 CSE behaviour", CLRConfig::FavorConfigFile)
CONFIG_DWORD_INFO_EX(INTERNAL_SuppressLostExceptionTypeAssert, W("SuppressLostExceptionTypeAssert"), 0, "", CLRConfig::REGUTIL_default)
+RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_FailFastOnCorruptedStateException, W("FailFastOnCorruptedStateException"), 0, "Failfast if a CSE is encountered", CLRConfig::FavorConfigFile)
//
// Garbage collector
diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h
index 043595dbc3..e0004a5948 100644
--- a/src/inc/corinfo.h
+++ b/src/inc/corinfo.h
@@ -3421,7 +3421,7 @@ public:
// to return the string values to the runtime for deletion.
// this avoid leaking the memory in the JIT.
virtual void freeStringConfigValue(
- wchar_t *value
+ __in_z wchar_t *value
) = 0;
#endif // !RYUJIT_CTPBUILD
};
diff --git a/src/inc/dlwrap.h b/src/inc/dlwrap.h
index 9129bcf2bf..d30e01462a 100644
--- a/src/inc/dlwrap.h
+++ b/src/inc/dlwrap.h
@@ -42,6 +42,7 @@ VerQueryValueW_NoThrow(
#endif
#if defined(_WININET_) && !defined (CreateUrlCacheEntryW_NoThrow)
+__success(return)
BOOL
CreateUrlCacheEntryW_NoThrow(
IN LPCWSTR lpszUrlName,
diff --git a/src/inc/downlevel.h b/src/inc/downlevel.h
index 12aeb42cf7..d33a0abb5b 100644
--- a/src/inc/downlevel.h
+++ b/src/inc/downlevel.h
@@ -143,13 +143,14 @@ namespace DownLevel
// User /system defaults
// TODO: I don't think we need all of these.
int GetSystemDefaultLocaleName(__out_ecount(cchLocaleName) LPWSTR lpLocaleName, __in int cchLocaleName);
- DWORD GetUserPreferredUILanguages (__in DWORD dwFlags, __out PULONG pulNumLanguages, __out_ecount_opt(*pcchLanguagesBuffer) PWSTR pwszLanguagesBuffer, __in PULONG pcchLanguagesBuffer);
+ __success(return == 1) DWORD GetUserPreferredUILanguages (__in DWORD dwFlags, __out PULONG pulNumLanguages, __out_ecount_opt(*pcchLanguagesBuffer) PWSTR pwszLanguagesBuffer, __in PULONG pcchLanguagesBuffer);
int GetUserDefaultLocaleName(__out_ecount(cchLocaleName) LPWSTR lpLocaleName, __in int cchLocaleName);
// Locale and calendar information
int GetLocaleInfoEx (__in LPCWSTR lpLocaleName, __in LCTYPE LCType, __out_ecount_opt(cchData) LPWSTR lpLCData, __in int cchData);
int GetDateFormatEx(__in LPCWSTR lpLocaleName, __in DWORD dwFlags, __in_opt CONST SYSTEMTIME* lpDate, __in_opt LPCWSTR lpFormat,
__out_ecount(cchDate) LPWSTR lpDateStr, __in int cchDate, __in_opt LPCWSTR lpCalendar);
+ __success(return != 0)
int GetCalendarInfoEx(__in LPCWSTR lpLocaleName,
__in CALID Calendar,
__in_opt LPCWSTR pReserved,
@@ -160,12 +161,13 @@ namespace DownLevel
// Compareinfo type information
int TurkishCompareStringIgnoreCase(LCID lcid, DWORD dwCmpFlags, LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2, int cchCount2);
-
- int CompareStringEx(LPCWSTR lpLocaleName, DWORD dwCmpFlags, LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2,
- int cchCount2, LPNLSVERSIONINFO lpVersionInformation, LPVOID lpReserved, LPARAM lParam );
- int CompareStringOrdinal(LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2, int cchCount2, BOOL bIgnoreCase);
+ int CompareStringEx(__in LPCWSTR lpLocaleName, __in DWORD dwCmpFlags, __in_ecount(cchCount1) LPCWSTR lpString1, __in int cchCount1, __in_ecount(cchCount2) LPCWSTR lpString2,
+ __in int cchCount2, __in_opt LPNLSVERSIONINFO lpVersionInformation, __in_opt LPVOID lpReserved, __in_opt LPARAM lParam );
+
+ int CompareStringOrdinal(__in_ecount(cchCount1) LPCWSTR string1, __in int cchCount1, __in_ecount(cchCount2) LPCWSTR string2, __in int cchCount2, __in BOOL bIgnoreCase);
+ __success(return != 0)
int LCMapStringEx(__in LPCWSTR lpLocaleName,
__in DWORD dwMapFlags,
__in_ecount(cchSrc) LPCWSTR lpSrcStr,
@@ -176,6 +178,7 @@ namespace DownLevel
__in_opt LPVOID lpReserved,
__in_opt LPARAM lParam);
+ __success(return != -1)
int FindNLSStringEx(__in LPCWSTR lpLocaleName,
__in DWORD dwFindNLSStringFlags,
__in_ecount(cchSource) LPCWSTR lpStringSource,
@@ -200,6 +203,7 @@ namespace DownLevel
// This is where we fudge data the OS doesn't know (even on Vista)
namespace UplevelFallback
{
+ __success(return != 0)
int LCMapStringEx(__in LPCWSTR lpLocaleName,
__in DWORD dwMapFlags,
__in_ecount(cchSrc) LPCWSTR lpSrcStr,
@@ -225,6 +229,7 @@ namespace DownLevel
int ResolveLocaleName(__in LPCWSTR lpNameToResolve, __in_ecount_opt(cchLocaleName) LPWSTR lpLocaleName, __in int cchLocaleName);
+ __success(return)
BOOL GetThreadPreferredUILanguages( __in DWORD dwFlags,
__out PULONG pulNumLanguages,
__out_ecount_opt(*pcchLanguagesBuffer) PWSTR pwszLanguagesBuffer,
diff --git a/src/inc/eventtracebase.h b/src/inc/eventtracebase.h
index eac127e732..9a6b218d3f 100644
--- a/src/inc/eventtracebase.h
+++ b/src/inc/eventtracebase.h
@@ -385,7 +385,7 @@ namespace ETW
friend class ETW::EnumerationLog;
#ifdef FEATURE_EVENT_TRACE
static VOID SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL bFireDomainModuleEvents=FALSE);
- static ULONG SendModuleRange(Module *pModule, DWORD dwEventOptions);
+ static ULONG SendModuleRange(__in Module *pModule, __in DWORD dwEventOptions);
static VOID SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions);
static VOID SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptions, LPCWSTR wszFriendlyName=NULL);
public:
diff --git a/src/inc/formattype.cpp b/src/inc/formattype.cpp
index 05b4c86247..923ff3e9a1 100644
--- a/src/inc/formattype.cpp
+++ b/src/inc/formattype.cpp
@@ -93,7 +93,7 @@ const PCCOR_SIGNATURE PrettyPrintSignature(
const char* name, // can be "", the name of the method for this sig 0 means local var sig
CQuickBytes *out, // where to put the pretty printed string
IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig
- __in_opt const char* inlabel, // prefix for names (NULL if no names required)
+ _In_opt_z_ const char* inlabel, // prefix for names (NULL if no names required)
BOOL printTyArity=FALSE);
diff --git a/src/inc/newapis.h b/src/inc/newapis.h
index 0ec87b5c70..57286e2051 100644
--- a/src/inc/newapis.h
+++ b/src/inc/newapis.h
@@ -326,7 +326,9 @@ namespace NewApis
// Enumeration functions
__success(return != 0) BOOL
EnumDateFormatsExEx (DATEFMT_ENUMPROCEXEX lpDateFmtEnumProcExEx, LPCWSTR lpLocaleName, DWORD dwFlags, LPARAM lParam);
+ __success(return != 0)
BOOL EnumTimeFormatsEx(TIMEFMT_ENUMPROCEX lpTimeFmtEnumProcEx, LPCWSTR lpLocaleName, DWORD dwFlags, LPARAM lParam);
+ __success(return != 0)
BOOL EnumCalendarInfoExEx(CALINFO_ENUMPROCEXEX pCalInfoEnumProcExEx, LPCWSTR lpLocaleName, CALID Calendar, CALTYPE CalType, LPARAM lParam);
int LCIDToLocaleName(__in LCID Locale, __out_ecount_opt(cchName) LPWSTR lpName, __in int cchName, __in DWORD dwFlags);
diff --git a/src/inc/palclr.h b/src/inc/palclr.h
index 9842bc4be6..26d882d08f 100644
--- a/src/inc/palclr.h
+++ b/src/inc/palclr.h
@@ -91,6 +91,7 @@
#define DIRECTORY_SEPARATOR_STR_W W("\\")
#define PATH_SEPARATOR_CHAR_W W(';')
+#define PATH_SEPARATOR_STR_W W(";")
// PAL Macros
// Not all compilers support fully anonymous aggregate types, so the
diff --git a/src/inc/sbuffer.h b/src/inc/sbuffer.h
index adcde9bab8..0c98fdb668 100644
--- a/src/inc/sbuffer.h
+++ b/src/inc/sbuffer.h
@@ -353,8 +353,8 @@ class SBuffer
// Manipulates contents of the buffer via the plugins below, but
// adds some debugging checks. Should always call through here rather
// than directly calling the extensibility points.
- void DebugMoveBuffer(BYTE *to, BYTE *from, COUNT_T size);
- void DebugCopyConstructBuffer(BYTE *to, const BYTE *from, COUNT_T size);
+ void DebugMoveBuffer(__out_bcount(size) BYTE *to, BYTE *from, COUNT_T size);
+ void DebugCopyConstructBuffer(__out_bcount(size) BYTE *to, const BYTE *from, COUNT_T size);
void DebugConstructBuffer(BYTE *buffer, COUNT_T size);
void DebugDestructBuffer(BYTE *buffer, COUNT_T size);
diff --git a/src/inc/sstring.h b/src/inc/sstring.h
index a42d71155e..f4ae412f18 100644
--- a/src/inc/sstring.h
+++ b/src/inc/sstring.h
@@ -1006,6 +1006,15 @@ typedef InlineSString<512> StackSString;
// be needed is small and it's preferable not to take up the stack space.
typedef InlineSString<32> SmallStackSString;
+// To be used specifically for path strings.
+#ifdef _DEBUG
+// This is a smaller version for debug builds to exercise the buffer allocation path
+typedef InlineSString<32> PathString;
+#else
+// Set it to the current MAX_PATH
+typedef InlineSString<260> PathString;
+#endif
+
// ================================================================================
// Quick macro to create an SString around a literal string.
// usage:
diff --git a/src/inc/stgpool.h b/src/inc/stgpool.h
index 5932a51464..9170125b37 100644
--- a/src/inc/stgpool.h
+++ b/src/inc/stgpool.h
@@ -333,7 +333,7 @@ protected:
// helper for extension segments.
//*****************************************************************************
__checkReturn
- FORCEINLINE HRESULT GetDataReadOnly(UINT32 nOffset, __in MetaData::DataBlob *pData)
+ FORCEINLINE HRESULT GetDataReadOnly(UINT32 nOffset, __inout MetaData::DataBlob *pData)
{
LIMITED_METHOD_CONTRACT;
_ASSERTE(IsReadOnly());
@@ -375,7 +375,7 @@ protected:
// helper for extension segments.
//*****************************************************************************
__checkReturn
- virtual HRESULT GetData(UINT32 nOffset, __in MetaData::DataBlob *pData)
+ virtual HRESULT GetData(UINT32 nOffset, __inout MetaData::DataBlob *pData)
{
WRAPPER_NO_CONTRACT;
return GetDataReadOnly(nOffset, pData);
diff --git a/src/inc/sxshelpers.h b/src/inc/sxshelpers.h
index 3fa450d5b9..3ecf5cc9a2 100644
--- a/src/inc/sxshelpers.h
+++ b/src/inc/sxshelpers.h
@@ -103,7 +103,7 @@ class AssemblyVersion
inline AssemblyVersion(AssemblyVersion& version);
// Init
- HRESULT Init(LPCWSTR pwzVersion, BOOL bStartsWithV);
+ HRESULT Init(__in_z LPCWSTR pwzVersion, BOOL bStartsWithV);
inline HRESULT Init(WORD major, WORD minor, WORD build, WORD revision);
// Mofifiers.
diff --git a/src/inc/utilcode.h b/src/inc/utilcode.h
index 7d380e24de..e832441454 100644
--- a/src/inc/utilcode.h
+++ b/src/inc/utilcode.h
@@ -5600,6 +5600,7 @@ namespace Clr { namespace Util
namespace Reg
{
HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, SString & ssValue);
+ __success(return == S_OK)
HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, __deref_out __deref_out_z LPWSTR* pwszValue);
}
@@ -5625,6 +5626,7 @@ namespace Win32
SString & ssFileName,
bool fAllowLongFileNames = false);
+ __success(return == S_OK)
HRESULT GetModuleFileName(
HMODULE hModule,
__deref_out_z LPWSTR * pwszFileName,
diff --git a/src/inc/winrt/windowsstring.h b/src/inc/winrt/windowsstring.h
index ff5fcfe811..fe99e69478 100644
--- a/src/inc/winrt/windowsstring.h
+++ b/src/inc/winrt/windowsstring.h
@@ -324,7 +324,7 @@ namespace clr
//
// if the HRESULT indicates failure, does nothing
//
- static HRESULT FreeAndAssignOnSuccess(HRESULT hr, HSTRING newValue, __out HSTRING *target)
+ static HRESULT FreeAndAssignOnSuccess(HRESULT hr, HSTRING newValue, __inout HSTRING *target)
{
STATIC_CONTRACT_LIMITED_METHOD;
if (SUCCEEDED(hr))
diff --git a/src/jit/codegenxarch.cpp b/src/jit/codegenxarch.cpp
index 1f590abe02..076ba7c262 100644
--- a/src/jit/codegenxarch.cpp
+++ b/src/jit/codegenxarch.cpp
@@ -5094,13 +5094,16 @@ void CodeGen::genCallInstruction(GenTreePtr node)
genConsumeReg(target));
}
}
-#if defined(_TARGET_AMD64_) && defined(FEATURE_READYTORUN_COMPILER)
+#ifdef FEATURE_READYTORUN_COMPILER
else if (call->gtEntryPoint.addr != nullptr)
{
- genEmitCall(emitter::EC_FUNC_TOKEN_INDIR,
+ genEmitCall((call->gtEntryPoint.accessType == IAT_VALUE) ? emitter::EC_FUNC_TOKEN : emitter::EC_FUNC_TOKEN_INDIR,
methHnd,
INDEBUG_LDISASM_COMMA(sigInfo)
(void*) call->gtEntryPoint.addr,
+#ifdef _TARGET_X86_
+ stackArgBytes,
+#endif // _TARGET_X86_
retSize,
ilOffset);
}
diff --git a/src/md/compressedinteger.h b/src/md/compressedinteger.h
index 54a86cb626..2dcae9b60c 100644
--- a/src/md/compressedinteger.h
+++ b/src/md/compressedinteger.h
@@ -67,6 +67,7 @@ public:
// Returns FALSE if the value cannot be encoded as compressed integer, doesn't fill *pcbEncodingSize
// then.
__checkReturn
+ __success(return)
static inline BOOL GetEncodingSize(
UINT32 nValue,
__out UINT32 *pcbEncodingSize);
@@ -74,6 +75,7 @@ public:
// *pcbEncodingSize with 1, 2 or 4 and *pnEncodedValue with the encoded value.
// Returns FALSE if the value cannot be encoded as compressed integer, doesn't fill *pcbEncodingSize
// nor *pnEncodedValue then.
+ __success(return)
static inline BOOL Encode(
UINT32 nValue,
__out UINT32 *pnEncodedValue,
diff --git a/src/md/datablob.h b/src/md/datablob.h
index 891e41eff0..8e00b29cfe 100644
--- a/src/md/datablob.h
+++ b/src/md/datablob.h
@@ -67,19 +67,19 @@ public:
// Returns FALSE if there's not enough data in the blob, doesn't initialize the value '*pnValue' then.
// Returns TRUE otherwise, fills *pnValue, but doesn't move the memory block (doesn't skip the read
// data).
- __checkReturn inline BOOL PeekU1(__out BYTE *pnValue) const;
- __checkReturn inline BOOL PeekU2(__out UINT16 *pnValue) const;
- __checkReturn inline BOOL PeekU4(__out UINT32 *pnValue) const;
- __checkReturn inline BOOL PeekU8(__out UINT64 *pnValue) const;
+ __checkReturn __success(return) inline BOOL PeekU1(__out BYTE *pnValue) const;
+ __checkReturn __success(return) inline BOOL PeekU2(__out UINT16 *pnValue) const;
+ __checkReturn __success(return) inline BOOL PeekU4(__out UINT32 *pnValue) const;
+ __checkReturn __success(return) inline BOOL PeekU8(__out UINT64 *pnValue) const;
//#GetUx_Functions
// Reads the U1/U2/U4/U8 from the data blob and skips the read data.
// Returns FALSE if there's not enough data in the blob, doesn't initialize the value '*pnValue' then.
// Returns TRUE otherwise, fills *pnValue and moves the memory block behind the read data.
- __checkReturn inline BOOL GetU1(__out BYTE *pnValue);
- __checkReturn inline BOOL GetU2(__out UINT16 *pnValue);
- __checkReturn inline BOOL GetU4(__out UINT32 *pnValue);
- __checkReturn inline BOOL GetU8(__out UINT64 *pnValue);
+ __checkReturn __success(return) inline BOOL GetU1(__out BYTE *pnValue);
+ __checkReturn __success(return) inline BOOL GetU2(__out UINT16 *pnValue);
+ __checkReturn __success(return) inline BOOL GetU4(__out UINT32 *pnValue);
+ __checkReturn __success(return) inline BOOL GetU8(__out UINT64 *pnValue);
// Reads compressed integer (1, 2 or 4 bytes of format code:CompressedInteger#Format - returns the size
// in *pcbCompressedValueSize) from the data blob without skipping the read data.
@@ -89,6 +89,7 @@ public:
// Returns TRUE otherwise, fills *pnValue and *pcbCompressedValueSize (with number 1,2 or 4), but
// doesn't move the memory block (doesn't skip the read data).
__checkReturn
+ __success(return)
inline BOOL PeekCompressedU(
__out UINT32 *pnValue,
__out UINT32 *pcbCompressedValueSize);
@@ -97,7 +98,8 @@ public:
// Returns FALSE if there's not enough data in the blob or the compression is invalid (starts with byte
// 111? ????), doesn't initialize the value *pnValue then.
// Returns TRUE otherwise, fills *pnValue and moves the memory block behind the read data.
- __checkReturn
+ __checkReturn
+ __success(return)
inline BOOL GetCompressedU(__out UINT32 *pnValue);
// Reads compressed integer (1, 2 or 4 bytes of format code:CompressedInteger#Format - returns the size
// in *pcbCompressedValueSize) from the data blob and skips the read data.
@@ -107,6 +109,7 @@ public:
// Returns TRUE otherwise, fills *pnValue and *pcbCompressedValueSize (with number 1,2 or 4) and moves
// the memory block behind the read data.
__checkReturn
+ __success(return)
inline BOOL GetCompressedU(
__out UINT32 *pnValue,
__out UINT32 *pcbCompressedValueSize);
@@ -117,6 +120,7 @@ public:
// Returns TRUE otherwise, fills *pData with the "read" data and moves the memory block behind the
// "read" data.
__checkReturn
+ __success(return)
inline BOOL GetDataOfSize(
UINT32 cbDataSize,
__out DataBlob *pData);
@@ -174,11 +178,13 @@ public:
// Returns FALSE if there's less than cbSize data represented.
// Returns TRUE otherwise and truncates the represented data size to cbSize.
__checkReturn
+ __success(return)
inline BOOL TruncateToExactSize(UINT32 cbSize);
// Truncates the buffer by size (cbSize).
// Returns FALSE if there's less than cbSize data represented.
// Returns TRUE otherwise and truncates the represented data size by cbSize.
__checkReturn
+ __success(return)
inline BOOL TruncateBySize(UINT32 cbSize);
#ifdef _DEBUG
@@ -198,12 +204,14 @@ public:
// integer (bigger than code:CompressedInteger::const_Max).
// Returns TRUE on success and moves the memory block behind the written data.
__checkReturn
+ __success(return)
inline BOOL StoreCompressedU(UINT32 nValue);
// Writes data from *pSource to the data blob and skips the written data.
// Returns FALSE if there's not enough data in the blob.
// Returns TRUE on success and moves memory block behind the written data.
__checkReturn
+ __success(return)
inline BOOL StoreData(__in const DataBlob *pSource);
private:
diff --git a/src/md/datablob.inl b/src/md/datablob.inl
index d7ce361013..40c92c2131 100644
--- a/src/md/datablob.inl
+++ b/src/md/datablob.inl
@@ -106,6 +106,7 @@ DataBlob::Init(
// See code:#PeekUx_Functions above.
//
__checkReturn
+_Success_(return)
inline
BOOL
DataBlob::PeekU1(__out BYTE *pnValue) const
@@ -123,6 +124,7 @@ DataBlob::PeekU1(__out BYTE *pnValue) const
// See code:#PeekUx_Functions above.
//
__checkReturn
+_Success_(return)
inline
BOOL
DataBlob::PeekU2(__out UINT16 *pnValue) const
@@ -140,6 +142,7 @@ DataBlob::PeekU2(__out UINT16 *pnValue) const
// See code:#PeekUx_Functions above.
//
__checkReturn
+_Success_(return)
inline
BOOL
DataBlob::PeekU4(__out UINT32 *pnValue) const
@@ -157,6 +160,7 @@ DataBlob::PeekU4(__out UINT32 *pnValue) const
// See code:#PeekUx_Functions above.
//
__checkReturn
+_Success_(return)
inline
BOOL
DataBlob::PeekU8(__out UINT64 *pnValue) const
@@ -183,6 +187,7 @@ DataBlob::PeekU8(__out UINT64 *pnValue) const
// See code:#GetUx_Functions above.
//
__checkReturn
+_Success_(return)
inline
BOOL
DataBlob::GetU1(__out BYTE *pnValue)
@@ -201,6 +206,7 @@ DataBlob::GetU1(__out BYTE *pnValue)
// See code:#GetUx_Functions above.
//
__checkReturn
+_Success_(return)
inline
BOOL
DataBlob::GetU2(__out UINT16 *pnValue)
@@ -219,6 +225,7 @@ DataBlob::GetU2(__out UINT16 *pnValue)
// See code:#GetUx_Functions above.
//
__checkReturn
+_Success_(return)
inline
BOOL
DataBlob::GetU4(__out UINT32 *pnValue)
@@ -237,6 +244,7 @@ DataBlob::GetU4(__out UINT32 *pnValue)
// See code:#GetUx_Functions above.
//
__checkReturn
+_Success_(return)
inline
BOOL
DataBlob::GetU8(__out UINT64 *pnValue)
@@ -278,6 +286,7 @@ DataBlob::GetCompressedU(__out UINT32 *pnValue)
// doesn't move the memory block (doesn't skip the read data).
//
__checkReturn
+_Success_(return)
inline
BOOL
DataBlob::PeekCompressedU(
diff --git a/src/md/heaps/blobheap.h b/src/md/heaps/blobheap.h
index 91d5430368..d3fb1e324c 100644
--- a/src/md/heaps/blobheap.h
+++ b/src/md/heaps/blobheap.h
@@ -83,7 +83,7 @@ public:
__checkReturn
inline HRESULT GetAllData(
- __out DataBlob *pData)
+ __inout DataBlob *pData)
{
return m_BlobPool.GetDataReadOnly(0, pData);
}
diff --git a/src/md/hotdata/hotheap.h b/src/md/hotdata/hotheap.h
index cc59c8a175..e9e42c4330 100644
--- a/src/md/hotdata/hotheap.h
+++ b/src/md/hotdata/hotheap.h
@@ -52,7 +52,7 @@ public:
__checkReturn
HRESULT GetData(
UINT32 nDataIndex,
- __in DataBlob *pData);
+ __out DataBlob *pData);
inline BOOL IsEmpty() const
{ return m_pHotHeapHeader == NULL; }
diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
new file mode 100644
index 0000000000..b600fa59ef
--- /dev/null
+++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Globalization;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class GlobalizationInterop
+ {
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode)]
+ internal unsafe static extern int CompareString(byte[] localeName, char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len, CompareOptions options);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode)]
+ internal unsafe static extern int IndexOf(byte[] localeName, string target, char* pSource, int cwSourceLength, CompareOptions options);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode)]
+ internal unsafe static extern int LastIndexOf(byte[] localeName, string target, char* pSource, int cwSourceLength, CompareOptions options);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal unsafe static extern bool StartsWith(byte[] localeName, string target, string source, int cwSourceLength, CompareOptions options);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal unsafe static extern bool EndsWith(byte[] localeName, string target, string source, int cwSourceLength, CompareOptions options);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode)]
+ internal unsafe static extern int GetSortKey(byte[] localeName, string str, int strLength, byte* sortKey, int sortKeyLength, CompareOptions options);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode)]
+ internal unsafe static extern int CompareStringOrdinalIgnoreCase(char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len);
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs
index 46fb25b6c3..ba658d0f5e 100644
--- a/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs
+++ b/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs
@@ -2,14 +2,22 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
namespace System.Globalization
{
public partial class CompareInfo
- {
+ {
+ // ICU uses a char* (UTF-8) to represent a locale name.
+ private readonly byte[] m_sortNameAsUtf8;
+
internal unsafe CompareInfo(CultureInfo culture)
{
- // TODO: Implement This Fully.
+ m_name = culture.m_name;
+ m_sortName = culture.SortName;
+ m_sortNameAsUtf8 = System.Text.Encoding.UTF8.GetBytes(m_sortName);
}
internal static int IndexOfOrdinal(string source, string value, int startIndex, int count, bool ignoreCase)
@@ -17,13 +25,13 @@ namespace System.Globalization
Contract.Assert(source != null);
Contract.Assert(value != null);
- // TODO: Implement This Fully.
-
if (value.Length == 0)
{
return startIndex;
}
+ // TODO (dotnet/corefx#3468): Move this into the shim so we don't have to do the ToUpper or call substring.
+
if (ignoreCase)
{
source = source.ToUpper(CultureInfo.InvariantCulture);
@@ -53,13 +61,13 @@ namespace System.Globalization
Contract.Assert(source != null);
Contract.Assert(value != null);
- // TODO: Implement This Fully.
-
if (value.Length == 0)
{
return startIndex;
}
+ // TODO (dotnet/corefx#3468): Move this into the shim so we don't have to do the ToUpper or call substring.
+
if (ignoreCase)
{
source = source.ToUpper(CultureInfo.InvariantCulture);
@@ -76,8 +84,8 @@ namespace System.Globalization
last = cur;
}
- return last >= 0 ?
- last + startIndex - count + 1 :
+ return last >= 0 ?
+ last + startIndex - count + 1 :
-1;
}
@@ -86,25 +94,13 @@ namespace System.Globalization
Contract.Assert(source != null);
Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
- // TODO: Implement This Fully.
- int hash = 5381;
-
- unchecked
- {
- for (int i = 0; i < source.Length; i++)
- {
- hash = ((hash << 5) + hash) + ChangeCaseAscii(source[i]);
- }
- }
-
- return hash;
+ return GetHashCodeOfStringCore(source, options, forceRandomizedHashing: false, additionalEntropy: 0);
}
[System.Security.SecuritySafeCritical]
private static unsafe int CompareStringOrdinalIgnoreCase(char* string1, int count1, char* string2, int count2)
{
- // TODO: Implement This Fully.
- return CompareStringOrdinalAscii(string1, count1, string2, count2, ignoreCase: true);
+ return Interop.GlobalizationInterop.CompareStringOrdinalIgnoreCase(string1, count1, string2, count2);
}
[System.Security.SecuritySafeCritical]
@@ -114,37 +110,66 @@ namespace System.Globalization
Contract.Assert(string2 != null);
Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
- // TODO: Implement This Fully.
- string s1 = string1.Substring(offset1, length1);
- string s2 = string2.Substring(offset2, length2);
-
- fixed (char* c1 = s1)
+ fixed (char* pString1 = string1)
{
- fixed (char* c2 = s2)
+ fixed (char* pString2 = string2)
{
- return CompareStringOrdinalAscii(c1, s1.Length, c2, s2.Length, IgnoreCase(options));
+ return Interop.GlobalizationInterop.CompareString(m_sortNameAsUtf8, pString1 + offset1, length1, pString2 + offset2, length2, options);
}
}
}
- private int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
+ [System.Security.SecuritySafeCritical]
+ private unsafe int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
{
Contract.Assert(!string.IsNullOrEmpty(source));
Contract.Assert(target != null);
Contract.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
- // TODO: Implement This Fully.
- return IndexOfOrdinal(source, target, startIndex, count, IgnoreCase(options));
+ if (target.Length == 0)
+ {
+ return startIndex;
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ return IndexOfOrdinal(source, target, startIndex, count, ignoreCase: false);
+ }
+
+ fixed (char* pSource = source)
+ {
+ int lastIndex = Interop.GlobalizationInterop.IndexOf(m_sortNameAsUtf8, target, pSource + startIndex, count, options);
+
+ return lastIndex != -1 ? lastIndex + startIndex : -1;
+ }
}
- private int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
+ private unsafe int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
{
Contract.Assert(!string.IsNullOrEmpty(source));
Contract.Assert(target != null);
Contract.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
- // TODO: Implement This Fully.
- return LastIndexOfOrdinal(source, target, startIndex, count, IgnoreCase(options));
+ if (target.Length == 0)
+ {
+ return startIndex;
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ return LastIndexOfOrdinal(source, target, startIndex, count, ignoreCase: false);
+ }
+
+ // startIndex is the index into source where we start search backwards from. leftStartIndex is the index into source
+ // of the start of the string that is count characters away from startIndex.
+ int leftStartIndex = (startIndex - count + 1);
+
+ fixed (char* pSource = source)
+ {
+ int lastIndex = Interop.GlobalizationInterop.LastIndexOf(m_sortNameAsUtf8, target, pSource + (startIndex - count + 1), count, options);
+
+ return lastIndex != -1 ? lastIndex + leftStartIndex : -1;
+ }
}
private bool StartsWith(string source, string prefix, CompareOptions options)
@@ -153,10 +178,7 @@ namespace System.Globalization
Contract.Assert(!string.IsNullOrEmpty(prefix));
Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
- // TODO: Implement This Fully.
- if(prefix.Length > source.Length) return false;
-
- return StringEqualsAscii(source.Substring(0, prefix.Length), prefix, IgnoreCase(options));
+ return Interop.GlobalizationInterop.StartsWith(m_sortNameAsUtf8, prefix, source, source.Length, options);
}
private bool EndsWith(string source, string suffix, CompareOptions options)
@@ -165,75 +187,40 @@ namespace System.Globalization
Contract.Assert(!string.IsNullOrEmpty(suffix));
Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
- // TODO: Implement This Fully.
- if(suffix.Length > source.Length) return false;
-
- return StringEqualsAscii(source.Substring(source.Length - suffix.Length), suffix, IgnoreCase(options));
+ return Interop.GlobalizationInterop.EndsWith(m_sortNameAsUtf8, suffix, source, source.Length, options);
}
// -----------------------------
// ---- PAL layer ends here ----
// -----------------------------
- private static char ChangeCaseAscii(char c, bool toUpper = true)
+ internal unsafe int GetHashCodeOfStringCore(string source, CompareOptions options, bool forceRandomizedHashing, long additionalEntropy)
{
- if (toUpper && c >= 'a' && c <= 'z')
- {
- return (char)('A' + (c - 'a'));
- }
- else if (!toUpper && c >= 'A' && c <= 'Z')
- {
- return (char)('a' + (c - 'A'));
- }
-
- return c;
- }
+ Contract.Assert(source != null);
+ Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
- private static bool StringEqualsAscii(string s1, string s2, bool ignoreCase = true)
- {
- if (s1.Length != s2.Length) return false;
+ int sortKeyLength = Interop.GlobalizationInterop.GetSortKey(m_sortNameAsUtf8, source, source.Length, null, 0, options);
- for (int i = 0; i < s1.Length; i++)
+ // As an optimization, for small sort keys we allocate the buffer on the stack.
+ if (sortKeyLength <= 256)
{
- char c1 = ignoreCase ? ChangeCaseAscii(s1[i]) : s1[i];
- char c2 = ignoreCase ? ChangeCaseAscii(s2[i]) : s2[i];
-
- if (c1 != c2) return false;
+ byte* pSortKey = stackalloc byte[sortKeyLength];
+ Interop.GlobalizationInterop.GetSortKey(m_sortNameAsUtf8, source, source.Length, pSortKey, sortKeyLength, options);
+ return InternalHashSortKey(pSortKey, sortKeyLength, false, additionalEntropy);
}
- return true;
- }
+ byte[] sortKey = new byte[sortKeyLength];
- [System.Security.SecuritySafeCritical]
- private static unsafe int CompareStringOrdinalAscii(char* s1, int count1, char* s2, int count2, bool ignoreCase)
- {
- int countMin = Math.Min(count1, count2);
+ fixed(byte* pSortKey = sortKey)
{
- for (int i = 0; i < countMin; i++)
- {
- char c1 = ignoreCase ? ChangeCaseAscii(s1[i]) : s1[i];
- char c2 = ignoreCase ? ChangeCaseAscii(s2[i]) : s2[i];
-
- if (c1 < c2)
- {
- return -1;
- }
- else if (c1 > c2)
- {
- return 1;
- }
- }
+ Interop.GlobalizationInterop.GetSortKey(m_sortNameAsUtf8, source, source.Length, pSortKey, sortKeyLength, options);
+ return InternalHashSortKey(pSortKey, sortKeyLength, false, additionalEntropy);
}
-
- if (count1 == count2) return 0;
- if (count1 > count2) return 1;
-
- return -1;
}
- private static bool IgnoreCase(CompareOptions options)
- {
- return ((options & CompareOptions.IgnoreCase) == CompareOptions.IgnoreCase);
- }
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall)]
+ [SuppressUnmanagedCodeSecurity]
+ private static unsafe extern int InternalHashSortKey(byte* sortKey, int sortKeyLength, [MarshalAs(UnmanagedType.Bool)] bool forceRandomizedHashing, long additionalEntropy);
}
-} \ No newline at end of file
+}
diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs b/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs
index 9a18175a06..9a64917b66 100644
--- a/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs
+++ b/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs
@@ -19,11 +19,10 @@ namespace System.Globalization
//////////////////////////////////////////////////////////////////////////
internal unsafe TextInfo(CultureData cultureData)
{
- // TODO: Implement this fully.
m_cultureData = cultureData;
m_cultureName = m_cultureData.CultureName;
m_textInfoName = m_cultureData.STEXTINFO;
- m_needsTurkishCasing = NeedsTurkishCasing(this.m_textInfoName);
+ m_needsTurkishCasing = NeedsTurkishCasing(m_textInfoName);
}
[System.Security.SecuritySafeCritical]
@@ -61,9 +60,7 @@ namespace System.Globalization
private bool NeedsTurkishCasing(string localeName)
{
Contract.Assert(localeName != null);
-
- string lcName = CultureData.AnsiToLower(localeName);
- return lcName.Length >= 2 && ((lcName[0] == 't' && lcName[1] == 'r') || (lcName[0] == 'a' && lcName[1] == 'z'));
+ return CultureInfo.GetCultureInfo(localeName).CompareInfo.Compare("i", "I", CompareOptions.IgnoreCase) != 0;
}
}
}
diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.cs b/src/mscorlib/corefx/System/Globalization/TextInfo.cs
index e99151dda8..7de2b67036 100644
--- a/src/mscorlib/corefx/System/Globalization/TextInfo.cs
+++ b/src/mscorlib/corefx/System/Globalization/TextInfo.cs
@@ -288,14 +288,6 @@ namespace System.Globalization
{
get
{
-#if PLATFORM_UNIX
- // UNIXTODO: This hack can be removed once collation works and the code after this correctly returns "false".
- if (m_needsTurkishCasing)
- {
- return false;
- }
-#endif
-
if (m_IsAsciiCasingSameAsInvariant == null)
{
m_IsAsciiCasingSameAsInvariant = CultureInfo.GetCultureInfo(m_textInfoName).CompareInfo.Compare("abcdefghijklmnopqrstuvwxyz",
diff --git a/src/mscorlib/model.xml b/src/mscorlib/model.xml
index 70b8e916b4..512c7a0ade 100644
--- a/src/mscorlib/model.xml
+++ b/src/mscorlib/model.xml
@@ -1017,6 +1017,7 @@
<Member Name="Resolve(System.IntPtr,System.Reflection.AssemblyName)" />
<Member Name="ResolveUnmanagedDll(System.String,System.IntPtr)" />
<Member Name="LoadUnmanagedDll(System.String)" />
+ <Member Name="LoadUnmanagedDllFromPath(System.String)" />
<Member Name="get_Default" />
<Member Name="SetProfileOptimizationRoot(System.String)" />
<Member Name="StartProfileOptimization(System.String)" />
@@ -9900,6 +9901,7 @@
<Member Name="get_Name" />
<Member MemberType="Property" Name="ConstructionException" />
<Member MemberType="Property" Name="CurrentThreadActivityId" />
+ <Member MemberType="Event" Name="EventCommandExecuted" />
<Member Name="Dispose" />
<Member Name="Dispose(System.Boolean)" />
<Member Name="GenerateManifest(System.Type,System.String)" />
diff --git a/src/mscorlib/mscorlib.shared.sources.props b/src/mscorlib/mscorlib.shared.sources.props
index 81749f0569..13f58e2fc0 100644
--- a/src/mscorlib/mscorlib.shared.sources.props
+++ b/src/mscorlib/mscorlib.shared.sources.props
@@ -787,6 +787,7 @@
<GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\Interop.Libraries.cs" />
<GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\System.Globalization.Native\Interop.Calendar.cs" />
<GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\System.Globalization.Native\Interop.Casing.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\System.Globalization.Native\Interop.Collation.cs" />
<GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\System.Globalization.Native\Interop.Locale.cs" />
<GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\System.Globalization.Native\Interop.TimeZoneInfo.cs" />
<GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CalendarData.Unix.cs" />
diff --git a/src/mscorlib/src/System/Collections/Hashtable.cs b/src/mscorlib/src/System/Collections/Hashtable.cs
index 4c30b72b5e..2c10ff0442 100644
--- a/src/mscorlib/src/System/Collections/Hashtable.cs
+++ b/src/mscorlib/src/System/Collections/Hashtable.cs
@@ -22,7 +22,7 @@ namespace System.Collections {
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Diagnostics.Contracts;
-#if FEATURE_RANDOMIZED_STRING_HASHING
+#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_PAL
using System.Security.Cryptography;
#endif
@@ -1802,9 +1802,11 @@ namespace System.Collections {
return comparer;
}
-
+
private const int bufferSize = 1024;
+#if !FEATURE_PAL
private static RandomNumberGenerator rng;
+#endif
private static byte[] data;
private static int currentIndex = bufferSize;
private static readonly object lockObj = new Object();
@@ -1816,14 +1818,21 @@ namespace System.Collections {
if(currentIndex == bufferSize)
{
- if(null == rng)
+ if(data == null)
{
- rng = RandomNumberGenerator.Create();
data = new byte[bufferSize];
Contract.Assert(bufferSize % 8 == 0, "We increment our current index by 8, so our buffer size must be a multiple of 8");
+#if !FEATURE_PAL
+ rng = RandomNumberGenerator.Create();
+#endif
+
}
+#if FEATURE_PAL
+ Microsoft.Win32.Win32Native.Random(true, data, data.Length);
+#else
rng.GetBytes(data);
+#endif
currentIndex = 0;
}
diff --git a/src/mscorlib/src/System/Decimal.cs b/src/mscorlib/src/System/Decimal.cs
index 894760043e..a9acef73b4 100644
--- a/src/mscorlib/src/System/Decimal.cs
+++ b/src/mscorlib/src/System/Decimal.cs
@@ -218,11 +218,7 @@ namespace System {
// Constructs a Decimal from a Currency value.
//
internal Decimal(Currency value) {
- Decimal temp = Currency.ToDecimal(value);
- this.lo = temp.lo;
- this.mid = temp.mid;
- this.hi = temp.hi;
- this.flags = temp.flags;
+ this = Currency.ToDecimal(value);
}
// Don't remove these 2 methods below. They are required by the fx when the are dealing with Currency in their
diff --git a/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs
index 66a9b17ba7..f461a14e50 100644
--- a/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs
+++ b/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs
@@ -199,6 +199,30 @@ namespace System.Runtime.Loader
return assembly;
}
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern IntPtr InternalLoadUnmanagedDllFromPath(string unmanagedDllPath);
+
+ // This method provides a way for overriders of LoadUnmanagedDll() to load an unmanaged DLL from a specific path in a
+ // platform-independent way. The DLL is loaded with default load flags.
+ protected IntPtr LoadUnmanagedDllFromPath(string unmanagedDllPath)
+ {
+ if (unmanagedDllPath == null)
+ {
+ throw new ArgumentNullException("unmanagedDllPath");
+ }
+ if (unmanagedDllPath.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"), "unmanagedDllPath");
+ }
+ if (Path.IsRelative(unmanagedDllPath))
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired"), "unmanagedDllPath");
+ }
+
+ return InternalLoadUnmanagedDllFromPath(unmanagedDllPath);
+ }
// Custom AssemblyLoadContext implementations can override this
// method to perform the load of unmanaged native dll
diff --git a/src/mscorlib/src/System/String.cs b/src/mscorlib/src/System/String.cs
index 8acafd6d5f..eb8fdd88a2 100644
--- a/src/mscorlib/src/System/String.cs
+++ b/src/mscorlib/src/System/String.cs
@@ -2556,10 +2556,12 @@ namespace System {
return CultureInfo.InvariantCulture.CompareInfo.IsPrefix(this, value, CompareOptions.IgnoreCase);
case StringComparison.Ordinal:
- if( this.Length < value.Length) {
+ if( this.Length < value.Length || m_firstChar != value.m_firstChar) {
return false;
}
- return (nativeCompareOrdinalEx(this, 0, value, 0, value.Length) == 0);
+ return (value.Length == 1) ?
+ true : // First char is the same and thats all there is to compare
+ (nativeCompareOrdinalEx(this, 0, value, 0, value.Length) == 0);
case StringComparison.OrdinalIgnoreCase:
if( this.Length < value.Length) {
diff --git a/src/mscorlib/src/System/StringComparer.cs b/src/mscorlib/src/System/StringComparer.cs
index cc976504ab..9799a51942 100644
--- a/src/mscorlib/src/System/StringComparer.cs
+++ b/src/mscorlib/src/System/StringComparer.cs
@@ -239,8 +239,7 @@ namespace System {
}
#if FEATURE_COREFX_GLOBALIZATION
- // TODO: Implement this fully.
- throw new NotImplementedException();
+ return _compareInfo.GetHashCodeOfStringCore(obj, options, true, _entropy);
#else
return _compareInfo.GetHashCodeOfString(obj, options, true, _entropy);
#endif
@@ -394,8 +393,7 @@ namespace System {
if( _ignoreCase) {
#if FEATURE_COREFX_GLOBALIZATION
- // TODO: Implement this fully.
- throw new NotImplementedException();
+ return CultureInfo.InvariantCulture.CompareInfo.GetHashCodeOfStringCore(obj, CompareOptions.IgnoreCase, true, _entropy);
#else
return TextInfo.GetHashCodeOrdinalIgnoreCase(obj, true, _entropy);
#endif
diff --git a/src/mscorlib/src/System/Threading/ExecutionContext.cs b/src/mscorlib/src/System/Threading/ExecutionContext.cs
index 3fc1e14908..94308118bc 100644
--- a/src/mscorlib/src/System/Threading/ExecutionContext.cs
+++ b/src/mscorlib/src/System/Threading/ExecutionContext.cs
@@ -59,18 +59,18 @@ namespace System.Threading
static ExecutionContext t_currentMaybeNull;
private readonly Dictionary<IAsyncLocal, object> m_localValues;
- private readonly List<IAsyncLocal> m_localChangeNotifications;
+ private readonly IAsyncLocal[] m_localChangeNotifications;
private ExecutionContext()
{
m_localValues = new Dictionary<IAsyncLocal, object>();
- m_localChangeNotifications = new List<IAsyncLocal>();
+ m_localChangeNotifications = Array.Empty<IAsyncLocal>();
}
- private ExecutionContext(ExecutionContext other)
+ private ExecutionContext(Dictionary<IAsyncLocal, object> localValues, IAsyncLocal[] localChangeNotifications)
{
- m_localValues = new Dictionary<IAsyncLocal, object>(other.m_localValues);
- m_localChangeNotifications = new List<IAsyncLocal>(other.m_localChangeNotifications);
+ m_localValues = localValues;
+ m_localChangeNotifications = localChangeNotifications;
}
[SecuritySafeCritical]
@@ -191,18 +191,39 @@ namespace System.Threading
if (previousValue == newValue)
return;
- current = new ExecutionContext(current);
- current.m_localValues[local] = newValue;
+ //
+ // Allocate a new Dictionary containing a copy of the old values, plus the new value. We have to do this manually to
+ // minimize allocations of IEnumerators, etc.
+ //
+ Dictionary<IAsyncLocal, object> newValues = new Dictionary<IAsyncLocal, object>(current.m_localValues.Count + (hadPreviousValue ? 0 : 1));
- t_currentMaybeNull = current;
+ foreach (KeyValuePair<IAsyncLocal, object> pair in current.m_localValues)
+ newValues.Add(pair.Key, pair.Value);
+ newValues[local] = newValue;
+
+ //
+ // Either copy the change notification array, or create a new one, depending on whether we need to add a new item.
+ //
+ IAsyncLocal[] newChangeNotifications = current.m_localChangeNotifications;
if (needChangeNotifications)
{
if (hadPreviousValue)
- Contract.Assert(current.m_localChangeNotifications.Contains(local));
+ {
+ Contract.Assert(Array.IndexOf(newChangeNotifications, local) >= 0);
+ }
else
- current.m_localChangeNotifications.Add(local);
+ {
+ int newNotificationIndex = newChangeNotifications.Length;
+ Array.Resize(ref newChangeNotifications, newNotificationIndex + 1);
+ newChangeNotifications[newNotificationIndex] = local;
+ }
+ }
+ t_currentMaybeNull = new ExecutionContext(newValues, newChangeNotifications);
+
+ if (needChangeNotifications)
+ {
local.OnValueChanged(previousValue, newValue, false);
}
}
diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h
index 6f88513d29..080d07781d 100644
--- a/src/pal/inc/pal.h
+++ b/src/pal/inc/pal.h
@@ -3658,6 +3658,19 @@ LoadLibraryExW(
IN /*Reserved*/ HANDLE hFile,
IN DWORD dwFlags);
+PALIMPORT
+HMODULE
+PALAPI
+PAL_LoadLibraryDirect(
+ IN LPCWSTR lpLibFileName);
+
+PALIMPORT
+HMODULE
+PALAPI
+PAL_RegisterLibraryDirect(
+ IN HMODULE dl_handle,
+ IN LPCWSTR lpLibFileName);
+
/*++
Function:
PAL_LOADLoadPEFile
@@ -3879,14 +3892,6 @@ HeapCreate(
IN SIZE_T dwMaximumSize);
PALIMPORT
-SIZE_T
-PALAPI
-HeapSize(
- HANDLE hHeap,
- DWORD dwFlags,
- LPCVOID lpMem);
-
-PALIMPORT
LPVOID
PALAPI
HeapAlloc(
diff --git a/src/pal/inc/rt/palrt.h b/src/pal/inc/rt/palrt.h
index 92d9b3a219..b969047ce3 100644
--- a/src/pal/inc/rt/palrt.h
+++ b/src/pal/inc/rt/palrt.h
@@ -1364,11 +1364,13 @@ typedef VOID (__stdcall *WAITORTIMERCALLBACK)(PVOID, BOOLEAN);
#define DIRECTORY_SEPARATOR_CHAR_W W('/')
#define DIRECTORY_SEPARATOR_STR_W W("/")
#define PATH_SEPARATOR_CHAR_W W(':')
+#define PATH_SEPARATOR_STR_W W(":")
#else // PLATFORM_UNIX
#define DIRECTORY_SEPARATOR_CHAR_A '\\'
#define DIRECTORY_SEPARATOR_CHAR_W W('\\')
#define DIRECTORY_SEPARATOR_STR_W W("\\")
#define PATH_SEPARATOR_CHAR_W W(';')
+#define PATH_SEPARATOR_STR_W W(";")
#endif // PLATFORM_UNIX
#ifndef IMAGE_IMPORT_DESC_FIELD
diff --git a/src/pal/src/CMakeLists.txt b/src/pal/src/CMakeLists.txt
index 854655621f..20393cd17e 100644
--- a/src/pal/src/CMakeLists.txt
+++ b/src/pal/src/CMakeLists.txt
@@ -141,6 +141,7 @@ set(SOURCES
misc/interlock.cpp
misc/miscpalapi.cpp
misc/msgbox.cpp
+ misc/stackstring.cpp
misc/strutil.cpp
misc/sysinfo.cpp
misc/time.cpp
@@ -223,7 +224,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL Linux)
rt
dl
unwind
- unwind-ptrace
unwind-generic
)
endif(CMAKE_SYSTEM_NAME STREQUAL Linux)
diff --git a/src/pal/src/config.h.in b/src/pal/src/config.h.in
index 5133374392..4c06de0eca 100644
--- a/src/pal/src/config.h.in
+++ b/src/pal/src/config.h.in
@@ -135,7 +135,6 @@
#define HAVE_LOWERCASE_ISO_NAME 0
#define HAVE_READ_REAL_TIME 0
#define HAVE_UNDERSCORE_ISO_NAME 0
-#define MALLOC_ZERO_RETURNS_NULL 0
#define MKSTEMP64_IS_USED_INSTEAD_OF_MKSTEMP 0
#define NEED_DLCOMPAT 0
#define OPEN64_IS_USED_INSTEAD_OF_OPEN 0
diff --git a/src/pal/src/configure.cmake b/src/pal/src/configure.cmake
index 69d947adb3..77a0846762 100644
--- a/src/pal/src/configure.cmake
+++ b/src/pal/src/configure.cmake
@@ -763,22 +763,6 @@ int main(void)
unlink(szFileName);
exit(ret);
}" UNGETC_NOT_RETURN_EOF)
-check_cxx_source_runs("
-#include <stdlib.h>
-
-int main(void)
-{
- void *p;
-
- p = malloc(0);
-
- if (p == NULL)
- {
- exit(0);
- }
-
- exit(1);
-}" MALLOC_ZERO_RETURNS_NULL)
set(CMAKE_REQUIRED_LIBRARIES pthread)
check_cxx_source_runs("
#include <stdlib.h>
diff --git a/src/pal/src/cruntime/malloc.cpp b/src/pal/src/cruntime/malloc.cpp
index 2628a47ad4..36587dbd81 100644
--- a/src/pal/src/cruntime/malloc.cpp
+++ b/src/pal/src/cruntime/malloc.cpp
@@ -112,12 +112,13 @@ CorUnix::InternalMalloc(
{
void *pvMem;
pthrCurrent->suspensionInfo.EnterUnsafeRegion();
-#if MALLOC_ZERO_RETURNS_NULL
+
if (szSize == 0)
{
+ // malloc may return null for a requested size of zero bytes. Force a nonzero size to get a valid pointer.
szSize = 1;
}
-#endif
+
pvMem = (void*)malloc(szSize);
pthrCurrent->suspensionInfo.LeaveUnsafeRegion();
return pvMem;
diff --git a/src/pal/src/cruntime/wchar.cpp b/src/pal/src/cruntime/wchar.cpp
index 0eb211cc7f..17442d3de8 100644
--- a/src/pal/src/cruntime/wchar.cpp
+++ b/src/pal/src/cruntime/wchar.cpp
@@ -1450,7 +1450,7 @@ PAL_wcsncat( wchar_16 * strDest, const wchar_16 *strSource, size_t count )
static BOOL MISC_CRT_WCSTOD_IsValidCharacter( WCHAR c )
{
if ( c == '+' || c == '-' || c == '.' || ( c >= '0' && c <= '9' ) ||
- c == 'e' || c == 'E' || c == 'd' || c == 'd' )
+ c == 'e' || c == 'E' || c == 'd' || c == 'D' )
{
return TRUE;
}
diff --git a/src/pal/src/exception/seh-unwind.cpp b/src/pal/src/exception/seh-unwind.cpp
index 7a0a81fa3f..5a8c67160f 100644
--- a/src/pal/src/exception/seh-unwind.cpp
+++ b/src/pal/src/exception/seh-unwind.cpp
@@ -36,7 +36,9 @@ Abstract:
#endif // !__LINUX__
#include <libunwind.h>
#ifdef __LINUX__
+#ifdef HAVE_LIBUNWIND_PTRACE
#include <libunwind-ptrace.h>
+#endif // HAVE_LIBUNWIND_PTRACE
#endif // __LINUX__
#endif // HAVE_LIBUNWIND_H
@@ -327,7 +329,6 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP
#ifdef _AMD64_
#ifdef __LINUX__
-
static struct LibunwindCallbacksInfoType
{
CONTEXT *Context;
@@ -435,10 +436,31 @@ static int get_proc_name(unw_addr_space_t as, unw_word_t addr, char *bufp, size_
return -UNW_EINVAL;
}
+int find_proc_info(unw_addr_space_t as,
+ unw_word_t ip, unw_proc_info_t *pip,
+ int need_unwind_info, void *arg)
+{
+#ifdef HAVE_LIBUNWIND_PTRACE
+ // UNIXTODO: libunwind RPM package on Fedora/CentOS/RedHat doesn't have libunwind-ptrace.so
+ // and we can't use it from a shared library like libmscordaccore.so.
+ // That's why all calls to ptrace parts of libunwind ifdeffed out for now.
+ return _UPT_find_proc_info(as, ip, pip, need_unwind_info, arg);
+#else
+ return -UNW_EINVAL;
+#endif
+}
+
+void put_unwind_info(unw_addr_space_t as, unw_proc_info_t *pip, void *arg)
+{
+#ifdef HAVE_LIBUNWIND_PTRACE
+ return _UPT_put_unwind_info(as, pip, arg);
+#endif
+}
+
static unw_accessors_t unwind_accessors =
{
- .find_proc_info = _UPT_find_proc_info,
- .put_unwind_info = _UPT_put_unwind_info,
+ .find_proc_info = find_proc_info,
+ .put_unwind_info = put_unwind_info,
.get_dyn_info_list_addr = get_dyn_info_list_addr,
.access_mem = access_mem,
.access_reg = access_reg,
@@ -494,7 +516,9 @@ BOOL PAL_VirtualUnwindOutOfProc(CONTEXT *context,
LibunwindCallbacksInfo.readMemCallback = readMemCallback;
WinContextToUnwindContext(context, &unwContext);
addrSpace = unw_create_addr_space(&unwind_accessors, 0);
+#ifdef HAVE_LIBUNWIND_PTRACE
libunwindUptPtr = _UPT_create(pid);
+#endif
st = unw_init_remote(&cursor, addrSpace, libunwindUptPtr);
if (st < 0)
{
@@ -518,10 +542,12 @@ BOOL PAL_VirtualUnwindOutOfProc(CONTEXT *context,
result = TRUE;
Exit:
- if (libunwindUptPtr != nullptr)
+#ifdef HAVE_LIBUNWIND_PTRACE
+ if (libunwindUptPtr != NULL)
{
_UPT_destroy(libunwindUptPtr);
}
+#endif
if (addrSpace != 0)
{
unw_destroy_addr_space(addrSpace);
diff --git a/src/pal/src/include/pal/thread.hpp b/src/pal/src/include/pal/thread.hpp
index f84ee6eada..15d4f43ca1 100644
--- a/src/pal/src/include/pal/thread.hpp
+++ b/src/pal/src/include/pal/thread.hpp
@@ -342,6 +342,11 @@ namespace CorUnix
bool m_fStartStatus;
bool m_fStartStatusSet;
+ // Base address of the stack of this thread
+ void* m_stackBase;
+ // Limit address of the stack of this thread
+ void* m_stackLimit;
+
// The default stack size of a newly created thread (currently 256KB)
// when the dwStackSize paramter of PAL_CreateThread()
// is zero. This value can be set by setting the
@@ -408,7 +413,9 @@ namespace CorUnix
m_eThreadType(UserCreatedThread),
m_fStartItemsInitialized(FALSE),
m_fStartStatus(FALSE),
- m_fStartStatusSet(FALSE)
+ m_fStartStatusSet(FALSE),
+ m_stackBase(NULL),
+ m_stackLimit(NULL)
#ifdef FEATURE_PAL_SXS
, m_fInPal(TRUE)
#endif // FEATURE_PAL_SXS
@@ -646,6 +653,20 @@ namespace CorUnix
ReleaseThreadReference(
void
);
+
+ // Get base address of this thread's stack
+ // Can be called only for the current thread.
+ void *
+ GetStackBase(
+ void
+ );
+
+ // Get limit address of this thread's stack
+ // Can be called only for the current thread.
+ void *
+ GetStackLimit(
+ void
+ );
#ifdef FEATURE_PAL_SXS
//
diff --git a/src/pal/src/loader/module.cpp b/src/pal/src/loader/module.cpp
index 22a3a009de..29d8d19d82 100644
--- a/src/pal/src/loader/module.cpp
+++ b/src/pal/src/loader/module.cpp
@@ -96,8 +96,16 @@ char g_szCoreCLRPath[MAX_LONGPATH] = { 0 };
/* static function declarations ***********************************************/
+template<class TChar> bool LOADVerifyLibraryPath(const TChar *libraryPath);
+bool LOADConvertLibraryPathWideStringToMultibyteString(
+ LPCWSTR wideLibraryPath,
+ CHAR (&multibyteLibraryPath)[MAX_LONGPATH],
+ INT *multibyteLibraryPathLengthRef);
+
static BOOL LOADValidateModule(MODSTRUCT *module);
static LPWSTR LOADGetModuleFileName(MODSTRUCT *module);
+static HMODULE LOADLoadLibraryDirect(LPCSTR libraryNameOrPath, bool setLastError);
+static HMODULE LOADRegisterLibraryDirect(HMODULE dl_handle, LPCSTR libraryNameOrPath, BOOL fDynamic);
static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic);
static void LOAD_SEH_CallDllMain(MODSTRUCT *module, DWORD dwReason, LPVOID lpReserved);
static MODSTRUCT *LOADAllocModule(void *dl_handle, LPCSTR name);
@@ -161,17 +169,8 @@ LoadLibraryExA(
(lpLibFileName)?lpLibFileName:"NULL",
(lpLibFileName)?lpLibFileName:"NULL");
- if (NULL == lpLibFileName)
+ if (!LOADVerifyLibraryPath(lpLibFileName))
{
- ERROR("lpLibFileName is NULL;Exit.\n");
- SetLastError(ERROR_MOD_NOT_FOUND);
- goto Done;
- }
-
- if (lpLibFileName[0]=='\0')
- {
- ERROR("can't load library with NULL file name...\n");
- SetLastError(ERROR_INVALID_PARAMETER);
goto Done;
}
@@ -230,47 +229,116 @@ LoadLibraryExW(
lpLibFileName?lpLibFileName:W16_NULLSTRING,
lpLibFileName?lpLibFileName:W16_NULLSTRING);
- if (NULL == lpLibFileName)
+ if (!LOADVerifyLibraryPath(lpLibFileName))
{
- ERROR("lpLibFileName is NULL;Exit.\n");
- SetLastError(ERROR_MOD_NOT_FOUND);
goto done;
}
- if (lpLibFileName[0]==0)
+ if (!LOADConvertLibraryPathWideStringToMultibyteString(lpLibFileName, lpstr, &name_length))
{
- ERROR("Can't load library with NULL file name...\n");
- SetLastError(ERROR_INVALID_PARAMETER);
goto done;
}
/* do the Dos/Unix conversion on our own copy of the name */
+ FILEDosToUnixPathA(lpstr);
- name_length = WideCharToMultiByte(CP_ACP, 0, lpLibFileName, -1, lpstr,
- MAX_LONGPATH, NULL, NULL);
- if (name_length == 0)
+ /* let LOADLoadLibrary call SetLastError in case of failure */
+ hModule = LOADLoadLibrary(lpstr, TRUE);
+
+done:
+ LOGEXIT("LoadLibraryExW returns HMODULE %p\n", hModule);
+ PERF_EXIT(LoadLibraryExW);
+ return hModule;
+}
+
+/*
+Function:
+LoadLibraryDirect
+
+Loads a library using a system call, without registering the library with the module list.
+
+Returns the system handle to the loaded library, or nullptr upon failure (error is set via SetLastError()).
+*/
+HMODULE
+PALAPI
+PAL_LoadLibraryDirect(
+ IN LPCWSTR lpLibFileName)
+{
+ CHAR lpstr[MAX_LONGPATH];
+ INT name_length;
+ HMODULE hModule = NULL;
+
+ PERF_ENTRY(LoadLibraryDirect);
+ ENTRY("LoadLibraryDirect (lpLibFileName=%p (%S)) \n",
+ lpLibFileName?lpLibFileName:W16_NULLSTRING,
+ lpLibFileName?lpLibFileName:W16_NULLSTRING);
+
+ if (!LOADVerifyLibraryPath(lpLibFileName))
+ {
+ goto done;
+ }
+
+ if (!LOADConvertLibraryPathWideStringToMultibyteString(lpLibFileName, lpstr, &name_length))
{
- DWORD dwLastError = GetLastError();
- if (dwLastError == ERROR_INSUFFICIENT_BUFFER)
- {
- ERROR("lpLibFileName is larger than MAX_LONGPATH (%d)!\n", MAX_LONGPATH);
- }
- else
- {
- ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError);
- }
- SetLastError(ERROR_INVALID_PARAMETER);
goto done;
}
+ /* do the Dos/Unix conversion on our own copy of the name */
FILEDosToUnixPathA(lpstr);
- /* let LOADLoadLibrary call SetLastError in case of failure */
- hModule = LOADLoadLibrary(lpstr, TRUE);
+ /* let LOADLoadLibraryDirect call SetLastError in case of failure */
+ hModule = LOADLoadLibraryDirect(lpstr, true /* setLastError */);
done:
- LOGEXIT("LoadLibraryExW returns HMODULE %p\n", hModule);
- PERF_EXIT(LoadLibraryExW);
+ LOGEXIT("LoadLibraryDirect returns HMODULE %p\n", hModule);
+ PERF_EXIT(LoadLibraryDirect);
+ return hModule;
+}
+
+/*
+Function:
+RegisterLibraryDirect
+
+Registers a system handle to a loaded library with the module list.
+
+Returns a PAL handle to the loaded library, or nullptr upon failure (error is set via SetLastError()).
+*/
+HMODULE
+PALAPI
+PAL_RegisterLibraryDirect(
+ IN HMODULE dl_handle,
+ IN LPCWSTR lpLibFileName)
+{
+ CHAR lpstr[MAX_LONGPATH];
+ INT name_length;
+ HMODULE hModule = NULL;
+
+ PERF_ENTRY(RegisterLibraryDirect);
+ ENTRY("RegisterLibraryDirect (lpLibFileName=%p (%S)) \n",
+ lpLibFileName ? lpLibFileName : W16_NULLSTRING,
+ lpLibFileName ? lpLibFileName : W16_NULLSTRING);
+
+ if (!LOADVerifyLibraryPath(lpLibFileName))
+ {
+ goto done;
+ }
+
+ if (!LOADConvertLibraryPathWideStringToMultibyteString(lpLibFileName, lpstr, &name_length))
+ {
+ goto done;
+ }
+
+ /* do the Dos/Unix conversion on our own copy of the name */
+ FILEDosToUnixPathA(lpstr);
+
+ /* let LOADRegisterLibraryDirect call SetLastError in case of failure */
+ LockModuleList();
+ hModule = LOADRegisterLibraryDirect(dl_handle, lpstr, true /* fDynamic */);
+ UnlockModuleList();
+
+done:
+ LOGEXIT("RegisterLibraryDirect returns HMODULE %p\n", hModule);
+ PERF_EXIT(RegisterLibraryDirect);
return hModule;
}
@@ -1147,6 +1215,53 @@ done_nolock:
/* Static function definitions ************************************************/
+// Checks the library path for null or empty string. On error, calls SetLastError() and returns false.
+template<class TChar>
+bool LOADVerifyLibraryPath(const TChar *libraryPath)
+{
+ if (libraryPath == nullptr)
+ {
+ ERROR("libraryPath is null\n");
+ SetLastError(ERROR_MOD_NOT_FOUND);
+ return false;
+ }
+ if (libraryPath[0] == '\0')
+ {
+ ERROR("libraryPath is empty\n");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+ return true;
+}
+
+// Converts the wide char library path string into a multibyte-char string. On error, calls SetLastError() and returns false.
+bool LOADConvertLibraryPathWideStringToMultibyteString(
+ LPCWSTR wideLibraryPath,
+ CHAR(&multibyteLibraryPath)[MAX_LONGPATH],
+ INT *multibyteLibraryPathLengthRef)
+{
+ _ASSERTE(wideLibraryPath != nullptr);
+ _ASSERTE(multibyteLibraryPathLengthRef != nullptr);
+
+ *multibyteLibraryPathLengthRef = WideCharToMultiByte(CP_ACP, 0, wideLibraryPath, -1, multibyteLibraryPath,
+ MAX_LONGPATH, nullptr, nullptr);
+ if (*multibyteLibraryPathLengthRef == 0)
+ {
+ DWORD dwLastError = GetLastError();
+ if (dwLastError == ERROR_INSUFFICIENT_BUFFER)
+ {
+ ERROR("wideLibraryPath converted to a multibyte string is longer than MAX_LONGPATH (%d)!\n", MAX_LONGPATH);
+ }
+ else
+ {
+ ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError);
+ }
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+ return true;
+}
+
/*++
Function :
LOADValidateModule
@@ -1295,88 +1410,60 @@ static MODSTRUCT *LOADAllocModule(void *dl_handle, LPCSTR name)
return module;
}
-/*++
-Function :
- LOADLoadLibrary [internal]
-
- implementation of LoadLibrary (for use by the A/W variants)
+/*
+Function:
+ LOADLoadLibraryDirect [internal]
-Parameters :
- LPSTR shortAsciiName : name of module as specified to LoadLibrary
+ Loads a library using a system call, without registering the library with the module list.
- BOOL fDynamic : TRUE if dynamic load through LoadLibrary, FALSE if static load through RegisterLibrary
-
-Return value :
- handle to loaded module
+Parameters:
+ LPCSTR libraryNameOrPath: The library to load.
+ bool setLastError: True to set the last error upon failure, false otherwise.
---*/
-static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic)
+Return value:
+ System handle to the loaded library, or nullptr upon failure (error is set via SetLastError() if 'setLastError' is true).
+*/
+static HMODULE LOADLoadLibraryDirect(LPCSTR libraryNameOrPath, bool setLastError)
{
- CHAR fullLibraryName[MAX_LONGPATH];
- MODSTRUCT *module = NULL;
- void *dl_handle = NULL;
- DWORD dwError;
- DWORD retval;
-
- // Check whether we have been requested to load 'libc'. If that's the case then use the
- // full name of the library that is defined in <gnu/lib-names.h> by the LIBC_SO constant.
- // The problem is that calling dlopen("libc.so") will fail for libc even thought it works
- // for other libraries. The reason is that libc.so is just linker script (i.e. a test file).
- // As a result, we have to use the full name (i.e. lib.so.6) that is defined by LIBC_SO.
- if (strcmp(shortAsciiName, LIBC_NAME_WITHOUT_EXTENSION) == 0)
- {
-#if defined(__APPLE__)
- shortAsciiName = "libc.dylib";
-#elif defined(__FreeBSD__)
- shortAsciiName = FREEBSD_LIBC;
-#else
- shortAsciiName = LIBC_SO;
-#endif
- }
-
- LockModuleList();
+ _ASSERTE(libraryNameOrPath != nullptr);
+ _ASSERTE(libraryNameOrPath[0] != '\0');
- // See if file can be dlopen()ed; this should work even if it's already loaded
+ HMODULE dl_handle = dlopen(libraryNameOrPath, RTLD_LAZY);
+ if (dl_handle != nullptr)
{
- // See GetProcAddress for an explanation why we leave the PAL.
- PAL_LeaveHolder holder;
-
- // P/Invokes are often declared with variations on the actual library name.
- // For example, it's common to leave off the extension/suffix of the library
- // even if it has one, or to leave off a prefix like "lib" even if it has one
- // (both of these are done typically to smooth over cross-platform differences).
- // We try to dlopen with such variations on the original.
- const char* const formatStrings[4] = // used with args: PAL_SHLIB_PREFIX, shortAsciiName, PAL_SHLIB_SUFFIX
- {
- "%s%s%s", // prefix+name+suffix
- "%.0s%s%.0s", // name
- "%.0s%s%s", // name+suffix
- "%s%s%.0s", // prefix+name
- };
- const int skipPrefixing = strchr(shortAsciiName, '/') != NULL; // skip prefixing if the name is actually a path
- for (int i = 0; i < 4; i++)
- {
- if (skipPrefixing && (i == 0 || i == 3)) // 0th and 3rd strings include prefixes
- continue;
-
- if (!dl_handle &&
- snprintf(fullLibraryName, MAX_LONGPATH, formatStrings[i], PAL_SHLIB_PREFIX, shortAsciiName, PAL_SHLIB_SUFFIX) < MAX_LONGPATH &&
- ((dl_handle = dlopen(fullLibraryName, RTLD_LAZY | RTLD_NOLOAD)) ||
- (dl_handle = dlopen(fullLibraryName, RTLD_LAZY))))
- {
- shortAsciiName = fullLibraryName;
- break;
- }
- }
+ TRACE("dlopen() found module %s\n", libraryNameOrPath);
}
-
- if (!dl_handle)
+ else if (setLastError)
{
- WARN("dlopen() failed; dlerror says '%s'\n", dlerror());
+ WARN("dlopen() failed; dlerror says '%s'\n", dlerror());
SetLastError(ERROR_MOD_NOT_FOUND);
- goto done;
}
- TRACE("dlopen() found module %s\n", shortAsciiName);
+
+ return dl_handle;
+}
+
+/*
+Function:
+ LOADRegisterLibraryDirect [internal]
+
+ Registers a system handle to a loaded library with the module list.
+
+Parameters:
+ HMODULE dl_handle: System handle to the loaded library.
+ LPCSTR libraryNameOrPath: The library that was loaded.
+ BOOL fDynamic: TRUE if dynamic load through LoadLibrary, FALSE if static load through RegisterLibrary.
+
+Return value:
+ PAL handle to the loaded library, or nullptr upon failure (error is set via SetLastError()).
+*/
+static HMODULE LOADRegisterLibraryDirect(HMODULE dl_handle, LPCSTR libraryNameOrPath, BOOL fDynamic)
+{
+ _ASSERTE(dl_handle != nullptr);
+ _ASSERTE(libraryNameOrPath != nullptr);
+ _ASSERTE(libraryNameOrPath[0] != '\0');
+
+ MODSTRUCT *module;
+ DWORD dwError;
#if !RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN
/* search module list for a match. */
@@ -1388,25 +1475,25 @@ static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic)
/* found the handle. increment the refcount and return the
existing module structure */
TRACE("Found matching module %p for module name %s\n",
- module, shortAsciiName);
+ module, libraryNameOrPath);
if (module->refcount != -1)
module->refcount++;
dlclose(dl_handle);
- goto done;
+ return module;
}
module = module->next;
} while (module != &exe_module);
#endif
- TRACE("Module doesn't exist : creating %s.\n", shortAsciiName);
- module = LOADAllocModule(dl_handle, shortAsciiName);
+ TRACE("Module doesn't exist : creating %s.\n", libraryNameOrPath);
+ module = LOADAllocModule(dl_handle, libraryNameOrPath);
if (NULL == module)
{
ERROR("couldn't create new module\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
dlclose(dl_handle);
- goto done;
+ return nullptr;
}
/* Add the new module on to the end of the list */
@@ -1441,7 +1528,7 @@ static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic)
PREGISTER_MODULE registerModule = (PREGISTER_MODULE)dlsym(module->dl_handle, "PAL_RegisterModule");
if (registerModule)
{
- module->hinstance = registerModule(shortAsciiName);
+ module->hinstance = registerModule(libraryNameOrPath);
}
else
{
@@ -1452,6 +1539,7 @@ static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic)
}
}
+ BOOL dllMainRetVal;
{
#if !_NO_DEBUG_MESSAGES_
/* reset ENTRY nesting level back to zero while inside the callback... */
@@ -1463,7 +1551,7 @@ static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic)
// This module may be foreign to our PAL, so leave our PAL.
// If it depends on us, it will re-enter.
PAL_LeaveHolder holder;
- retval = module->pDllMain(module->hinstance, DLL_PROCESS_ATTACH, fDynamic ? NULL : (LPVOID)-1);
+ dllMainRetVal = module->pDllMain(module->hinstance, DLL_PROCESS_ATTACH, fDynamic ? NULL : (LPVOID)-1);
}
#if !_NO_DEBUG_MESSAGES_
@@ -1473,14 +1561,14 @@ static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic)
}
// If DlMain(DLL_PROCESS_ATTACH) returns FALSE, we must immediately unload the module
- if (!retval)
+ if (!dllMainRetVal)
{
ERROR("DllMain returned FALSE; unloading module.\n");
module->pDllMain = NULL;
FreeLibrary((HMODULE)module);
SetLastError(ERROR_DLL_INIT_FAILED);
module = NULL;
- goto done;
+ return nullptr;
}
}
else
@@ -1488,9 +1576,96 @@ static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic)
TRACE("Module does not contain a DllMain function.\n");
}
+ return module;
+}
+
+/*++
+Function :
+ LOADLoadLibrary [internal]
+
+ implementation of LoadLibrary (for use by the A/W variants)
+
+Parameters :
+ LPSTR shortAsciiName : name of module as specified to LoadLibrary
+
+ BOOL fDynamic : TRUE if dynamic load through LoadLibrary, FALSE if static load through RegisterLibrary
+
+Return value :
+ handle to loaded module
+
+--*/
+static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic)
+{
+ CHAR fullLibraryName[MAX_LONGPATH];
+ HMODULE module = NULL;
+ HMODULE dl_handle = NULL;
+
+ // Check whether we have been requested to load 'libc'. If that's the case then use the
+ // full name of the library that is defined in <gnu/lib-names.h> by the LIBC_SO constant.
+ // The problem is that calling dlopen("libc.so") will fail for libc even thought it works
+ // for other libraries. The reason is that libc.so is just linker script (i.e. a test file).
+ // As a result, we have to use the full name (i.e. lib.so.6) that is defined by LIBC_SO.
+ if (strcmp(shortAsciiName, LIBC_NAME_WITHOUT_EXTENSION) == 0)
+ {
+#if defined(__APPLE__)
+ shortAsciiName = "libc.dylib";
+#elif defined(__FreeBSD__)
+ shortAsciiName = FREEBSD_LIBC;
+#else
+ shortAsciiName = LIBC_SO;
+#endif
+ }
+
+ LockModuleList();
+
+ // See if file can be dlopen()ed; this should work even if it's already loaded
+ {
+ // See GetProcAddress for an explanation why we leave the PAL.
+ PAL_LeaveHolder holder;
+
+ // P/Invokes are often declared with variations on the actual library name.
+ // For example, it's common to leave off the extension/suffix of the library
+ // even if it has one, or to leave off a prefix like "lib" even if it has one
+ // (both of these are done typically to smooth over cross-platform differences).
+ // We try to dlopen with such variations on the original.
+ const char* const formatStrings[4] = // used with args: PAL_SHLIB_PREFIX, shortAsciiName, PAL_SHLIB_SUFFIX
+ {
+ "%s%s%s", // prefix+name+suffix
+ "%.0s%s%.0s", // name
+ "%.0s%s%s", // name+suffix
+ "%s%s%.0s", // prefix+name
+ };
+ const int skipPrefixing = strchr(shortAsciiName, '/') != NULL; // skip prefixing if the name is actually a path
+ for (int i = 0; i < 4; i++)
+ {
+ if (skipPrefixing && (i == 0 || i == 3)) // 0th and 3rd strings include prefixes
+ continue;
+
+ _ASSERTE(dl_handle == nullptr);
+ if (snprintf(fullLibraryName, MAX_LONGPATH, formatStrings[i], PAL_SHLIB_PREFIX, shortAsciiName, PAL_SHLIB_SUFFIX) < MAX_LONGPATH)
+ {
+ dl_handle = LOADLoadLibraryDirect(fullLibraryName, false /* setLastError */);
+ if (dl_handle != nullptr)
+ {
+ shortAsciiName = fullLibraryName;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!dl_handle)
+ {
+ WARN("dlopen() failed; dlerror says '%s'\n", dlerror());
+ SetLastError(ERROR_MOD_NOT_FOUND);
+ goto done;
+ }
+
+ module = LOADRegisterLibraryDirect(dl_handle, shortAsciiName, fDynamic);
+
done:
UnlockModuleList();
- return (HMODULE)module;
+ return module;
}
/*++
diff --git a/src/pal/src/memory/heap.cpp b/src/pal/src/memory/heap.cpp
index b85e02fd77..5cc59d0c91 100644
--- a/src/pal/src/memory/heap.cpp
+++ b/src/pal/src/memory/heap.cpp
@@ -26,7 +26,6 @@ Revision History:
#include "pal/handlemgr.hpp"
#include "pal/corunix.hpp"
#include <errno.h>
-#define HEAP_SIZEINFO_SIZE (2 * sizeof(DWORD))
using namespace CorUnix;
SET_DEFAULT_DEBUG_CHANNEL(MEM);
@@ -36,12 +35,10 @@ SET_DEFAULT_DEBUG_CHANNEL(MEM);
// should be placed after the SET_DEFAULT_DEBUG_CHANNEL(MEM)
#include <safemath.h>
-#define HEAP_MAGIC 0xEAFDC9BB
#ifndef __APPLE__
#define DUMMY_HEAP 0x01020304
#endif // __APPLE__
-
#ifdef __APPLE__
#define CACHE_HEAP_ZONE
#endif // __APPLE__
@@ -192,33 +189,6 @@ GetProcessHeap(
/*++
Function:
-HeapSize
-
-See MSDN doc.
---*/
-SIZE_T
-PALAPI
-HeapSize(
- HANDLE hHeap,
- DWORD dwFlags,
- LPCVOID lpMem)
-{
- SIZE_T ret = (SIZE_T)-1;
- PERF_ENTRY(HeapSize);
- ENTRY("HeapSize(hHeap=%p, dwFlags=%#x, lpMem=%p)\n",
- hHeap, dwFlags, lpMem);
-
- // First four bytes contain magic
- // Second four bytes size.
- ret = ((DWORD *)(static_cast<LPCBYTE>(lpMem) - HEAP_SIZEINFO_SIZE))[1];
-
- LOGEXIT("HeapSize returning %d\n", ret);
- PERF_EXIT(HeapSize);
- return ret;
-}
-
-/*++
-Function:
HeapAlloc
Abstract
@@ -229,15 +199,15 @@ See MSDN doc.
LPVOID
PALAPI
HeapAlloc(
- IN HANDLE hHeap,
- IN DWORD dwFlags,
- IN SIZE_T dwBytes)
+ IN HANDLE hHeap,
+ IN DWORD dwFlags,
+ IN SIZE_T numberOfBytes)
{
BYTE *pMem;
PERF_ENTRY(HeapAlloc);
- ENTRY("HeapAlloc (hHeap=%p, dwFlags=%#x, dwBytes=%u)\n",
- hHeap, dwFlags, dwBytes);
+ ENTRY("HeapAlloc (hHeap=%p, dwFlags=%#x, numberOfBytes=%u)\n",
+ hHeap, dwFlags, numberOfBytes);
#ifdef __APPLE__
if (hHeap == NULL)
@@ -261,26 +231,16 @@ HeapAlloc(
return NULL;
}
-
- size_t fullsize;
- if (!ClrSafeInt<size_t>::addition(dwBytes, HEAP_SIZEINFO_SIZE,fullsize))
- {
- ERROR("Integer Overflow\n");
- SetLastError(ERROR_ARITHMETIC_OVERFLOW);
- LOGEXIT("HeapAlloc returning NULL\n");
- PERF_EXIT(HeapAlloc);
- return NULL;
- }
#ifdef __APPLE__
// This is patterned off of InternalMalloc in malloc.cpp.
{
CPalThread *pthrCurrent = InternalGetCurrentThread();
pthrCurrent->suspensionInfo.EnterUnsafeRegion();
- pMem = (BYTE *)malloc_zone_malloc((malloc_zone_t *)hHeap, fullsize);
+ pMem = (BYTE *)malloc_zone_malloc((malloc_zone_t *)hHeap, numberOfBytes);
pthrCurrent->suspensionInfo.LeaveUnsafeRegion();
}
#else // __APPLE__
- pMem = (BYTE *) PAL_malloc(fullsize);
+ pMem = (BYTE *) PAL_malloc(numberOfBytes);
#endif // __APPLE__ else
if (pMem == NULL)
@@ -292,20 +252,15 @@ HeapAlloc(
return NULL;
}
- /* use a magic number, to know it has been allocated with HeapAlloc
- when doing HeapFree */
- ((DWORD *) pMem)[0] = HEAP_MAGIC;
- /* Store the size in the second word */
- ((DWORD *)pMem)[1] = dwBytes;
-
- /*If the Heap Zero memory flag is set initialize to zero*/
+ /* If the HEAP_ZERO_MEMORY flag is set initialize to zero */
if (dwFlags == HEAP_ZERO_MEMORY)
{
- memset(pMem+ HEAP_SIZEINFO_SIZE, 0, dwBytes);
+ memset(pMem, 0, numberOfBytes);
}
- LOGEXIT("HeapAlloc returning LPVOID %p\n", pMem + HEAP_SIZEINFO_SIZE);
+
+ LOGEXIT("HeapAlloc returning LPVOID %p\n", pMem);
PERF_EXIT(HeapAlloc);
- return (pMem + HEAP_SIZEINFO_SIZE);
+ return (pMem);
}
@@ -321,9 +276,9 @@ See MSDN doc.
BOOL
PALAPI
HeapFree(
- IN HANDLE hHeap,
- IN DWORD dwFlags,
- IN LPVOID lpMem)
+ IN HANDLE hHeap,
+ IN DWORD dwFlags,
+ IN LPVOID lpMem)
{
BOOL bRetVal = FALSE;
@@ -349,23 +304,12 @@ HeapFree(
goto done;
}
- if ( !lpMem )
+ if (!lpMem)
{
bRetVal = TRUE;
goto done;
}
- /*HEAP_SIZEINFO_SIZE + nMemAlloc is the size of Magic Number plus
- *size of the int to store value of Memory allocated */
- lpMem = static_cast<LPVOID>(static_cast<LPBYTE>(lpMem) - HEAP_SIZEINFO_SIZE);
-
- /* check if the memory has been allocated by HeapAlloc */
- if (*((DWORD *) lpMem) != HEAP_MAGIC)
- {
- ERROR("Pointer hasn't been allocated with HeapAlloc (%p)\n",
- static_cast<LPBYTE>(lpMem) + HEAP_SIZEINFO_SIZE);
- SetLastError(ERROR_INVALID_PARAMETER);
- goto done;
- }
+
*((DWORD *) lpMem) = 0;
bRetVal = TRUE;
@@ -400,21 +344,21 @@ See MSDN doc.
LPVOID
PALAPI
HeapReAlloc(
- IN HANDLE hHeap,
- IN DWORD dwFlags,
- IN LPVOID lpmem,
- IN SIZE_T dwBytes)
+ IN HANDLE hHeap,
+ IN DWORD dwFlags,
+ IN LPVOID lpmem,
+ IN SIZE_T numberOfBytes)
{
BYTE *pMem = NULL;
PERF_ENTRY(HeapReAlloc);
- ENTRY("HeapReAlloc (hHeap=%p, dwFlags=%#x, lpmem=%p, dwBytes=%u)\n",
- hHeap, dwFlags, lpmem, dwBytes);
+ ENTRY("HeapReAlloc (hHeap=%p, dwFlags=%#x, lpmem=%p, numberOfBytes=%u)\n",
+ hHeap, dwFlags, lpmem, numberOfBytes);
#ifdef __APPLE__
if (hHeap == NULL)
#else // __APPLE__
- if (hHeap != (HANDLE) DUMMY_HEAP)
+ if (hHeap != (HANDLE)DUMMY_HEAP)
#endif // __APPLE__ else
{
ASSERT("Invalid heap handle\n");
@@ -438,26 +382,10 @@ HeapReAlloc(
goto done;
}
- /*HEAP_SIZEINFO_SIZE + nMemAlloc is the size of Magic Number plus
- *size of the int to store value of Memory allocated */
- lpmem = static_cast<LPVOID>(static_cast<LPBYTE>(lpmem) - HEAP_SIZEINFO_SIZE);
-
- /* check if the memory has been allocated by HeapAlloc */
- if (*((DWORD *) lpmem) != HEAP_MAGIC)
+ if(numberOfBytes == 0)
{
- ERROR("Pointer hasn't been allocated with HeapAlloc (%p)\n",
- static_cast<LPBYTE>(lpmem) + HEAP_SIZEINFO_SIZE);
- SetLastError(ERROR_INVALID_PARAMETER);
- goto done;
- }
-
-
- size_t fullsize;
- if (!ClrSafeInt<size_t>::addition(dwBytes, HEAP_SIZEINFO_SIZE, fullsize))
- {
- ERROR("Integer Overflow\n");
- SetLastError(ERROR_ARITHMETIC_OVERFLOW);
- goto done;
+ // PAL's realloc behaves like free for a requested size of zero bytes. Force a nonzero size to get a valid pointer.
+ numberOfBytes = 1;
}
#ifdef __APPLE__
@@ -465,11 +393,11 @@ HeapReAlloc(
{
CPalThread *pthrCurrent = InternalGetCurrentThread();
pthrCurrent->suspensionInfo.EnterUnsafeRegion();
- pMem = (BYTE *) malloc_zone_realloc((malloc_zone_t *)hHeap, lpmem, fullsize);
+ pMem = (BYTE *) malloc_zone_realloc((malloc_zone_t *)hHeap, lpmem, numberOfBytes);
pthrCurrent->suspensionInfo.LeaveUnsafeRegion();
}
#else // __APPLE__
- pMem = (BYTE *) PAL_realloc(lpmem,fullsize);
+ pMem = (BYTE *) PAL_realloc(lpmem, numberOfBytes);
#endif // __APPLE__ else
if (pMem == NULL)
@@ -479,14 +407,10 @@ HeapReAlloc(
goto done;
}
- /* use a magic number, to know it has been allocated with HeapAlloc
- when doing HeapFree */
- *((DWORD *) pMem) = HEAP_MAGIC;
-
done:
- LOGEXIT("HeapReAlloc returns LPVOID %p\n", pMem ? (pMem + HEAP_SIZEINFO_SIZE) : pMem);
+ LOGEXIT("HeapReAlloc returns LPVOID %p\n", pMem);
PERF_EXIT(HeapReAlloc);
- return pMem ? (pMem + HEAP_SIZEINFO_SIZE) : pMem;
+ return pMem;
}
BOOL
diff --git a/src/pal/src/misc/perftrace.cpp b/src/pal/src/misc/perftrace.cpp
index d2bfd797cf..d4223a629a 100644
--- a/src/pal/src/misc/perftrace.cpp
+++ b/src/pal/src/misc/perftrace.cpp
@@ -785,7 +785,7 @@ PERFReadSetting( )
//more code is required to deal with corrupted input file.
BOOL ret;
unsigned int index;
- char line[256 /* PAL_PERF_MAX_INPUT */]; // just use it. can define a new one like MAX_LINE=1024;
+ char line[PAL_PERF_MAX_INPUT];
char * ptr;
char function_name[PAL_PERF_MAX_FUNCTION_NAME]; //no function can be longer than 127 bytes.
diff --git a/src/pal/src/misc/stackstring.cpp b/src/pal/src/misc/stackstring.cpp
new file mode 100644
index 0000000000..d35c0d88fc
--- /dev/null
+++ b/src/pal/src/misc/stackstring.cpp
@@ -0,0 +1,138 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include "pal/malloc.hpp"
+#include "pal/dbgmsg.h"
+
+SET_DEFAULT_DEBUG_CHANNEL(MISC);
+
+template <SIZE_T STACKCOUNT>
+class StackString
+{
+private:
+ WCHAR m_innerBuffer[STACKCOUNT + 1];
+ WCHAR * m_buffer;
+ SIZE_T m_count; // actual allocated count
+
+ void NullTerminate()
+ {
+ m_buffer[m_count] = W('\0');
+ }
+
+ void DeleteBuffer()
+ {
+ if (m_innerBuffer != m_buffer)
+ PAL_free(m_buffer);
+
+ m_buffer = NULL;
+ return;
+ }
+
+ void ReallocateBuffer(SIZE_T count)
+ {
+ // count is always > STACKCOUNT here.
+ WCHAR * newBuffer = (WCHAR *)PAL_malloc((count + 1) * sizeof(WCHAR));
+ if (NULL == newBuffer)
+ {
+ ERROR("malloc failed\n");
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+
+ DeleteBuffer();
+ m_count = 0;
+
+ return;
+ }
+
+ DeleteBuffer();
+ m_buffer = newBuffer;
+ m_count = count;
+
+ return;
+ }
+
+ void Resize(SIZE_T count)
+ {
+ if (NULL == m_buffer)
+ {
+ if (count > STACKCOUNT)
+ {
+ ReallocateBuffer(count);
+ }
+ else
+ {
+ m_buffer = m_innerBuffer;
+ m_count = count;
+ }
+ }
+ else if (m_innerBuffer == m_buffer)
+ {
+ if (count > STACKCOUNT)
+ ReallocateBuffer(count);
+ else
+ m_count = count;
+ }
+ else
+ {
+ ReallocateBuffer(count);
+ }
+
+ return;
+ }
+
+ StackString(const StackString &s)
+ {
+ Set(s);
+ }
+
+ ~StackString()
+ {
+ DeleteBuffer();
+ }
+
+public:
+ StackString()
+ : m_count(0), m_buffer(m_innerBuffer)
+ {
+ }
+
+ BOOL Set(const WCHAR * buffer, SIZE_T count)
+ {
+ Resize(count);
+ if (NULL == m_buffer)
+ return FALSE;
+
+ CopyMemory(m_buffer, buffer, (count + 1) * sizeof(WCHAR));
+ NullTerminate();
+ return TRUE;
+ }
+
+ BOOL Set(const StackString &s)
+ {
+ return Set(s.m_buffer, s.m_count);
+ }
+
+ SIZE_T Getcount() const
+ {
+ return m_count;
+ }
+
+ CONST WCHAR * GetString() const
+ {
+ return (const WCHAR *)m_buffer;
+ }
+
+ WCHAR * OpenStringBuffer(SIZE_T count)
+ {
+ Resize(count);
+ return (WCHAR *)m_buffer;
+ }
+
+ void CloseBuffer(SIZE_T count)
+ {
+ if (m_count > count)
+ m_count = count;
+
+ NullTerminate();
+ return;
+ }
+};
diff --git a/src/pal/src/thread/thread.cpp b/src/pal/src/thread/thread.cpp
index a1c6eb6c14..4bda53f3f5 100644
--- a/src/pal/src/thread/thread.cpp
+++ b/src/pal/src/thread/thread.cpp
@@ -2428,79 +2428,108 @@ ThreadInitializationRoutine(
return NO_ERROR;
}
+// Get base address of this thread's stack
+// Can be called only for the current thread.
void *
-PALAPI
-PAL_GetStackBase()
+CPalThread::GetStackBase()
{
+ _ASSERT_MSG(this == InternalGetCurrentThread(), "CPalThread::GetStackBase called from foreign thread");
+
+ if (m_stackBase == NULL)
+ {
#ifdef _TARGET_MAC64
- // This is a Mac specific method
- return pthread_get_stackaddr_np(pthread_self());
+ // This is a Mac specific method
+ m_stackBase = pthread_get_stackaddr_np(pthread_self());
#else
- pthread_attr_t attr;
- void* stackAddr;
- size_t stackSize;
- int status;
-
- pthread_t thread = pthread_self();
-
- status = pthread_attr_init(&attr);
- _ASSERT_MSG(status == 0, "pthread_attr_init call failed");
+ pthread_attr_t attr;
+ void* stackAddr;
+ size_t stackSize;
+ int status;
+
+ pthread_t thread = pthread_self();
+
+ status = pthread_attr_init(&attr);
+ _ASSERT_MSG(status == 0, "pthread_attr_init call failed");
#if HAVE_PTHREAD_ATTR_GET_NP
- status = pthread_attr_get_np(thread, &attr);
+ status = pthread_attr_get_np(thread, &attr);
#elif HAVE_PTHREAD_GETATTR_NP
- status = pthread_getattr_np(thread, &attr);
+ status = pthread_getattr_np(thread, &attr);
#else
#error Dont know how to get thread attributes on this platform!
#endif
- _ASSERT_MSG(status == 0, "pthread_getattr_np call failed");
+ _ASSERT_MSG(status == 0, "pthread_getattr_np call failed");
- status = pthread_attr_getstack(&attr, &stackAddr, &stackSize);
- _ASSERT_MSG(status == 0, "pthread_attr_getstack call failed");
+ status = pthread_attr_getstack(&attr, &stackAddr, &stackSize);
+ _ASSERT_MSG(status == 0, "pthread_attr_getstack call failed");
- status = pthread_attr_destroy(&attr);
- _ASSERT_MSG(status == 0, "pthread_attr_destroy call failed");
+ status = pthread_attr_destroy(&attr);
+ _ASSERT_MSG(status == 0, "pthread_attr_destroy call failed");
- return (void*)((size_t)stackAddr + stackSize);
+ m_stackBase = (void*)((size_t)stackAddr + stackSize);
#endif
+ }
+
+ return m_stackBase;
}
+// Get limit address of this thread's stack.
+// Can be called only for the current thread.
void *
-PALAPI
-PAL_GetStackLimit()
+CPalThread::GetStackLimit()
{
+ _ASSERT_MSG(this == InternalGetCurrentThread(), "CPalThread::GetStackLimit called from foreign thread");
+
+ if (m_stackLimit == NULL)
+ {
#ifdef _TARGET_MAC64
- // This is a Mac specific method
- return ((BYTE *)pthread_get_stackaddr_np(pthread_self()) -
- pthread_get_stacksize_np(pthread_self()));
+ // This is a Mac specific method
+ m_stackLimit = ((BYTE *)pthread_get_stackaddr_np(pthread_self()) -
+ pthread_get_stacksize_np(pthread_self()));
#else
- pthread_attr_t attr;
- void* stackAddr;
- size_t stackSize;
- int status;
-
- pthread_t thread = pthread_self();
-
- status = pthread_attr_init(&attr);
- _ASSERT_MSG(status == 0, "pthread_attr_init call failed");
+ pthread_attr_t attr;
+ size_t stackSize;
+ int status;
+
+ pthread_t thread = pthread_self();
+
+ status = pthread_attr_init(&attr);
+ _ASSERT_MSG(status == 0, "pthread_attr_init call failed");
#if HAVE_PTHREAD_ATTR_GET_NP
- status = pthread_attr_get_np(thread, &attr);
+ status = pthread_attr_get_np(thread, &attr);
#elif HAVE_PTHREAD_GETATTR_NP
- status = pthread_getattr_np(thread, &attr);
+ status = pthread_getattr_np(thread, &attr);
#else
#error Dont know how to get thread attributes on this platform!
#endif
- _ASSERT_MSG(status == 0, "pthread_getattr_np call failed");
+ _ASSERT_MSG(status == 0, "pthread_getattr_np call failed");
- status = pthread_attr_getstack(&attr, &stackAddr, &stackSize);
- _ASSERT_MSG(status == 0, "pthread_attr_getstack call failed");
+ status = pthread_attr_getstack(&attr, &m_stackLimit, &stackSize);
+ _ASSERT_MSG(status == 0, "pthread_attr_getstack call failed");
- status = pthread_attr_destroy(&attr);
- _ASSERT_MSG(status == 0, "pthread_attr_destroy call failed");
-
- return stackAddr;
+ status = pthread_attr_destroy(&attr);
+ _ASSERT_MSG(status == 0, "pthread_attr_destroy call failed");
#endif
+ }
+
+ return m_stackLimit;
+}
+
+void *
+PALAPI
+PAL_GetStackBase()
+{
+ CPalThread* thread = InternalGetCurrentThread();
+ return thread->GetStackBase();
+}
+
+void *
+PALAPI
+PAL_GetStackLimit()
+{
+ CPalThread* thread = InternalGetCurrentThread();
+ return thread->GetStackLimit();
}
PAL_ERROR InjectActivationInternal(CorUnix::CPalThread* pThread);
diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.c b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.c
index 896934065b..7c825375eb 100644
--- a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.c
+++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.c
@@ -317,7 +317,7 @@ void starttests(int threadID)
ULONGLONG startTime = 0;
ULONGLONG endTime = 0;
- LONG volatile * Destination;
+ LONG volatile Destination;
LONG Exchange;
LONG Comperand;
LONG result;
@@ -336,10 +336,10 @@ void starttests(int threadID)
for (i=0;i<REPEAT_COUNT;i++)
{
- *Destination = (LONG volatile) threadID;
+ Destination = (LONG volatile) threadID;
Exchange = (LONG) i;
Comperand = (LONG) threadID;
- result = InterlockedCompareExchange( Destination, Exchange, Comperand);
+ result = InterlockedCompareExchange(&Destination, Exchange, Comperand);
if( i != result )
{
diff --git a/src/tools/crossgen/crossgen.cpp b/src/tools/crossgen/crossgen.cpp
index 192f6b1bf8..9bdfdd7294 100644
--- a/src/tools/crossgen/crossgen.cpp
+++ b/src/tools/crossgen/crossgen.cpp
@@ -282,7 +282,7 @@ bool ComputeMscorlibPathFromTrustedPlatformAssemblies(LPWSTR pwzMscorlibPath, DW
{
LPWSTR wszTrustedPathCopy = new WCHAR[wcslen(pwzTrustedPlatformAssemblies) + 1];
wcscpy_s(wszTrustedPathCopy, wcslen(pwzTrustedPlatformAssemblies) + 1, pwzTrustedPlatformAssemblies);
- LPWSTR wszSingleTrustedPath = wcstok(wszTrustedPathCopy, W(";"));
+ LPWSTR wszSingleTrustedPath = wcstok(wszTrustedPathCopy, PATH_SEPARATOR_STR_W);
while (wszSingleTrustedPath != NULL)
{
@@ -294,12 +294,12 @@ bool ComputeMscorlibPathFromTrustedPlatformAssemblies(LPWSTR pwzMscorlibPath, DW
wszSingleTrustedPath++;
}
- if (StringEndsWith(wszSingleTrustedPath, W("\\mscorlib.dll")) ||
- StringEndsWith(wszSingleTrustedPath, W("\\mscorlib.ni.dll")))
+ if (StringEndsWith(wszSingleTrustedPath, DIRECTORY_SEPARATOR_STR_W W("mscorlib.dll")) ||
+ StringEndsWith(wszSingleTrustedPath, DIRECTORY_SEPARATOR_STR_W W("mscorlib.ni.dll")))
{
wcscpy_s(pwzMscorlibPath, cbMscorlibPath, wszSingleTrustedPath);
- LPWSTR pwzSeparator = wcsrchr(pwzMscorlibPath, W('\\'));
+ LPWSTR pwzSeparator = wcsrchr(pwzMscorlibPath, DIRECTORY_SEPARATOR_CHAR_W);
if (pwzSeparator == NULL)
{
delete [] wszTrustedPathCopy;
@@ -311,7 +311,7 @@ bool ComputeMscorlibPathFromTrustedPlatformAssemblies(LPWSTR pwzMscorlibPath, DW
return true;
}
- wszSingleTrustedPath = wcstok(NULL, W(";"));
+ wszSingleTrustedPath = wcstok(NULL, PATH_SEPARATOR_STR_W);
}
delete [] wszTrustedPathCopy;
@@ -370,7 +370,7 @@ void PopulateTPAList(SString path, LPCWSTR pwszMask, SString &refTPAList, bool f
if (fAddDelimiter)
{
// Add the path delimiter if we already have entries in the TPAList
- refTPAList.Append(W(";"));
+ refTPAList.Append(PATH_SEPARATOR_CHAR_W);
}
// Add the path to the TPAList
refTPAList.Append(path);
@@ -400,7 +400,7 @@ void ComputeTPAListFromPlatformAssembliesPath(LPCWSTR pwzPlatformAssembliesPaths
while (itr != end)
{
start = itr;
- BOOL found = ssPlatformAssembliesPath.Find(itr, W(';'));
+ BOOL found = ssPlatformAssembliesPath.Find(itr, PATH_SEPARATOR_CHAR_W);
if (!found)
{
itr = end;
@@ -417,9 +417,9 @@ void ComputeTPAListFromPlatformAssembliesPath(LPCWSTR pwzPlatformAssembliesPaths
if (len > 0)
{
- if (qualifiedPath[len-1]!='\\')
+ if (qualifiedPath[len-1]!=DIRECTORY_SEPARATOR_CHAR_W)
{
- qualifiedPath.Append('\\');
+ qualifiedPath.Append(DIRECTORY_SEPARATOR_CHAR_W);
}
// Enumerate the EXE/DLL modules within this path and add them to the TPAList
diff --git a/src/utilcode/dlwrap.cpp b/src/utilcode/dlwrap.cpp
index f649e5267b..10acc61b76 100644
--- a/src/utilcode/dlwrap.cpp
+++ b/src/utilcode/dlwrap.cpp
@@ -86,6 +86,7 @@ VerQueryValueW_NoThrow(
// is available, and then it will remove unused functions.
// Instead of specifying all libs for imported functions needed by the following codes, we just
// remove them from compiling phase.
+__success(return)
BOOL
CreateUrlCacheEntryW_NoThrow(
IN LPCWSTR lpszUrlName,
diff --git a/src/utilcode/downlevel.cpp b/src/utilcode/downlevel.cpp
index 3b818e59f2..54d09553be 100644
--- a/src/utilcode/downlevel.cpp
+++ b/src/utilcode/downlevel.cpp
@@ -1810,6 +1810,7 @@ namespace DownLevel
return cchSrc;
}
+ __success(return != 0)
int LinguisticCaseString(__in LCID lcid,__in DWORD flags,
__in_ecount(cchSrc) const WCHAR * source,
__in int cchSrc,
diff --git a/src/utilcode/posterror.cpp b/src/utilcode/posterror.cpp
index 0ae48aab71..e409695a4b 100644
--- a/src/utilcode/posterror.cpp
+++ b/src/utilcode/posterror.cpp
@@ -256,7 +256,7 @@ HRESULT FillErrorInfo( // Return status.
}
CONTRACTL_END;
- ICreateErrorInfo *pICreateErr; // Error info creation Iface pointer.
+ ICreateErrorInfo *pICreateErr = NULL; // Error info creation Iface pointer.
IErrorInfo *pIErrInfo = NULL; // The IErrorInfo interface.
HRESULT hr; // Return status.
diff --git a/src/utilcode/registrywrapper.cpp b/src/utilcode/registrywrapper.cpp
index e48fb0941c..96a1d6c886 100644
--- a/src/utilcode/registrywrapper.cpp
+++ b/src/utilcode/registrywrapper.cpp
@@ -217,10 +217,12 @@ HRESULT CheckUseWow6432Node(REGSAM samDesired, bool * fResult)
// lpRedirectedKey is allocated and returned from this method. Caller owns the new string and
// should release
//
+__success(return == ERROR_SUCCESS)
HRESULT RedirectKey(REGSAM samDesired, HKEY hKey, LPCWSTR lpKey, __deref_out_z LPWSTR * lpRedirectedKey)
{
if (hKey != kRegistryRootHive || _wcsnicmp(lpKey, kRegistryRootKey, wcslen(kRegistryRootKey)) != 0)
{
+ *lpRedirectedKey = NULL;
return ERROR_SUCCESS;
}
diff --git a/src/utilcode/regutil.cpp b/src/utilcode/regutil.cpp
index c7c37aa028..9fa98b0b71 100644
--- a/src/utilcode/regutil.cpp
+++ b/src/utilcode/regutil.cpp
@@ -1130,8 +1130,8 @@ HRESULT REGUTIL::RegisterTypeLib( // Return code.
WCHAR szID[64]; // The typelib ID to register.
WCHAR szTLBID[256]; // TypeLib\\szID.
WCHAR szHelpDir[_MAX_PATH];
- WCHAR szDrive[_MAX_DRIVE];
- WCHAR szDir[_MAX_DIR];
+ WCHAR szDrive[_MAX_DRIVE] = {0};
+ WCHAR szDir[_MAX_DIR] = {0};
WCHAR szVersion[64];
LPWSTR szTmp;
diff --git a/src/utilcode/securitywrapper.cpp b/src/utilcode/securitywrapper.cpp
index 1fa8fca54a..f9d709c1e2 100644
--- a/src/utilcode/securitywrapper.cpp
+++ b/src/utilcode/securitywrapper.cpp
@@ -412,13 +412,14 @@ void SidBuffer::InitFromProcess(DWORD pid)
HRESULT SidBuffer::InitFromProcessAppContainerSidNoThrow(DWORD pid)
{
HRESULT hr = S_OK;
+ HANDLE hToken = NULL;
+
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
if (hProcess == NULL)
{
hr = HRESULT_FROM_GetLastError();
goto exit;
}
- HANDLE hToken = NULL;
if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
{
hr = HRESULT_FROM_GetLastError();
diff --git a/src/utilcode/sortversioning.cpp b/src/utilcode/sortversioning.cpp
index 6b9f56cc8c..5f0d75b58e 100644
--- a/src/utilcode/sortversioning.cpp
+++ b/src/utilcode/sortversioning.cpp
@@ -209,6 +209,7 @@ namespace SortVersioning
}
// Attempts to load a Sort DLL. If this fails, the values of the __out parameters are unchanged.
+ __success(return)
BOOL LoadSortDllAndPublish(
__in LPCWSTR sDllName,
__in DWORD dwVersion,
diff --git a/src/utilcode/util.cpp b/src/utilcode/util.cpp
index e7d6a620ff..062cf61d95 100644
--- a/src/utilcode/util.cpp
+++ b/src/utilcode/util.cpp
@@ -3783,6 +3783,7 @@ namespace Com
{
namespace __imp
{
+ __success(return == S_OK)
static
HRESULT FindSubKeyDefaultValueForCLSID(REFCLSID rclsid, LPCWSTR wszSubKeyName, SString & ssValue)
{
@@ -3803,6 +3804,7 @@ namespace Com
return Clr::Util::Reg::ReadStringValue(HKEY_CLASSES_ROOT, ssKeyName.GetUnicode(), NULL, ssValue);
}
+ __success(return == S_OK)
static
HRESULT FindSubKeyDefaultValueForCLSID(REFCLSID rclsid, LPCWSTR wszSubKeyName, __deref_out __deref_out_z LPWSTR* pwszValue)
{
diff --git a/src/utilcode/util_nodependencies.cpp b/src/utilcode/util_nodependencies.cpp
index 27720ae0f8..9f4bc9423d 100644
--- a/src/utilcode/util_nodependencies.cpp
+++ b/src/utilcode/util_nodependencies.cpp
@@ -516,7 +516,7 @@ HRESULT GetDebuggerSettingInfoWorker(__out_ecount_part_opt(*pcchDebuggerString,
}
// Look in AeDebug key for "Debugger"; get the size of any value stored there.
- DWORD valueType, valueSize;
+ DWORD valueType, valueSize = 0;
ret = WszRegQueryValueEx(hKeyHolder, kUnmanagedDebuggerValue, 0, &valueType, 0, &valueSize);
_ASSERTE(pcchDebuggerString != NULL);
diff --git a/src/utilcode/utilmessagebox.cpp b/src/utilcode/utilmessagebox.cpp
index f28d2d48f3..8b936daea8 100644
--- a/src/utilcode/utilmessagebox.cpp
+++ b/src/utilcode/utilmessagebox.cpp
@@ -190,7 +190,7 @@ int MessageBoxImpl(
mustUseMessageBox = (pfnTaskDialogIndirect == NULL);
}
- int result;
+ int result = MB_OK;
if (mustUseMessageBox) {
result = WszMessageBox(hWnd, message, title, uType);
}
@@ -247,6 +247,9 @@ int MessageBoxImpl(
if (hr == S_OK) {
result = nButtonPressed;
}
+ else {
+ result = IDOK;
+ }
_ASSERTE(result == IDOK || result == IDRETRY || result == IDIGNORE);
}
diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt
index 9282ce1d75..e1e6138644 100644
--- a/src/vm/CMakeLists.txt
+++ b/src/vm/CMakeLists.txt
@@ -207,6 +207,7 @@ set(VM_SOURCES_WKS
listlock.cpp
managedmdimport.cpp
marshalnative.cpp
+ marvin32.cpp
mdaassistants.cpp
message.cpp
methodtablebuilder.cpp
@@ -276,7 +277,6 @@ set(VM_SOURCES_DAC_AND_WKS_WIN32
list(APPEND VM_SOURCES_WKS
${VM_SOURCES_DAC_AND_WKS_WIN32}
- marvin32.cpp # move out of win32 when FEATURE_RANDOMIZED_STRING_HASHING is enabled for linux
# These should not be included for Linux
appxutil.cpp
assemblynativeresource.cpp
diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp
index 0067f6b37e..aed588c61d 100644
--- a/src/vm/appdomain.cpp
+++ b/src/vm/appdomain.cpp
@@ -8256,8 +8256,11 @@ public:
}
else
{
- IfFailRet(FString::Utf8_Unicode(szName, bIsAscii, wzBuffer, *pcchBuffer));
- *pcchBuffer = cchName;
+ IfFailRet(FString::Utf8_Unicode(szName, bIsAscii, wzBuffer, cchBuffer));
+ if (pcchBuffer != nullptr)
+ {
+ *pcchBuffer = cchName;
+ }
return S_OK;
}
}
diff --git a/src/vm/assemblynative.cpp b/src/vm/assemblynative.cpp
index 5b4e0c5347..b6b69ca900 100644
--- a/src/vm/assemblynative.cpp
+++ b/src/vm/assemblynative.cpp
@@ -25,6 +25,7 @@
#include "asm.h"
#endif
#include "assemblynative.hpp"
+#include "dllimport.h"
#include "field.h"
#include "assemblyname.hpp"
#include "eeconfig.h"
@@ -880,6 +881,22 @@ void QCALLTYPE AssemblyNative::LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext
END_QCALL;
}
+// static
+INT_PTR QCALLTYPE AssemblyNative::InternalLoadUnmanagedDllFromPath(LPCWSTR unmanagedLibraryPath)
+{
+ QCALL_CONTRACT;
+
+ HMODULE moduleHandle = nullptr;
+
+ BEGIN_QCALL;
+
+ moduleHandle = NDirect::LoadLibraryFromPath(unmanagedLibraryPath);
+
+ END_QCALL;
+
+ return reinterpret_cast<INT_PTR>(moduleHandle);
+}
+
/*static */
void QCALLTYPE AssemblyNative::LoadFromStream(INT_PTR ptrNativeAssemblyLoadContext, INT_PTR ptrAssemblyArray,
INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength,
diff --git a/src/vm/assemblynative.hpp b/src/vm/assemblynative.hpp
index f4ca12ee68..23c9914795 100644
--- a/src/vm/assemblynative.hpp
+++ b/src/vm/assemblynative.hpp
@@ -279,6 +279,7 @@ public:
static BOOL QCALLTYPE OverrideDefaultAssemblyLoadContextForCurrentDomain(INT_PTR ptrNativeAssemblyLoadContext);
static BOOL QCALLTYPE CanUseAppPathAssemblyLoadContextInCurrentDomain();
static void QCALLTYPE LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly);
+ static INT_PTR QCALLTYPE InternalLoadUnmanagedDllFromPath(LPCWSTR unmanagedLibraryPath);
static void QCALLTYPE LoadFromStream(INT_PTR ptrNativeAssemblyLoadContext, INT_PTR ptrAssemblyArray, INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength, QCall::ObjectHandleOnStack retLoadedAssembly);
static Assembly* LoadFromPEImage(CLRPrivBinderAssemblyLoadContext* pBinderContext, PEImage *pILImage, PEImage *pNIImage);
static INT_PTR QCALLTYPE GetLoadContextForAssembly(QCall::AssemblyHandle pAssembly);
diff --git a/src/vm/assemblynativeresource.cpp b/src/vm/assemblynativeresource.cpp
index 2f13e2b78d..8c18299c9d 100644
--- a/src/vm/assemblynativeresource.cpp
+++ b/src/vm/assemblynativeresource.cpp
@@ -281,8 +281,8 @@ VOID Win32Res::WriteVerResource()
WORD cbStringBlocks;
int i;
bool bUseFileVer = false;
- WCHAR rcFile[_MAX_PATH]; // Name of file without path
- WCHAR rcFileExtension[_MAX_PATH]; // file extension
+ WCHAR rcFile[_MAX_PATH] = {0}; // Name of file without path
+ WCHAR rcFileExtension[_MAX_PATH] = {0}; // file extension
WCHAR rcFileName[_MAX_PATH]; // Name of file with extension but without path
DWORD cbTmp;
diff --git a/src/vm/callingconvention.h b/src/vm/callingconvention.h
index b1ed3853c6..244a3df878 100644
--- a/src/vm/callingconvention.h
+++ b/src/vm/callingconvention.h
@@ -1282,6 +1282,7 @@ void ArgIteratorTemplate<ARGITERATOR_BASE>::ForceSigWalk()
#ifdef FEATURE_INTERPRETER
BYTE callconv = CallConv();
switch (callconv)
+ {
case IMAGE_CEE_CS_CALLCONV_C:
case IMAGE_CEE_CS_CALLCONV_STDCALL:
numRegistersUsed = NUM_ARGUMENT_REGISTERS;
diff --git a/src/vm/ceeload.cpp b/src/vm/ceeload.cpp
index b379d94365..d3d5bb8700 100644
--- a/src/vm/ceeload.cpp
+++ b/src/vm/ceeload.cpp
@@ -3068,7 +3068,7 @@ BOOL Module::IsRuntimeWrapExceptions()
if (hr == S_OK)
{
CustomAttributeParser ca(pVal, cbVal);
- CaNamedArg namedArgs[1];
+ CaNamedArg namedArgs[1] = {{0}};
// First, the void constructor:
IfFailGo(ParseKnownCaArgs(ca, NULL, 0));
diff --git a/src/vm/clrprivbinderfusion.cpp b/src/vm/clrprivbinderfusion.cpp
index aedecde9c6..8b27d7942f 100644
--- a/src/vm/clrprivbinderfusion.cpp
+++ b/src/vm/clrprivbinderfusion.cpp
@@ -232,7 +232,7 @@ public:
STDMETHOD(GetName)(
- __out LPDWORD lpcwBuffer,
+ __inout LPDWORD lpcwBuffer,
__out_ecount_opt(*lpcwBuffer) WCHAR *pwzName)
{
LIMITED_METHOD_CONTRACT;
diff --git a/src/vm/clrprivbinderwinrt.cpp b/src/vm/clrprivbinderwinrt.cpp
index dc6556a7cf..1532943f35 100644
--- a/src/vm/clrprivbinderwinrt.cpp
+++ b/src/vm/clrprivbinderwinrt.cpp
@@ -390,7 +390,7 @@ HRESULT CLRPrivBinderWinRT::BindWinRTAssemblyByName(
const WCHAR * wszFileName = pFileNameElem->GetValue();
pAssembly = FindAssemblyByFileName(wszFileName);
- WCHAR wszFileNameStripped[_MAX_PATH];
+ WCHAR wszFileNameStripped[_MAX_PATH] = {0};
SplitPath(wszFileName, NULL, NULL, NULL, NULL, wszFileNameStripped, _MAX_PATH, NULL, NULL);
if (pAssembly == nullptr)
diff --git a/src/vm/comdynamic.cpp b/src/vm/comdynamic.cpp
index 13be5f7008..28bf7ab368 100644
--- a/src/vm/comdynamic.cpp
+++ b/src/vm/comdynamic.cpp
@@ -1404,7 +1404,7 @@ HRESULT COMDynamicWrite::EmitDebugInfoBegin(Module *pModule,
// and fill out the debug directory and save off the symbols now.
if (pWriter != NULL)
{
- IMAGE_DEBUG_DIRECTORY debugDirIDD;
+ IMAGE_DEBUG_DIRECTORY debugDirIDD = {0};
DWORD debugDirDataSize;
BYTE *debugDirData;
diff --git a/src/vm/comisolatedstorage.cpp b/src/vm/comisolatedstorage.cpp
index 50eb9fe1b0..abdcb9b768 100644
--- a/src/vm/comisolatedstorage.cpp
+++ b/src/vm/comisolatedstorage.cpp
@@ -312,7 +312,7 @@ void QCALLTYPE COMIsolatedStorageFile::GetRootDir(DWORD dwF
QCALL_CONTRACT;
BEGIN_QCALL;
- WCHAR wszPath[MAX_LONGPATH + 1];
+ WCHAR wszPath[MAX_LONGPATH + 1] = {0};
GetRootDirInternal(dwFlags, wszPath, COUNTOF(wszPath));
retRootDir.Set(wszPath);
diff --git a/src/vm/compile.cpp b/src/vm/compile.cpp
index cf1d399a13..0cb474e2f8 100644
--- a/src/vm/compile.cpp
+++ b/src/vm/compile.cpp
@@ -759,9 +759,9 @@ HRESULT CEECompileInfo::LoadTypeRefWinRT(
Assembly *pAssembly;
mdToken tkResolutionScope;
- pAssemblyImport->GetResolutionScopeOfTypeRef(ref, &tkResolutionScope);
-
- if(TypeFromToken(tkResolutionScope) == mdtAssemblyRef)
+ if(FAILED(pAssemblyImport->GetResolutionScopeOfTypeRef(ref, &tkResolutionScope)))
+ hr = S_FALSE;
+ else if(TypeFromToken(tkResolutionScope) == mdtAssemblyRef)
{
DWORD dwAssemblyRefFlags;
IfFailThrow(pAssemblyImport->GetAssemblyRefProps(tkResolutionScope, NULL, NULL,
diff --git a/src/vm/comutilnative.cpp b/src/vm/comutilnative.cpp
index 55a7a1f73a..9664bf9325 100644
--- a/src/vm/comutilnative.cpp
+++ b/src/vm/comutilnative.cpp
@@ -3067,7 +3067,7 @@ void COMNlsHashProvider::InitializeDefaultSeed()
CONTRACTL_END;
PCBYTE pEntropy = GetEntropy();
- AllocMemHolder<SYMCRYPT_MARVIN32_EXPANDED_SEED> pSeed = GetAppDomain()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(SYMCRYPT_MARVIN32_EXPANDED_SEED)));
+ AllocMemHolder<SYMCRYPT_MARVIN32_EXPANDED_SEED> pSeed(GetAppDomain()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(SYMCRYPT_MARVIN32_EXPANDED_SEED))));
SymCryptMarvin32ExpandSeed(pSeed, pEntropy, SYMCRYPT_MARVIN32_SEED_SIZE);
if(InterlockedCompareExchangeT(&pDefaultSeed, (PCSYMCRYPT_MARVIN32_EXPANDED_SEED) pSeed, NULL) == NULL)
@@ -3104,12 +3104,16 @@ PCBYTE COMNlsHashProvider::GetEntropy()
if(pEntropy == NULL)
{
+ AllocMemHolder<BYTE> pNewEntropy(GetAppDomain()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(SYMCRYPT_MARVIN32_SEED_SIZE))));
+
+#ifdef FEATURE_PAL
+ PAL_Random(TRUE, pNewEntropy, SYMCRYPT_MARVIN32_SEED_SIZE);
+#else
HCRYPTPROV hCryptProv;
- AllocMemHolder<BYTE> pNewEntropy = GetAppDomain()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(SYMCRYPT_MARVIN32_SEED_SIZE)));
-
WszCryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
CryptGenRandom(hCryptProv, SYMCRYPT_MARVIN32_SEED_SIZE, pNewEntropy);
CryptReleaseContext(hCryptProv, 0);
+#endif
if(InterlockedCompareExchangeT(&pEntropy, (PBYTE) pNewEntropy, NULL) == NULL)
{
@@ -3138,3 +3142,20 @@ void COMNlsHashProvider::CreateMarvin32Seed(INT64 additionalEntropy, PSYMCRYPT_M
SymCryptMarvin32ExpandSeed(pExpandedMarvinSeed, (PCBYTE) &entropy, SYMCRYPT_MARVIN32_SEED_SIZE);
}
#endif // FEATURE_RANDOMIZED_STRING_HASHING
+
+#ifdef FEATURE_COREFX_GLOBALIZATION
+INT32 QCALLTYPE CoreFxGlobalization::HashSortKey(PCBYTE pSortKey, INT32 cbSortKey, BOOL forceRandomizedHashing, INT64 additionalEntropy)
+{
+ QCALL_CONTRACT;
+
+ INT32 retVal = 0;
+
+ BEGIN_QCALL;
+
+ retVal = COMNlsHashProvider::s_NlsHashProvider.HashSortKey(pSortKey, cbSortKey, forceRandomizedHashing, additionalEntropy);
+
+ END_QCALL;
+
+ return retVal;
+}
+#endif //FEATURE_COREFX_GLOBALIZATION
diff --git a/src/vm/comutilnative.h b/src/vm/comutilnative.h
index 0f9c7c9f38..d234d7c62d 100644
--- a/src/vm/comutilnative.h
+++ b/src/vm/comutilnative.h
@@ -309,4 +309,11 @@ private:
#endif // FEATURE_RANDOMIZED_STRING_HASHING
};
+#ifdef FEATURE_COREFX_GLOBALIZATION
+class CoreFxGlobalization {
+public:
+ static INT32 QCALLTYPE HashSortKey(PCBYTE pSortKey, INT32 cbSortKey, BOOL forceRandomizedHashing, INT64 additionalEntropy);
+};
+#endif // FEATURE_COREFX_GLOBALIZATION
+
#endif // _COMUTILNATIVE_H_
diff --git a/src/vm/dllimport.cpp b/src/vm/dllimport.cpp
index 71842eef9c..f6fabde447 100644
--- a/src/vm/dllimport.cpp
+++ b/src/vm/dllimport.cpp
@@ -4031,7 +4031,7 @@ struct HiddenParameterInfo
void CheckForHiddenParameters(DWORD cParamMarshalInfo,
__in_ecount(cParamMarshalInfo) MarshalInfo *pParamMarshalInfo,
__out DWORD *pcHiddenNativeParameters,
- __out_ecount(*pcHiddenNativeParameters) HiddenParameterInfo **ppHiddenNativeParameters)
+ __out HiddenParameterInfo **ppHiddenNativeParameters)
{
CONTRACTL
{
@@ -6578,6 +6578,25 @@ public:
return m_hr;
}
+ void DECLSPEC_NORETURN Throw(SString &libraryNameOrPath)
+ {
+ STANDARD_VM_CONTRACT;
+
+ HRESULT theHRESULT = GetHR();
+ if (theHRESULT == HRESULT_FROM_WIN32(ERROR_BAD_EXE_FORMAT))
+ {
+ COMPlusThrow(kBadImageFormatException);
+ }
+ else
+ {
+ SString hrString;
+ GetHRMsg(theHRESULT, hrString);
+ COMPlusThrow(kDllNotFoundException, IDS_EE_NDIRECT_LOADLIB, libraryNameOrPath.GetUnicode(), hrString);
+ }
+
+ __UNREACHABLE();
+ }
+
private:
void UpdateHR(DWORD priority, HRESULT hr)
{
@@ -6593,7 +6612,7 @@ private:
}; // class LoadLibErrorTracker
-// Local helper function for the LoadLibraryModule below
+// Local helper function for the LoadLibraryModule function below
static HMODULE LocalLoadLibraryHelper( LPCWSTR name, DWORD flags, LoadLibErrorTracker *pErrorTracker )
{
STANDARD_VM_CONTRACT;
@@ -6636,6 +6655,27 @@ static HMODULE LocalLoadLibraryHelper( LPCWSTR name, DWORD flags, LoadLibErrorTr
return hmod;
}
+// Local helper function for the LoadLibraryFromPath function below
+static HMODULE LocalLoadLibraryDirectHelper(LPCWSTR name, DWORD flags, LoadLibErrorTracker *pErrorTracker)
+{
+ STANDARD_VM_CONTRACT;
+
+#ifndef FEATURE_PAL
+ return LocalLoadLibraryHelper(name, flags, pErrorTracker);
+#else // !FEATURE_PAL
+ // Load the library directly, and don't register it yet with PAL. The system library handle is required here, not the PAL
+ // handle. The system library handle is registered with PAL to get a PAL handle in LoadLibraryModuleViaHost().
+ HMODULE hmod = PAL_LoadLibraryDirect(name);
+
+ if (hmod == NULL)
+ {
+ pErrorTracker->TrackErrorCode(GetLastError());
+ }
+
+ return hmod;
+#endif // !FEATURE_PAL
+}
+
#if !defined(FEATURE_CORESYSTEM)
@@ -6771,6 +6811,22 @@ VOID NDirect::CheckUnificationList(NDirectMethodDesc * pMD, DWORD * pDllImportSe
}
#endif // !FEATURE_CORECLR
+// static
+HMODULE NDirect::LoadLibraryFromPath(LPCWSTR libraryPath)
+{
+ STANDARD_VM_CONTRACT;
+
+ LoadLibErrorTracker errorTracker;
+ const HMODULE systemModuleHandle =
+ LocalLoadLibraryDirectHelper(libraryPath, GetLoadWithAlteredSearchPathFlag(), &errorTracker);
+ if (systemModuleHandle == nullptr)
+ {
+ SString libraryPathSString(libraryPath);
+ errorTracker.Throw(libraryPathSString);
+ }
+ return systemModuleHandle;
+}
+
#if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
/* static */
HMODULE NDirect::LoadLibraryModuleViaHost(NDirectMethodDesc * pMD, AppDomain* pDomain, const wchar_t* wszLibName)
@@ -6849,6 +6905,14 @@ HMODULE NDirect::LoadLibraryModuleViaHost(NDirectMethodDesc * pMD, AppDomain* pD
GCPROTECT_END();
+#ifdef FEATURE_PAL
+ if (hmod != nullptr)
+ {
+ // Register the system library handle with PAL and get a PAL library handle
+ hmod = PAL_RegisterLibraryDirect(hmod, wszLibName);
+ }
+#endif // FEATURE_PAL
+
return (HMODULE)hmod;
}
#endif //defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
@@ -7250,17 +7314,7 @@ VOID NDirect::NDirectLink(NDirectMethodDesc *pMD)
if (!hmod)
{
- HRESULT theHRESULT = errorTracker.GetHR();
- if (theHRESULT == HRESULT_FROM_WIN32(ERROR_BAD_EXE_FORMAT))
- {
- COMPlusThrow(kBadImageFormatException);
- }
- else
- {
- SString hrString;
- GetHRMsg(theHRESULT, hrString);
- COMPlusThrow(kDllNotFoundException, IDS_EE_NDIRECT_LOADLIB, ssLibName.GetUnicode(), hrString);
- }
+ errorTracker.Throw(ssLibName);
}
WCHAR wszEPName[50];
diff --git a/src/vm/dllimport.h b/src/vm/dllimport.h
index 7cf33c3e08..5b87427851 100644
--- a/src/vm/dllimport.h
+++ b/src/vm/dllimport.h
@@ -78,7 +78,8 @@ public:
static HRESULT HasNAT_LAttribute(IMDInternalImport *pInternalImport, mdToken token, DWORD dwMemberAttrs);
static LPVOID NDirectGetEntryPoint(NDirectMethodDesc *pMD, HINSTANCE hMod);
- static HINSTANCE LoadLibraryModule( NDirectMethodDesc * pMD, LoadLibErrorTracker *pErrorTracker);
+ static HMODULE LoadLibraryFromPath(LPCWSTR libraryPath);
+ static HINSTANCE LoadLibraryModule(NDirectMethodDesc * pMD, LoadLibErrorTracker *pErrorTracker);
#ifndef FEATURE_CORECLR
static VOID CheckUnificationList(NDirectMethodDesc * pMD, DWORD * pDllImportSearchPathFlag, BOOL * pSearchAssemblyDirectory);
@@ -133,7 +134,7 @@ private:
NDirect() {LIMITED_METHOD_CONTRACT;}; // prevent "new"'s on this class
#if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
- static HMODULE LoadLibraryModuleViaHost(NDirectMethodDesc * pMD, AppDomain* pDomain, const wchar_t* wszLibName);
+ static HMODULE LoadLibraryModuleViaHost(NDirectMethodDesc * pMD, AppDomain* pDomain, const wchar_t* wszLibName);
#endif //defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
#if !defined(FEATURE_CORESYSTEM)
diff --git a/src/vm/dwbucketmanager.hpp b/src/vm/dwbucketmanager.hpp
index 11d56de66b..abcc6f3ed0 100644
--- a/src/vm/dwbucketmanager.hpp
+++ b/src/vm/dwbucketmanager.hpp
@@ -513,7 +513,7 @@ void BaseBucketParamsManager::GetAppVersion(__out_ecount(maxLength) WCHAR* targe
WCHAR appPath[MAX_LONGPATH];
DWORD cchAppPath = NumItems(appPath);
- WCHAR verBuf[23];
+ WCHAR verBuf[23] = {0};
USHORT major, minor, build, revision;
if ((GetCurrentModuleFileName(appPath, &cchAppPath) == S_OK) && SUCCEEDED(DwGetFileVersionInfo(appPath, major, minor, build, revision)))
diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h
index b6bd8eeaf5..e79ab11a95 100644
--- a/src/vm/ecalllist.h
+++ b/src/vm/ecalllist.h
@@ -1166,6 +1166,7 @@ FCFuncEnd()
FCFuncStart(gAssemblyLoadContextFuncs)
QCFuncElement("InitializeAssemblyLoadContext", AssemblyNative::InitializeAssemblyLoadContext)
QCFuncElement("LoadFromPath", AssemblyNative::LoadFromPath)
+ QCFuncElement("InternalLoadUnmanagedDllFromPath", AssemblyNative::InternalLoadUnmanagedDllFromPath)
QCFuncElement("OverrideDefaultAssemblyLoadContextForCurrentDomain", AssemblyNative::OverrideDefaultAssemblyLoadContextForCurrentDomain)
QCFuncElement("CanUseAppPathAssemblyLoadContextInCurrentDomain", AssemblyNative::CanUseAppPathAssemblyLoadContextInCurrentDomain)
QCFuncElement("LoadFromStream", AssemblyNative::LoadFromStream)
@@ -1524,6 +1525,12 @@ FCFuncStart(gTextInfoFuncs)
FCFuncEnd()
#endif // defined(FEATURE_LEGACYSURFACE) && !defined(FEATURE_COREFX_GLOBALIZATION)
+#ifdef FEATURE_COREFX_GLOBALIZATION
+FCFuncStart(gCompareInfoFuncs)
+ QCFuncElement("InternalHashSortKey", CoreFxGlobalization::HashSortKey)
+FCFuncEnd()
+#endif
+
FCFuncStart(gArrayFuncs)
FCFuncElement("get_Rank", ArrayNative::GetRank)
FCFuncElement("GetLowerBound", ArrayNative::GetLowerBound)
@@ -2183,9 +2190,9 @@ FCClassElement("ChannelServices", "System.Runtime.Remoting.Channels", gChannelSe
#ifdef FEATURE_CAS_POLICY
FCClassElement("CodeAccessSecurityEngine", "System.Security", gCodeAccessSecurityEngineFuncs)
#endif
-#if defined(FEATURE_LEGACYSURFACE) && !defined(FEATURE_COREFX_GLOBALIZATION)
+#if defined(FEATURE_LEGACYSURFACE) || defined(FEATURE_COREFX_GLOBALIZATION)
FCClassElement("CompareInfo", "System.Globalization", gCompareInfoFuncs)
-#endif // defined(FEATURE_LEGACYSURFACE) && !defined(FEATURE_COREFX_GLOBALIZATION)
+#endif // defined(FEATURE_LEGACYSURFACE)
FCClassElement("CompatibilitySwitch", "System.Runtime.Versioning", gCompatibilitySwitchFuncs)
#ifdef FEATURE_COMPRESSEDSTACK
FCClassElement("CompressedStack", "System.Threading", gCompressedStackFuncs)
diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp
index 45ac184f9f..4420ea2f3a 100644
--- a/src/vm/excep.cpp
+++ b/src/vm/excep.cpp
@@ -5868,7 +5868,7 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers,
}
const int buf_size = 128;
- WCHAR buf[buf_size];
+ WCHAR buf[buf_size] = {0};
// See detailed explanation of this flag in threads.cpp. But the basic idea is that we already
// reported the exception in the AppDomain where it went unhandled, so we don't need to report
@@ -8926,6 +8926,33 @@ LONG ReflectionInvocationExceptionFilter(
}
#endif // !FEATURE_PAL
+ // If the application has opted into triggering a failfast when a CorruptedStateException enters the Reflection system,
+ // then do the needful.
+ if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_FailFastOnCorruptedStateException) == 1)
+ {
+ // Get the thread and the managed exception object - they must exist at this point
+ Thread *pCurThread = GetThread();
+ _ASSERTE(pCurThread != NULL);
+
+ // Get the thread exception state
+ ThreadExceptionState * pCurTES = pCurThread->GetExceptionState();
+ _ASSERTE(pCurTES != NULL);
+
+ // Get the exception tracker for the current exception
+#ifdef WIN64EXCEPTIONS
+ PTR_ExceptionTracker pEHTracker = pCurTES->GetCurrentExceptionTracker();
+#elif _TARGET_X86_
+ PTR_ExInfo pEHTracker = pCurTES->GetCurrentExceptionTracker();
+#else // !(_WIN64 || _TARGET_X86_)
+#error Unsupported platform
+#endif // _WIN64
+
+ if (pEHTracker->GetCorruptionSeverity() == ProcessCorrupting)
+ {
+ EEPolicy::HandleFatalError(COR_E_FAILFAST, reinterpret_cast<UINT_PTR>(pExceptionInfo->ExceptionRecord->ExceptionAddress), NULL, pExceptionInfo);
+ }
+ }
+
return ret;
} // LONG ReflectionInvocationExceptionFilter()
diff --git a/src/vm/interoputil.h b/src/vm/interoputil.h
index f2404fa17f..87a70bea5b 100644
--- a/src/vm/interoputil.h
+++ b/src/vm/interoputil.h
@@ -232,12 +232,12 @@ ULONG SafeAddRefPreemp(IUnknown* pUnk);
//--------------------------------------------------------------------------------
// Release helper, enables and disables GC during call-outs
-HRESULT SafeVariantChangeType(VARIANT* pVarRes, VARIANT* pVarSrc,
+HRESULT SafeVariantChangeType(_Inout_ VARIANT* pVarRes, _In_ VARIANT* pVarSrc,
unsigned short wFlags, VARTYPE vt);
//--------------------------------------------------------------------------------
// Release helper, enables and disables GC during call-outs
-HRESULT SafeVariantChangeTypeEx(VARIANT* pVarRes, VARIANT* pVarSrc,
+HRESULT SafeVariantChangeTypeEx(_Inout_ VARIANT* pVarRes, _In_ VARIANT* pVarSrc,
LCID lcid, unsigned short wFlags, VARTYPE vt);
//--------------------------------------------------------------------------------
diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h
index 7ee310f825..65e3f54c5e 100644
--- a/src/vm/jitinterface.h
+++ b/src/vm/jitinterface.h
@@ -1084,7 +1084,7 @@ public:
);
void freeStringConfigValue(
- wchar_t *value
+ __in_z wchar_t *value
);
CEEInfo(MethodDesc * fd = NULL, bool fVerifyOnly = false) :
diff --git a/src/vm/mdaassistants.cpp b/src/vm/mdaassistants.cpp
index 38c38d89b0..cac15fdd81 100644
--- a/src/vm/mdaassistants.cpp
+++ b/src/vm/mdaassistants.cpp
@@ -996,7 +996,11 @@ void MdaPInvokeLog::LogPInvoke(NDirectMethodDesc* pMD, HINSTANCE hMod)
StackSString sszEntryPoint;
sszEntryPoint.SetUTF8(pMD->GetEntrypointName());
- WCHAR szDllFullName[_MAX_PATH], szDrive[_MAX_PATH], szPath[_MAX_PATH], szFileName[_MAX_PATH], szExt[_MAX_PATH];
+ WCHAR szDllFullName[_MAX_PATH] = {0};
+ WCHAR szDrive[_MAX_PATH] = {0};
+ WCHAR szPath[_MAX_PATH] = {0};
+ WCHAR szFileName[_MAX_PATH] = {0};
+ WCHAR szExt[_MAX_PATH] = {0};
WszGetModuleFileName(hMod, szDllFullName, _MAX_PATH);
SplitPath(szDllFullName, szDrive, _MAX_PATH, szPath, _MAX_PATH, szFileName, _MAX_PATH, szExt, _MAX_PATH);
diff --git a/src/vm/profilermetadataemitvalidator.h b/src/vm/profilermetadataemitvalidator.h
index 3c0306c24e..469edf6e02 100644
--- a/src/vm/profilermetadataemitvalidator.h
+++ b/src/vm/profilermetadataemitvalidator.h
@@ -460,6 +460,7 @@ public:
mdTypeDef *ptd); // [OUT] Put the TypeDef token here.
virtual HRESULT STDMETHODCALLTYPE GetScopeProps( // S_OK or error.
+ __out_ecount(cchName)
LPWSTR szName, // [OUT] Put the name here.
ULONG cchName, // [IN] Size of name buffer in wide chars.
ULONG *pchName, // [OUT] Put size of name (wide chars) here.
@@ -470,6 +471,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetTypeDefProps( // S_OK or error.
mdTypeDef td, // [IN] TypeDef token for inquiry.
+ __out_ecount(cchTypeDef)
LPWSTR szTypeDef, // [OUT] Put name here.
ULONG cchTypeDef, // [IN] size of name buffer in wide chars.
ULONG *pchTypeDef, // [OUT] put size of name (wide chars) here.
@@ -484,6 +486,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetTypeRefProps( // S_OK or error.
mdTypeRef tr, // [IN] TypeRef token.
mdToken *ptkResolutionScope, // [OUT] Resolution scope, ModuleRef or AssemblyRef.
+ __out_ecount(cchName)
LPWSTR szName, // [OUT] Name of the TypeRef.
ULONG cchName, // [IN] Size of buffer.
ULONG *pchName); // [OUT] Size of Name.
@@ -597,6 +600,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetMethodProps(
mdMethodDef mb, // The method for which to get props.
mdTypeDef *pClass, // Put method's class here.
+ __out_ecount(cchMethod)
LPWSTR szMethod, // Put method's name here.
ULONG cchMethod, // Size of szMethod buffer in wide chars.
ULONG *pchMethod, // Put actual size here
@@ -609,6 +613,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetMemberRefProps( // S_OK or error.
mdMemberRef mr, // [IN] given memberref
mdToken *ptk, // [OUT] Put classref or classdef here.
+ __out_ecount(cchMember)
LPWSTR szMember, // [OUT] buffer to fill for member's name
ULONG cchMember, // [IN] the count of char of szMember
ULONG *pchMember, // [OUT] actual count of char in member name
@@ -715,6 +720,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetUserString( // S_OK or error.
mdString stk, // [IN] String token.
+ __out_ecount(cchString)
LPWSTR szString, // [OUT] Copy of string.
ULONG cchString, // [IN] Max chars of room in szString.
ULONG *pchString); // [OUT] How many chars in actual string.
@@ -722,6 +728,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetPinvokeMap( // S_OK or error.
mdToken tk, // [IN] FieldDef or MethodDef.
DWORD *pdwMappingFlags, // [OUT] Flags used for mapping.
+ __out_ecount(cchImportName)
LPWSTR szImportName, // [OUT] Import name.
ULONG cchImportName, // [IN] Size of the name buffer.
ULONG *pchImportName, // [OUT] Actual number of characters stored.
@@ -773,6 +780,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetMemberProps(
mdToken mb, // The member for which to get props.
mdTypeDef *pClass, // Put member's class here.
+ __out_ecount(cchMember)
LPWSTR szMember, // Put member's name here.
ULONG cchMember, // Size of szMember buffer in wide chars.
ULONG *pchMember, // Put actual size here
@@ -788,6 +796,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetFieldProps(
mdFieldDef mb, // The field for which to get props.
mdTypeDef *pClass, // Put field's class here.
+ __out_ecount(cchField)
LPWSTR szField, // Put field's name here.
ULONG cchField, // Size of szField buffer in wide chars.
ULONG *pchField, // Put actual size here
@@ -820,6 +829,7 @@ public:
mdParamDef tk, // [IN]The Parameter.
mdMethodDef *pmd, // [OUT] Parent Method token.
ULONG *pulSequence, // [OUT] Parameter sequence.
+ __out_ecount(cchName)
LPWSTR szName, // [OUT] Put name here.
ULONG cchName, // [OUT] Size of name buffer.
ULONG *pchName, // [OUT] Put actual size of name here.
@@ -864,6 +874,7 @@ public:
DWORD *pdwParamFlags, // [OUT] Flags, for future use (e.g. variance)
mdToken *ptOwner, // [OUT] Owner (TypeDef or MethodDef)
DWORD *reserved, // [OUT] For future use (e.g. non-type parameters)
+ __out_ecount(cchName)
LPWSTR wzname, // [OUT] Put name here
ULONG cchName, // [IN] Size of buffer
ULONG *pchName); // [OUT] Put size of name (wide chars) here.
@@ -891,6 +902,7 @@ public:
DWORD* pdwMAchine); // [OUT] Machine as defined in NT header
virtual HRESULT STDMETHODCALLTYPE GetVersionString( // S_OK or error.
+ __out_ecount(ccBufSize)
LPWSTR pwzBuf, // [OUT] Put version string here.
DWORD ccBufSize, // [IN] size of the buffer, in wide chars
DWORD *pccBufSize); // [OUT] Size of the version string, wide chars, including terminating nul.
@@ -909,7 +921,8 @@ public:
const void **ppbPublicKey, // [OUT] Pointer to the public key.
ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key.
ULONG *pulHashAlgId, // [OUT] Hash Algorithm.
- LPWSTR szName, // [OUT] Buffer to fill with assembly's simply name.
+ __out_ecount(cchName)
+ LPWSTR szName, // [OUT] Buffer to fill with assembly's simply name.
ULONG cchName, // [IN] Size of buffer in wide chars.
ULONG *pchName, // [OUT] Actual # of wide chars in name.
ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData.
@@ -919,7 +932,8 @@ public:
mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties.
const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token.
ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token.
- LPWSTR szName, // [OUT] Buffer to fill with name.
+ __out_ecount(cchName)
+ LPWSTR szName, // [OUT] Buffer to fill with name.
ULONG cchName, // [IN] Size of buffer in wide chars.
ULONG *pchName, // [OUT] Actual # of wide chars in name.
ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData.
@@ -929,7 +943,8 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetFileProps( // S_OK or error.
mdFile mdf, // [IN] The File for which to get the properties.
- LPWSTR szName, // [OUT] Buffer to fill with name.
+ __out_ecount(cchName)
+ LPWSTR szName, // [OUT] Buffer to fill with name.
ULONG cchName, // [IN] Size of buffer in wide chars.
ULONG *pchName, // [OUT] Actual # of wide chars in name.
const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob.
@@ -938,7 +953,8 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetExportedTypeProps( // S_OK or error.
mdExportedType mdct, // [IN] The ExportedType for which to get the properties.
- LPWSTR szName, // [OUT] Buffer to fill with name.
+ __out_ecount(cchName)
+ LPWSTR szName, // [OUT] Buffer to fill with name.
ULONG cchName, // [IN] Size of buffer in wide chars.
ULONG *pchName, // [OUT] Actual # of wide chars in name.
mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef or mdExportedType.
@@ -947,7 +963,8 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetManifestResourceProps( // S_OK or error.
mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties.
- LPWSTR szName, // [OUT] Buffer to fill with name.
+ __out_ecount(cchName)
+ LPWSTR szName, // [OUT] Buffer to fill with name.
ULONG cchName, // [IN] Size of buffer in wide chars.
ULONG *pchName, // [OUT] Actual # of wide chars in name.
mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ManifestResource.
diff --git a/src/vm/securitymeta.cpp b/src/vm/securitymeta.cpp
index b46ac44b73..9ab6dbe0cb 100644
--- a/src/vm/securitymeta.cpp
+++ b/src/vm/securitymeta.cpp
@@ -1834,7 +1834,7 @@ TokenSecurityDescriptorFlags ParseAptcaAttribute(const BYTE *pbAptcaBlob, DWORD
aptcaFlags |= TokenSecurityDescriptorFlags_APTCA;
// Look for the PartialTrustVisibilityLevel named argument
- CaNamedArg namedArgs[1];
+ CaNamedArg namedArgs[1] = {{0}};
namedArgs[0].InitI4FieldEnum(g_PartialTrustVisibilityLevel, g_SecurityPartialTrustVisibilityLevel);
if (SUCCEEDED(ParseKnownCaNamedArgs(cap, namedArgs, _countof(namedArgs))))
diff --git a/src/vm/stubhelpers.h b/src/vm/stubhelpers.h
index ca3f604c7c..c538bd0701 100644
--- a/src/vm/stubhelpers.h
+++ b/src/vm/stubhelpers.h
@@ -73,7 +73,7 @@ public:
static FCDECL1(Object *, InterfaceMarshaler__ConvertToManagedWithoutUnboxing, IUnknown *pNative);
static FCDECL1(StringObject*, UriMarshaler__GetRawUriFromNative, ABI::Windows::Foundation::IUriRuntimeClass* pIUriRC);
- static FCDECL2(IUnknown*, UriMarshaler__CreateNativeUriInstance, CLR_CHAR* pRawUriObj, UINT strLen);
+ static FCDECL2(IUnknown*, UriMarshaler__CreateNativeUriInstance, __in_ecount(strLen) CLR_CHAR* pRawUriObj, UINT strLen);
static ABI::Windows::UI::Xaml::Interop::INotifyCollectionChangedEventArgs* QCALLTYPE
EventArgsMarshaler__CreateNativeNCCEventArgsInstance
diff --git a/src/vm/tlbexport.cpp b/src/vm/tlbexport.cpp
index 17861387bc..744671099a 100644
--- a/src/vm/tlbexport.cpp
+++ b/src/vm/tlbexport.cpp
@@ -277,10 +277,10 @@ void ExportTypeLibFromLoadedAssembly(
TypeLibExporter exporter; // Exporter object.
LPCWSTR szModule=0; // Module filename.
- WCHAR rcDrive[_MAX_DRIVE];
- WCHAR rcDir[_MAX_DIR];
- WCHAR rcFile[_MAX_FNAME];
- WCHAR rcTlb[_MAX_PATH+5]; // Buffer for the tlb filename.
+ WCHAR rcDrive[_MAX_DRIVE] = {0};
+ WCHAR rcDir[_MAX_DIR] = {0};
+ WCHAR rcFile[_MAX_FNAME] = {0};
+ WCHAR rcTlb[_MAX_PATH+5] = {0}; // Buffer for the tlb filename.
int bDynamic=0; // If true, dynamic module.
Module *pModule; // The Assembly's SecurityModule.
diff --git a/src/vm/util.cpp b/src/vm/util.cpp
index 9c135407da..f823aa9c8d 100644
--- a/src/vm/util.cpp
+++ b/src/vm/util.cpp
@@ -31,7 +31,7 @@
// Called again with a nonnull *pdstout to fill in the actual buffer.
//
// Returns the # of arguments.
-static UINT ParseCommandLine(LPCWSTR psrc, __out LPWSTR *pdstout)
+static UINT ParseCommandLine(LPCWSTR psrc, __inout LPWSTR *pdstout)
{
CONTRACTL
{
diff --git a/src/vm/wrappers.h b/src/vm/wrappers.h
index 1a0836b707..d495a64827 100644
--- a/src/vm/wrappers.h
+++ b/src/vm/wrappers.h
@@ -59,7 +59,7 @@ private:
//--------------------------------------------------------------------------------
// safe variant helper
-void SafeVariantClear(VARIANT* pVar);
+void SafeVariantClear(_Inout_ VARIANT* pVar);
class VariantHolder
{
diff --git a/src/zap/zapinfo.h b/src/zap/zapinfo.h
index c6c8ee3b57..1d16c9b760 100644
--- a/src/zap/zapinfo.h
+++ b/src/zap/zapinfo.h
@@ -777,7 +777,7 @@ public:
wchar_t *getStringConfigValue(const wchar_t *name);
- void freeStringConfigValue(wchar_t *value);
+ void freeStringConfigValue(__in_z wchar_t *value);
};
#endif // __ZAPINFO_H__
diff --git a/tests/buildtest.cmd b/tests/buildtest.cmd
index a73a67fbff..4d97c798e3 100644
--- a/tests/buildtest.cmd
+++ b/tests/buildtest.cmd
@@ -166,6 +166,23 @@ set _buildprefix=
set _buildpostfix=
set _buildappend=
call :build %1
+
+set CORE_ROOT=%__TestBinDir%\Tests\Core_Root
+echo.
+echo Creating test overlay...
+
+:: Log build command line
+set _buildprefix=echo
+set _buildpostfix=^> "%__TestManagedBuildLog%"
+set _buildappend=^>
+call :CreateTestOverlay %1
+
+:: Build
+set _buildprefix=
+set _buildpostfix=
+set _buildappend=
+call :CreateTestOverlay %1
+
exit /b %ERRORLEVEL%
:build
@@ -174,6 +191,12 @@ exit /b %ERRORLEVEL%
IF ERRORLEVEL 1 echo Test build failed. Refer to !__TestManagedBuildLog! for details && exit /b 1
exit /b 0
+:CreateTestOverlay
+
+%_buildprefix% %_msbuildexe% "%__ProjectFilesDir%\runtest.proj" /t:CreateTestOverlay /nologo /maxcpucount /verbosity:minimal /nodeReuse:false /fileloggerparameters:Verbosity=normal;LogFile="%__TestManagedBuildLog%";Append %* %_buildpostfix%
+IF ERRORLEVEL 1 echo Failed to create the test overlay. Refer to !__TestManagedBuildLog! for details && exit /b 1
+exit /b 0
+
:Usage
echo.
echo Usage:
diff --git a/tests/runtest.cmd b/tests/runtest.cmd
index 1c324333c8..f08af94110 100644
--- a/tests/runtest.cmd
+++ b/tests/runtest.cmd
@@ -27,7 +27,7 @@ if /i "%1" == "vs2015" (set __VSVersion=%1&shift&goto Arg_Loop)
if /i "%1" == "/?" (goto Usage)
-set Core_Root=%1
+set CORE_ROOT=%1
shift
:ArgsDone
:: Check prerequisites
@@ -70,16 +70,16 @@ if not defined __LogsDir set __LogsDir=%__ProjectFilesDir%..\bin\Logs
:: Default global test environment variables
if not defined XunitTestBinBase set XunitTestBinBase=%__TestWorkingDir%\
if not defined XunitTestReportDirBase set XunitTestReportDirBase=%XunitTestBinBase%\Reports\
-if defined Core_Root goto :CheckTestEnv
+if defined CORE_ROOT goto :CheckTestEnv
set noCore_RootSet=true
-set Core_Root=%__BinDir%
+set CORE_ROOT=%__BinDir%
:CheckTestEnv
::Check if the test Binaries are built
if not exist %XunitTestBinBase% echo Error: Ensure the Test Binaries are built and are present at %XunitTestBinBase%, Run - buildtest.cmd %__BuildArch% %__BuildType% to build the tests first. && exit /b 1
-if "%Core_Root%" == "" echo Error: Ensure you have done a successful build of the Product and Run - runtest BuildArch BuildType {path to product binaries}. && exit /b 1
-if not exist %Core_Root%\coreclr.dll echo Error: Ensure you have done a successful build of the Product and %Core_Root% contains runtime binaries. && exit /b 1
+if "%CORE_ROOT%" == "" echo Error: Ensure you have done a successful build of the Product and Run - runtest BuildArch BuildType {path to product binaries}. && exit /b 1
+if not exist %CORE_ROOT%\coreclr.dll echo Error: Ensure you have done a successful build of the Product and %CORE_ROOT% contains runtime binaries. && exit /b 1
if not "%__Exclude%"=="" (if not exist %__Exclude% echo Error: Exclusion .targets file not found && exit /b 1)
if not "%__TestEnv%"=="" (if not exist %__TestEnv% echo Error: Test Environment script not found && exit /b 1)
if not exist %__LogsDir% md %__LogsDir%
@@ -90,7 +90,7 @@ set __TestRunBuildLog=%__LogsDir%\TestRunResults_%__BuildOS%__%__BuildArch%__%__
set __TestRunHtmlLog=%__LogsDir%\TestRun_%__BuildOS%__%__BuildArch%__%__BuildType%.html
set __TestRunXmlLog=%__LogsDir%\TestRun_%__BuildOS%__%__BuildArch%__%__BuildType%.xml
-echo Core_Root that will be used is: %Core_Root%
+echo CORE_ROOT that will be used is: %CORE_ROOT%
echo Starting The Test Run ...
if "%__SkipWrapperGeneration%"=="true" goto :preptests
@@ -121,12 +121,12 @@ set _buildprefix=
set _buildpostfix=
set _buildappend=
if not "%noCore_RootSet%"=="true" goto :runtests
-set Core_Root=%XunitTestBinBase%\Tests\Core_Root
-echo Using Default Core_Root as %Core_Root%
-echo Copying Built binaries from %__BinDir% to %Core_Root%
-if exist %Core_Root% rd /s /q %Core_Root%
-md %Core_Root%
-xcopy /s %__BinDir% %Core_Root%
+set CORE_ROOT=%XunitTestBinBase%\Tests\Core_Root
+echo Using Default CORE_ROOT as %CORE_ROOT%
+echo Copying Built binaries from %__BinDir% to %CORE_ROOT%
+if exist %CORE_ROOT% rd /s /q %CORE_ROOT%
+md %CORE_ROOT%
+xcopy /s %__BinDir% %CORE_ROOT%
call :runtests
if ERRORLEVEL 1 (
echo Test Run failed. Refer to the following"
diff --git a/tests/runtest.proj b/tests/runtest.proj
index 97ab648f73..96f1c05d56 100644
--- a/tests/runtest.proj
+++ b/tests/runtest.proj
@@ -306,6 +306,11 @@ public class $([System.String]::Copy('%(AllCMDs.FullPath)').Replace("$(_CMDDIR)"
<Import Project="tests.targets" />
<Import Project="publishdependency.targets" />
+ <Target Name="CreateTestOverlay">
+ <MSBuild Projects="$(MSBuildProjectFile)"
+ Targets="CopyDependecyToCoreRoot"/>
+ </Target>
+
<Target Name="Build">
<!-- Default for building -->
<MSBuild Projects="$(MSBuildProjectFile)"
@@ -315,7 +320,8 @@ public class $([System.String]::Copy('%(AllCMDs.FullPath)').Replace("$(_CMDDIR)"
<!-- Execution -->
- <MSBuild Projects="$(MSBuildProjectFile)" Targets="CopyDependecyToCoreRoot"
+ <MSBuild Projects="$(MSBuildProjectFile)"
+ Targets="CreateTestOverlay"
Condition=" '$(NoRun)'!='true' "/>
<MSBuild Projects="$(MSBuildProjectFile)" Targets="RunTests"
diff --git a/tests/runtest.sh b/tests/runtest.sh
index 00847c6466..6333873266 100644..100755
--- a/tests/runtest.sh
+++ b/tests/runtest.sh
@@ -1,13 +1,44 @@
#!/usr/bin/env bash
function print_usage {
- echo ""
- echo "CoreCLR test runner script."
- echo "Arguments:"
- echo " -v, --verbose : Show output from each test."
- echo " --testDirFile=<path> : Run tests only in the directories specified by the file at <path>."
- echo " The file should specify one directory per line."
- echo ""
+ echo ''
+ echo 'CoreCLR test runner script.'
+ echo ''
+ echo 'Typical command line:'
+ echo ''
+ echo 'coreclr/tests/runtest.sh'
+ echo ' --testRootDir="temp/Windows.x64.Debug"'
+ echo ' --testNativeBinDir="coreclr/bin/obj/Linux.x64.Debug/tests"'
+ echo ' --coreClrBinDir="coreclr/bin/Product/Linux.x64.Debug"'
+ echo ' --mscorlibDir="windows/coreclr/bin/Product/Linux.x64.Debug"'
+ echo ' --coreFxBinDir="corefx/bin/Linux.AnyCPU.Debug"'
+ echo ' --coreFxNativeBinDir="corefx/bin/Linux.x64.Debug"'
+ echo ''
+ echo 'Required arguments:'
+ echo ' --testRootDir=<path> : Root directory of the test build (e.g. coreclr/bin/tests/Windows_NT.x64.Debug).'
+ echo ' --testNativeBinDir=<path> : Directory of the native CoreCLR test build (e.g. coreclr/bin/obj/Linux.x64.Debug/tests).'
+ echo ' (Also required: Either --coreOverlayDir, or all of the switches --coreOverlayDir overrides)'
+ echo ''
+ echo 'Optional arguments:'
+ echo ' --coreOverlayDir=<path> : Directory containing core binaries and test dependencies. If not specified, the'
+ echo ' default is testRootDir/Tests/coreoverlay. This switch overrides --coreClrBinDir,'
+ echo ' --mscorlibDir, --coreFxBinDir, and --coreFxNativeBinDir.'
+ echo ' --coreClrBinDir=<path> : Directory of the CoreCLR build (e.g. coreclr/bin/Product/Linux.x64.Debug).'
+ echo ' --mscorlibDir=<path> : Directory containing the built mscorlib.dll. If not specified, it is expected to be'
+ echo ' in the directory specified by --coreClrBinDir.'
+ echo ' --coreFxBinDir=<path> : Directory of the CoreFX build (e.g. corefx/bin/Linux.AnyCPU.Debug).'
+ echo ' --coreFxNativeBinDir=<path> : Directory of the CoreFX native build (e.g. corefx/bin/Linux.x64.Debug).'
+ echo ' --testDir=<path> : Run tests only in the specified directory. The path is relative to the directory'
+ echo ' specified by --testRootDir. Multiple of this switch may be specified.'
+ echo ' --testDirFile=<path> : Run tests only in the directories specified by the file at <path>. Paths are listed'
+ echo ' one line, relative to the directory specified by --testRootDir.'
+ echo ' --runFailingTestsOnly : Run only the tests that are disabled on this platform due to unexpected failures.'
+ echo ' Failing tests are listed in coreclr/tests/failingTestsOutsideWindows.txt, one per'
+ echo ' line, as paths to .sh files relative to the directory specified by --testRootDir.'
+ echo ' --sequential : Run tests sequentially (default is to run in parallel).'
+ echo ' -v, --verbose : Show output from each test.'
+ echo ' -h|--help : Show usage information.'
+ echo ''
}
function print_results {
@@ -22,120 +53,590 @@ function print_results {
echo "======================="
}
+# Initialize counters for bookkeeping.
+countTotalTests=0
+countPassedTests=0
+countFailedTests=0
+countSkippedTests=0
+
+# Variables for xUnit-style XML output. XML format: https://xunit.github.io/docs/format-xml-v2.html
+xunitOutputPath=
+xunitTestOutputPath=
+
+function xunit_output_begin {
+ xunitOutputPath=$testRootDir/coreclrtests.xml
+ xunitTestOutputPath=${xunitOutputPath}.test
+ if [ -e "$xunitOutputPath" ]; then
+ rm -f -r "$xunitOutputPath"
+ fi
+ if [ -e "$xunitTestOutputPath" ]; then
+ rm -f -r "$xunitTestOutputPath"
+ fi
+}
+
+function xunit_output_add_test {
+ # <assemblies>
+ # <assembly>
+ # <collection>
+ # <test .../> <!-- Write this element here -->
+
+ local scriptFilePath=$1
+ local outputFilePath=$2
+ local testResult=$3 # Pass, Fail, or Skip
+ local testScriptExitCode=$4
+
+ local testPath=${scriptFilePath:0:(-3)} # Remove trailing ".sh"
+ local testDir=$(dirname "$testPath")
+ local testName=$(basename "$testPath")
+
+ # Replace '/' with '.'
+ testPath=$(echo "$testPath" | tr / .)
+ testDir=$(echo "$testDir" | tr / .)
+
+ local line
+
+ line=" "
+ line="${line}<test"
+ line="${line} name=\"${testPath}\""
+ line="${line} type=\"${testDir}\""
+ line="${line} method=\"${testName}\""
+ line="${line} result=\"${testResult}\""
+
+ if [ "$testResult" == "Pass" ]; then
+ line="${line}/>"
+ echo "$line" >>"$xunitTestOutputPath"
+ return
+ fi
+
+ line="${line}>"
+ echo "$line" >>"$xunitTestOutputPath"
+
+ line=" "
+ if [ "$testResult" == "Skip" ]; then
+ line="${line}<reason><![CDATA[$(cat "$outputFilePath")]]></reason>"
+ echo "$line" >>"$xunitTestOutputPath"
+ else
+ line="${line}<failure exception-type=\"Exit code: ${testScriptExitCode}\">"
+ echo "$line" >>"$xunitTestOutputPath"
+
+ line=" "
+ line="${line}<message>"
+ echo "$line" >>"$xunitTestOutputPath"
+ line=" "
+ line="${line}<![CDATA["
+ echo "$line" >>"$xunitTestOutputPath"
+ cat "$outputFilePath" >>"$xunitTestOutputPath"
+ line=" "
+ line="${line}]]>"
+ echo "$line" >>"$xunitTestOutputPath"
+ line=" "
+ line="${line}</message>"
+ echo "$line" >>"$xunitTestOutputPath"
+
+ line=" "
+ line="${line}</failure>"
+ echo "$line" >>"$xunitTestOutputPath"
+ fi
+
+ line=" "
+ line="${line}</test>"
+ echo "$line" >>"$xunitTestOutputPath"
+}
+
+function xunit_output_end {
+ local errorSource=$1
+ local errorMessage=$2
+
+ local errorCount
+ if [ -z "$errorSource" ]; then
+ ((errorCount = 0))
+ else
+ ((errorCount = 1))
+ fi
+
+ echo '<?xml version="1.0" encoding="utf-8"?>' >>"$xunitOutputPath"
+ echo '<assemblies>' >>"$xunitOutputPath"
+
+ local line
+
+ # <assembly ...>
+ line=" "
+ line="${line}<assembly"
+ line="${line} name=\"CoreClrTestAssembly\""
+ line="${line} total=\"${countTotalTests}\""
+ line="${line} passed=\"${countPassedTests}\""
+ line="${line} failed=\"${countFailedTests}\""
+ line="${line} skipped=\"${countSkippedTests}\""
+ line="${line} errors=\"${errorCount}\""
+ line="${line}>"
+ echo "$line" >>"$xunitOutputPath"
+
+ # <collection ...>
+ line=" "
+ line="${line}<collection"
+ line="${line} name=\"CoreClrTestCollection\""
+ line="${line} total=\"${countTotalTests}\""
+ line="${line} passed=\"${countPassedTests}\""
+ line="${line} failed=\"${countFailedTests}\""
+ line="${line} skipped=\"${countSkippedTests}\""
+ line="${line}>"
+ echo "$line" >>"$xunitOutputPath"
+
+ # <test .../> <test .../> ...
+ if [ -f "$xunitTestOutputPath" ]; then
+ cat "$xunitTestOutputPath" >>"$xunitOutputPath"
+ rm -f "$xunitTestOutputPath"
+ fi
+
+ # </collection>
+ line=" "
+ line="${line}</collection>"
+ echo "$line" >>"$xunitOutputPath"
+
+ if [ -n "$errorSource" ]; then
+ # <errors>
+ line=" "
+ line="${line}<errors>"
+ echo "$line" >>"$xunitOutputPath"
+
+ # <error ...>
+ line=" "
+ line="${line}<error"
+ line="${line} type=\"TestHarnessError\""
+ line="${line} name=\"${errorSource}\""
+ line="${line}>"
+ echo "$line" >>"$xunitOutputPath"
+
+ # <failure .../>
+ line=" "
+ line="${line}<failure>${errorMessage}</failure>"
+ echo "$line" >>"$xunitOutputPath"
+
+ # </error>
+ line=" "
+ line="${line}</error>"
+ echo "$line" >>"$xunitOutputPath"
+
+ # </errors>
+ line=" "
+ line="${line}</errors>"
+ echo "$line" >>"$xunitOutputPath"
+ fi
+
+ # </assembly>
+ line=" "
+ line="${line}</assembly>"
+ echo "$line" >>"$xunitOutputPath"
+
+ # </assemblies>
+ echo '</assemblies>' >>"$xunitOutputPath"
+}
+
+function exit_with_error {
+ local errorSource=$1
+ local errorMessage=$2
+ local printUsage=$3
+
+ if [ -z "$printUsage" ]; then
+ ((printUsage = 0))
+ fi
+
+ echo "$errorMessage"
+ xunit_output_end "$errorSource" "$errorMessage"
+ if ((printUsage != 0)); then
+ print_usage
+ fi
+ exit 1
+}
+
# Handle Ctrl-C. We will stop execution and print the results that
# we gathered so far.
function handle_ctrl_c {
+ local errorSource='handle_ctrl_c'
+
echo ""
echo "*** Stopping... ***"
print_results
- exit 0
+ exit_with_error "$errorSource" "Test run aborted by Ctrl+C."
}
# Register the Ctrl-C handler
trap handle_ctrl_c INT
+function create_core_overlay {
+ local errorSource='create_core_overlay'
+ local printUsage=1
+
+ if [ -n "$coreOverlayDir" ]; then
+ export CORE_ROOT="$coreOverlayDir"
+ return
+ fi
+
+ # Check inputs to make sure we have enough information to create the core layout. $testRootDir/Tests/Core_Root should
+ # already exist and contain test dependencies that are not built.
+ local testDependenciesDir=$testRootDir/Tests/Core_Root
+ if [ ! -d "$testDependenciesDir" ]; then
+ exit_with_error "$errorSource" "Did not find the test dependencies directory: $testDependenciesDir"
+ fi
+ if [ -z "$coreClrBinDir" ]; then
+ exit_with_error "$errorSource" "One of --coreOverlayDir or --coreClrBinDir must be specified." "$printUsage"
+ fi
+ if [ ! -d "$coreClrBinDir" ]; then
+ exit_with_error "$errorSource" "Directory specified by --coreClrBinDir does not exist: $coreClrBinDir"
+ fi
+ if [ -z "$mscorlibDir" ]; then
+ mscorlibDir=$coreClrBinDir
+ fi
+ if [ ! -f "$mscorlibDir/mscorlib.dll" ]; then
+ exit_with_error "$errorSource" "mscorlib.dll was not found in: $mscorlibDir"
+ fi
+ if [ -z "$coreFxBinDir" ]; then
+ exit_with_error "$errorSource" "One of --coreOverlayDir or --coreFxBinDir must be specified." "$printUsage"
+ fi
+ if [ ! -d "$coreFxBinDir" ]; then
+ exit_with_error "$errorSource" "Directory specified by --coreFxBinDir does not exist: $coreFxBinDir"
+ fi
+ if [ -z "$coreFxNativeBinDir" ]; then
+ exit_with_error "$errorSource" "One of --coreOverlayDir or --coreFxBinDir must be specified." "$printUsage"
+ fi
+ if [ ! -d "$coreFxNativeBinDir/Native" ]; then
+ exit_with_error "$errorSource" "Directory specified by --coreFxBinDir does not exist: $coreFxNativeBinDir/Native"
+ fi
+
+ # Create the overlay
+ coreOverlayDir=$testRootDir/Tests/coreoverlay
+ export CORE_ROOT="$coreOverlayDir"
+ if [ -e "$coreOverlayDir" ]; then
+ rm -f -r "$coreOverlayDir"
+ fi
+ mkdir "$coreOverlayDir"
+ find "$coreFxBinDir" -iname '*.dll' \! -iwholename '*test*' \! -iwholename '*/ToolRuntime/*' -exec cp -f -u '{}' "$coreOverlayDir/" \;
+ cp -f "$coreFxNativeBinDir/Native/"*.so "$coreOverlayDir/" 2>/dev/null
+ cp -f "$coreClrBinDir/"* "$coreOverlayDir/" 2>/dev/null
+ cp -f "$mscorlibDir/mscorlib.dll" "$coreOverlayDir/"
+ cp -n "$testDependenciesDir"/* "$coreOverlayDir/" 2>/dev/null
+ if [ -f "$coreOverlayDir/mscorlib.ni.dll" ]; then
+ rm -f "$coreOverlayDir/mscorlib.ni.dll"
+ fi
+}
+
+function copy_test_native_bin_to_test_root {
+ local errorSource='copy_test_native_bin_to_test_root'
+
+ if [ -z "$testNativeBinDir" ]; then
+ exit_with_error "$errorSource" "--testNativeBinDir is required."
+ fi
+ testNativeBinDir=$testNativeBinDir/src
+ if [ ! -d "$testNativeBinDir" ]; then
+ exit_with_error "$errorSource" "Directory specified by --testNativeBinDir does not exist: $testNativeBinDir"
+ fi
+
+ # Copy native test components from the native test build into the respective test directory in the test root directory
+ find "$testNativeBinDir" -type f -iname '*.so' |
+ while IFS='' read -r filePath || [ -n "$filePath" ]; do
+ local dirPath=$(dirname "$filePath")
+ local destinationDirPath=${testRootDir}${dirPath:${#testNativeBinDir}}
+ if [ ! -d "$destinationDirPath" ]; then
+ exit_with_error "$errorSource" "Cannot copy native test bin '$filePath' to '$destinationDirPath/', as the destination directory does not exist."
+ fi
+ cp -f "$filePath" "$destinationDirPath/"
+ done
+}
+
+# Variables for unsupported and failing tests
+declare -a unsupportedTests
+declare -a failingTests
+((runFailingTestsOnly = 0))
+
+function load_unsupported_tests {
+ # Load the list of tests that fail and on this platform. These tests are disabled (skipped), pending investigation.
+ # 'readarray' is not used here, as it includes the trailing linefeed in lines placed in the array.
+ while IFS='' read -r line || [ -n "$line" ]; do
+ unsupportedTests[${#unsupportedTests[@]}]=$line
+ done <"$(dirname "$0")/testsUnsupportedOutsideWindows.txt"
+}
+
+function load_failing_tests {
+ # Load the list of tests that fail and on this platform. These tests are disabled (skipped), pending investigation.
+ # 'readarray' is not used here, as it includes the trailing linefeed in lines placed in the array.
+ while IFS='' read -r line || [ -n "$line" ]; do
+ failingTests[${#failingTests[@]}]=$line
+ done <"$(dirname "$0")/testsFailingOutsideWindows.txt"
+}
+
+function is_unsupported_test {
+ for unsupportedTest in "${unsupportedTests[@]}"; do
+ if [ "$1" == "$unsupportedTest" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+function is_failing_test {
+ for failingTest in "${failingTests[@]}"; do
+ if [ "$1" == "$failingTest" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+function skip_unsupported_test {
+ # This function runs in a background process. It should not echo anything, and should not use global variables. This
+ # function is analogous to run_test, and causes the test to be skipped with the message below.
+
+ local scriptFilePath=$1
+ local outputFilePath=$2
+
+ echo "Not supported on this platform." >"$outputFilePath"
+ return 2 # skip the test
+}
+
+function skip_failing_test {
+ # This function runs in a background process. It should not echo anything, and should not use global variables. This
+ # function is analogous to run_test, and causes the test to be skipped with the message below.
+
+ local scriptFilePath=$1
+ local outputFilePath=$2
+
+ echo "Temporarily disabled on this platform due to unexpected failures." >"$outputFilePath"
+ return 2 # skip the test
+}
+
+function run_test {
+ # This function runs in a background process. It should not echo anything, and should not use global variables.
+
+ local scriptFilePath=$1
+ local outputFilePath=$2
+
+ # Switch to directory where the script is
+ cd "$(dirname "$scriptFilePath")"
+
+ local scriptFileName=$(basename "$scriptFilePath")
+ local outputFileName=$(basename "$outputFilePath")
+
+ # Convert DOS line endings to Unix if needed
+ sed -i 's/\r$//' "$scriptFileName"
+
+ "./$scriptFileName" >"$outputFileName" 2>&1
+ return $?
+}
+
+# Variables for running tests in the background
+((maxProcesses = $(getconf _NPROCESSORS_ONLN) * 3 / 2)) # long tests delay process creation, use a few more processors
+((nextProcessIndex = 0))
+((processCount = 0))
+declare -a scriptFilePaths
+declare -a outputFilePaths
+declare -a processIds
+
+function finish_test {
+ wait ${processIds[$nextProcessIndex]}
+ local testScriptExitCode=$?
+ ((--processCount))
+
+ local scriptFilePath=${scriptFilePaths[$nextProcessIndex]}
+ local outputFilePath=${outputFilePaths[$nextProcessIndex]}
+ local scriptFileName=$(basename "$scriptFilePath")
+
+ local xunitTestResult
+ case $testScriptExitCode in
+ 0)
+ let countPassedTests++
+ xunitTestResult='Pass'
+ if ((verbose == 1 || runFailingTestsOnly == 1)); then
+ echo "PASSED - $scriptFilePath"
+ else
+ echo " - $scriptFilePath"
+ fi
+ ;;
+ 2)
+ let countSkippedTests++
+ xunitTestResult='Skip'
+ echo "SKIPPED - $scriptFilePath"
+ ;;
+ *)
+ let countFailedTests++
+ xunitTestResult='Fail'
+ echo "FAILED - $scriptFilePath"
+ ;;
+ esac
+ let countTotalTests++
+
+ if ((verbose == 1 || testScriptExitCode != 0)); then
+ while IFS='' read -r line || [ -n "$line" ]; do
+ echo " $line"
+ done <"$outputFilePath"
+ fi
+
+ xunit_output_add_test "$scriptFilePath" "$outputFilePath" "$xunitTestResult" "$testScriptExitCode"
+}
+
+function finish_remaining_tests {
+ # Finish the remaining tests in the order in which they were started
+ if ((nextProcessIndex >= processCount)); then
+ ((nextProcessIndex = 0))
+ fi
+ while ((processCount > 0)); do
+ finish_test
+ ((nextProcessIndex = (nextProcessIndex + 1) % maxProcesses))
+ done
+ ((nextProcessIndex = 0))
+}
+
+function start_test {
+ local scriptFilePath=$1
+
+ if ((runFailingTestsOnly == 1)) && ! is_failing_test "$scriptFilePath"; then
+ return
+ fi
+
+ if ((nextProcessIndex < processCount)); then
+ finish_test
+ fi
+
+ scriptFilePaths[$nextProcessIndex]=$scriptFilePath
+ local scriptFileName=$(basename "$scriptFilePath")
+ local outputFilePath=$(dirname "$scriptFilePath")/${scriptFileName}.out
+ outputFilePaths[$nextProcessIndex]=$outputFilePath
+
+ test "$verbose" == 1 && echo "Starting $scriptFilePath"
+ if is_unsupported_test "$scriptFilePath"; then
+ skip_unsupported_test "$scriptFilePath" "$outputFilePath" &
+ elif ((runFailingTestsOnly == 0)) && is_failing_test "$scriptFilePath"; then
+ skip_failing_test "$scriptFilePath" "$outputFilePath" &
+ else
+ run_test "$scriptFilePath" "$outputFilePath" &
+ fi
+ processIds[$nextProcessIndex]=$!
+
+ ((nextProcessIndex = (nextProcessIndex + 1) % maxProcesses))
+ ((++processCount))
+}
+
# Get a list of directories in which to scan for tests by reading the
# specified file line by line.
function set_test_directories {
- listFileName=$1
+ local errorSource='set_test_directories'
+
+ local listFileName=$1
if [ ! -f "$listFileName" ]
then
- echo "Test directories file not found at $listFileName"
- echo "Exiting..."
- exit 1
+ exit_with_error "$errorSource" "Test directories file not found at $listFileName"
fi
readarray testDirectories < "$listFileName"
}
function run_tests_in_directory {
- rootDir=$1
+ local testDir=$1
# Recursively search through directories for .sh files to run.
- for file in $(find "$rootDir" -name '*.sh' -printf '%P\n')
+ for scriptFilePath in $(find "$testDir" -type f -iname '*.sh' | sort)
do
- scriptFullPath="$rootDir/$file"
-
- # Switch to directory where the script is
- cd "$(dirname "$scriptFullPath")"
-
- # Convert DOS line endings to Unix if needed
- sed -i 's/\r$//' "$scriptFullPath"
-
- scriptName=$(basename "$file")
- test "$verbose" == 1 && echo "Starting $scriptName"
-
- # Run the test
- ./"$scriptName" |
- while testOutput= read -r line
- do
- # Print the test output if verbose mode is on
- test "$verbose" == 1 && echo " $line"
- done;
-
- testScriptExitCode=${PIPESTATUS[0]}
- case $testScriptExitCode in
- 0)
- let countPassedTests++
- echo "PASSED - $scriptFullPath"
- ;;
- 1)
- let countFailedTests++
- echo "FAILED - $scriptFullPath"
- ;;
- 2)
- let countSkippedTests++
- echo "SKIPPED - $scriptFullPath"
- ;;
- esac
-
- let countTotalTests++
-
- # Return to root directory
- cd "$rootDir"
+ start_test "${scriptFilePath:2}"
done
}
-# Initialize counters for bookkeeping.
-countTotalTests=0
-countPassedTests=0
-countFailedTests=0
-countSkippedTests=0
-
-currDir=`pwd`
+# Argument variables
+testRootDir=
+testNativeBinDir=
+coreOverlayDir=
+coreClrBinDir=
+mscorlibDir=
+coreFxBinDir=
+coreFxNativeBinDir=
# Handle arguments
verbose=0
for i in "$@"
do
case $i in
- -h|--help)
- print_usage
- exit 0;
- ;;
- -v|--verbose)
- verbose=1
- ;;
- --testDirFile=*)
- set_test_directories "${i#*=}"
- ;;
- *);;
+ -h|--help)
+ print_usage
+ exit 0
+ ;;
+ -v|--verbose)
+ verbose=1
+ ;;
+ --testRootDir=*)
+ testRootDir=${i#*=}
+ ;;
+ --testNativeBinDir=*)
+ testNativeBinDir=${i#*=}
+ ;;
+ --coreOverlayDir=*)
+ coreOverlayDir=${i#*=}
+ ;;
+ --coreClrBinDir=*)
+ coreClrBinDir=${i#*=}
+ ;;
+ --mscorlibDir=*)
+ mscorlibDir=${i#*=}
+ ;;
+ --coreFxBinDir=*)
+ coreFxBinDir=${i#*=}
+ ;;
+ --coreFxNativeBinDir=*)
+ coreFxNativeBinDir=${i#*=}
+ ;;
+ --testDir=*)
+ testDirectories[${#testDirectories[@]}]=${i#*=}
+ ;;
+ --testDirFile=*)
+ set_test_directories "${i#*=}"
+ ;;
+ --runFailingTestsOnly)
+ ((runFailingTestsOnly = 1))
+ ;;
+ --sequential)
+ ((maxProcesses = 1))
+ ;;
+ *)
+ echo "Unknown switch: $i"
+ print_usage
+ exit 0
+ ;;
esac
done
+if [ -z "$testRootDir" ]; then
+ echo "--testRootDir is required."
+ print_usage
+ exit 1
+fi
+if [ ! -d "$testRootDir" ]; then
+ echo "Directory specified by --testRootDir does not exist: $testRootDir"
+ exit 1
+fi
+cd "$testRootDir"
+
+xunit_output_begin
+create_core_overlay
+copy_test_native_bin_to_test_root
+load_unsupported_tests
+load_failing_tests
+
if [ -z "$testDirectories" ]
then
# No test directories were specified, so run everything in the current
# directory and its subdirectories.
- run_tests_in_directory "$currDir"
+ run_tests_in_directory "."
else
# Otherwise, run all the tests in each specified test directory.
for testDir in "${testDirectories[@]}"
do
- run_tests_in_directory $currDir/$testDir
+ if [ ! -d "$testDir" ]; then
+ echo "Test directory does not exist: $testDir"
+ else
+ run_tests_in_directory "./$testDir"
+ fi
done
fi
+finish_remaining_tests
print_results
+xunit_output_end
exit 0
diff --git a/tests/src/CLRTest.Execute.Bash.targets b/tests/src/CLRTest.Execute.Bash.targets
index 72d3619e69..7e91d5618e 100644
--- a/tests/src/CLRTest.Execute.Bash.targets
+++ b/tests/src/CLRTest.Execute.Bash.targets
@@ -101,7 +101,7 @@ fi
<_CLRTestRunFile Condition="'$(_CLRTestNeedsProjectToRun)' != 'True'">"$(AssemblyName).exe"</_CLRTestRunFile>
<!-- TODO: make this better? -->
- <_CLRTestRunFile Condition=" '$(CLRTestIsHosted)'=='true' And !$(_CLRTestNeedsProjectToRun) ">"$Core_Root/corerun" $(_CLRTestRunFile)</_CLRTestRunFile>
+ <_CLRTestRunFile Condition=" '$(CLRTestIsHosted)'=='true' And !$(_CLRTestNeedsProjectToRun) ">"$CORE_ROOT/corerun" $(_CLRTestRunFile)</_CLRTestRunFile>
<BashCLRTestLaunchCmds Condition=" '$(BashCLRTestLaunchCmds)'=='' "><![CDATA[
echo $(_CLRTestRunFile) $CLRTestExecutionArguments $Host_Args
@@ -129,22 +129,6 @@ CLRTestExitCode=$?
<Output TaskParameter="ParamList" PropertyName="_CLRTestParamList"/>
</GenerateParamList>
- <!-- If a test has precommands or postcommands but no bash-specific ones,
- we will skip running that test. In order to enable the test on Unix,
- the corresponding bash versions (_BashCLRTest[Pre|Post]Commands) of
- the commands should be specified. -->
- <PropertyGroup>
- <ShouldSkipTest>false</ShouldSkipTest>
- <ShouldSkipTest Condition="('$(_CLRTestPreCommands)' != '' AND '$(_BashCLRTestPreCommands)' == '')
- OR ('$(_CLRTestPostCommands)' != '' AND '$(_BashCLRTestPostCommands)' == '')"
- >true</ShouldSkipTest>
-
- <SkipTest>
-echo "Skipping this test due to presence of pre- or post-commands that are not bash-specific."
-exit 2 # Exit code indicating skip
- </SkipTest>
- </PropertyGroup>
-
<PropertyGroup>
<!--
This generates the script portion to parse all of the command line arguments.
@@ -183,14 +167,8 @@ done
$(BashCLRTestArgPrep)
]]></BashCLRTestArgPrep>
- <_CLRTestExecutionScriptText Condition="$(ShouldSkipTest)">
- <![CDATA[
-$(SkipTest)
- ]]>
- </_CLRTestExecutionScriptText>
-
<!-- NOTE! semicolons must be escaped with %3B boooo -->
- <_CLRTestExecutionScriptText Condition="!$(ShouldSkipTest)">
+ <_CLRTestExecutionScriptText>
<![CDATA[
# The __TestEnv variable may be used to specify something to run before the test.
$__TestEnv
diff --git a/tests/src/CLRTest.Execute.Batch.targets b/tests/src/CLRTest.Execute.Batch.targets
index d32feb2f8e..06e9524b95 100644
--- a/tests/src/CLRTest.Execute.Batch.targets
+++ b/tests/src/CLRTest.Execute.Batch.targets
@@ -103,7 +103,7 @@ IF NOT "%CLRTestExitCode%"=="%CLRTestExpectedExitCode%" (
<_CLRTestRunFile Condition="'$(_CLRTestNeedsProjectToRun)' != 'True'">"$(AssemblyName).exe"</_CLRTestRunFile>
<!-- TODO: make this better? -->
- <_CLRTestRunFile Condition=" '$(CLRTestIsHosted)'=='true' And !$(_CLRTestNeedsProjectToRun) ">"%Core_Root%\corerun.exe" $(_CLRTestRunFile)</_CLRTestRunFile>
+ <_CLRTestRunFile Condition=" '$(CLRTestIsHosted)'=='true' And !$(_CLRTestNeedsProjectToRun) ">"%CORE_ROOT%\corerun.exe" $(_CLRTestRunFile)</_CLRTestRunFile>
<BatchCLRTestLaunchCmds Condition=" '$(BatchCLRTestLaunchCmds)'=='' "><![CDATA[
ECHO $(_CLRTestRunFile) %CLRTestExecutionArguments% %Host_Args%
diff --git a/tests/src/managed/Compilation/Compilation.cs b/tests/src/managed/Compilation/Compilation.cs
index 0a0037af29..9b3ebcdd90 100644
--- a/tests/src/managed/Compilation/Compilation.cs
+++ b/tests/src/managed/Compilation/Compilation.cs
@@ -14,11 +14,11 @@ class Program
static int Main(string[] args)
{
Console.WriteLine("Starting the test");
- string codeFile = @"helloWorld.cs";
+ string codeFile = @"HelloWorld.cs";
var sourceTree = new List<SyntaxTree>(){SyntaxFactory.ParseSyntaxTree(File.ReadAllText(codeFile))};
- string mscorlibFile = Path.Combine(Environment.GetEnvironmentVariable("Core_root"), "mscorlib.dll");
+ string mscorlibFile = Path.Combine(Environment.GetEnvironmentVariable("CORE_ROOT"), "mscorlib.dll");
Console.WriteLine("Using reference to: {0}", mscorlibFile);
var reference = new List<MetadataReference>(){ MetadataReference.CreateFromFile(mscorlibFile)};
diff --git a/tests/testsFailingOutsideWindows.txt b/tests/testsFailingOutsideWindows.txt
new file mode 100644
index 0000000000..ba354dc807
--- /dev/null
+++ b/tests/testsFailingOutsideWindows.txt
@@ -0,0 +1,76 @@
+Interop/ICastable/Castable.sh
+Interop/ReversePInvoke/Marshalling/MarshalBoolArray.sh
+JIT/Directed/lifetime/lifetime2.sh
+JIT/Directed/newarr/newarr.sh
+JIT/Directed/PREFIX/unaligned/1/arglist.sh
+JIT/Directed/PREFIX/unaligned/2/arglist.sh
+JIT/Directed/PREFIX/unaligned/4/arglist.sh
+JIT/Directed/PREFIX/volatile/1/arglist.sh
+JIT/Directed/TypedReference/TypedReference.sh
+JIT/Methodical/ELEMENT_TYPE_IU/_il_dbgi_ref.sh
+JIT/Methodical/ELEMENT_TYPE_IU/_il_dbgu_ref.sh
+JIT/Methodical/ELEMENT_TYPE_IU/_il_reli_ref.sh
+JIT/Methodical/ELEMENT_TYPE_IU/_il_relu_ref.sh
+JIT/Methodical/refany/array1.sh
+JIT/Methodical/refany/array2.sh
+JIT/Methodical/refany/format.sh
+JIT/Methodical/refany/gcreport.sh
+JIT/Methodical/refany/_il_dbgarray1.sh
+JIT/Methodical/refany/_il_dbgarray2.sh
+JIT/Methodical/refany/_il_dbgarray3.sh
+JIT/Methodical/refany/_il_dbgnative.sh
+JIT/Methodical/refany/_il_dbgseq.sh
+JIT/Methodical/refany/_il_dbgu_native.sh
+JIT/Methodical/refany/_il_relarray1.sh
+JIT/Methodical/refany/_il_relarray2.sh
+JIT/Methodical/refany/_il_relarray3.sh
+JIT/Methodical/refany/_il_relnative.sh
+JIT/Methodical/refany/_il_relseq.sh
+JIT/Methodical/refany/_il_relu_native.sh
+JIT/Methodical/refany/lcs.sh
+JIT/Methodical/refany/native.sh
+JIT/Methodical/refany/virtcall.sh
+JIT/Methodical/tailcall_v4/tailcall_AV.sh
+JIT/Methodical/varargs/callconv/gc_ctor_il_d.sh
+JIT/Methodical/varargs/callconv/gc_ctor_il_r.sh
+JIT/Methodical/varargs/callconv/val_ctor_il_d.sh
+JIT/Methodical/varargs/callconv/val_ctor_il_r.sh
+JIT/Methodical/varargs/misc/Dev10_615402.sh
+JIT/Methodical/VT/etc/gc_nested.sh
+JIT/Methodical/VT/etc/nested.sh
+JIT/Methodical/xxobj/ldobj/_il_dbgldobj_I8.sh
+JIT/Methodical/xxobj/ldobj/_il_dbgldobj_I.sh
+JIT/Methodical/xxobj/ldobj/_il_dbgldobj_R4.sh
+JIT/Methodical/xxobj/ldobj/_il_dbgldobj_R8.sh
+JIT/Methodical/xxobj/ldobj/_il_dbgldobj_U2.sh
+JIT/Methodical/xxobj/ldobj/_il_dbgldobj_V.sh
+JIT/Methodical/xxobj/ldobj/_il_relldobj_I8.sh
+JIT/Methodical/xxobj/ldobj/_il_relldobj_I.sh
+JIT/Methodical/xxobj/ldobj/_il_relldobj_R4.sh
+JIT/Methodical/xxobj/ldobj/_il_relldobj_R8.sh
+JIT/Methodical/xxobj/ldobj/_il_relldobj_U2.sh
+JIT/Methodical/xxobj/ldobj/_il_relldobj_V.sh
+JIT/Methodical/xxobj/operand/_il_dbgrefanyval.sh
+JIT/Methodical/xxobj/operand/_il_relrefanyval.sh
+JIT/Methodical/xxobj/operand/refanyval.sh
+JIT/Regression/CLR-x86-EJIT/V1-M12-Beta2/b26323/b26323.sh
+JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b16423/b16423.sh
+JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b28901/b28901.sh
+JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b29583/b29583.sh
+JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b30838/b30838.sh
+JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b30864/b30864.sh
+JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b35784/b35784.sh
+JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b36472/b36472.sh
+JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b37598/b37598.sh
+JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b41391/b41391.sh
+JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b41621/b41621.sh
+JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b46867/b46867.sh
+JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b31745/b31745.sh
+JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b31746/b31746.sh
+JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b37646/b37646.sh
+JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b41852/b41852.sh
+JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b51575/b51575.sh
+JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b88793/b88793.sh
+JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b91248/b91248.sh
+JIT/Regression/CLR-x86-JIT/V2.0-Beta2/b409748/b409748.sh
+Regressions/expl_double/expl_double_1.sh
diff --git a/tests/testsUnsupportedOutsideWindows.txt b/tests/testsUnsupportedOutsideWindows.txt
new file mode 100644
index 0000000000..dd0509ede1
--- /dev/null
+++ b/tests/testsUnsupportedOutsideWindows.txt
@@ -0,0 +1,11 @@
+Interop/NativeCallable/NativeCallableTest.sh
+JIT/Directed/coverage/oldtests/callipinvoke.sh
+JIT/Directed/coverage/oldtests/Desktop/callipinvoke_il_d.sh
+JIT/Directed/coverage/oldtests/Desktop/callipinvoke_il_r.sh
+JIT/Directed/IL/PInvokeTail/TailWinApi.sh
+JIT/Directed/pinvoke/jump.sh
+JIT/Directed/pinvoke/sysinfo_il.sh
+JIT/Regression/clr-x64-JIT/v2.1/b173569/b173569.sh
+managed/Compilation/Compilation.sh
+readytorun/mainv1.sh
+readytorun/mainv2.sh