commit
bb5e81c235
@ -0,0 +1 @@
|
|||||||
|
39620cc0d166a265d5d5022a38c5f1ec648563ae SOURCES/dotnet-v8.0.0-rc.2.23479.6.tar.gz
|
@ -0,0 +1 @@
|
|||||||
|
SOURCES/dotnet-v8.0.0-rc.2.23479.6.tar.gz
|
@ -0,0 +1,135 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
Check debug symbols are present in shared object and can identify
|
||||||
|
code.
|
||||||
|
|
||||||
|
It starts scanning from a directory and recursively scans all ELF
|
||||||
|
files found in it for various symbols to ensure all debuginfo is
|
||||||
|
present and nothing has been stripped.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
./check-debug-symbols /path/of/dir/to/scan/
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
./check-debug-symbols /usr/lib64
|
||||||
|
"""
|
||||||
|
|
||||||
|
# This technique was explained to me by Mark Wielaard (mjw).
|
||||||
|
|
||||||
|
import collections
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
ScanResult = collections.namedtuple('ScanResult',
|
||||||
|
'file_name debug_info debug_abbrev file_symbols gnu_debuglink')
|
||||||
|
|
||||||
|
|
||||||
|
def scan_file(file):
|
||||||
|
"Scan the provided file and return a ScanResult containing results of the scan."
|
||||||
|
|
||||||
|
# Test for .debug_* sections in the shared object. This is the main test.
|
||||||
|
# Stripped objects will not contain these.
|
||||||
|
readelf_S_result = subprocess.run(['eu-readelf', '-S', file],
|
||||||
|
stdout=subprocess.PIPE, encoding='utf-8', check=True)
|
||||||
|
has_debug_info = any(line for line in readelf_S_result.stdout.split('\n') if '] .debug_info' in line)
|
||||||
|
|
||||||
|
has_debug_abbrev = any(line for line in readelf_S_result.stdout.split('\n') if '] .debug_abbrev' in line)
|
||||||
|
|
||||||
|
# Test FILE symbols. These will most likely be removed by anyting that
|
||||||
|
# manipulates symbol tables because it's generally useless. So a nice test
|
||||||
|
# that nothing has messed with symbols.
|
||||||
|
def contains_file_symbols(line):
|
||||||
|
parts = line.split()
|
||||||
|
if len(parts) < 8:
|
||||||
|
return False
|
||||||
|
return \
|
||||||
|
parts[2] == '0' and parts[3] == 'FILE' and parts[4] == 'LOCAL' and parts[5] == 'DEFAULT' and \
|
||||||
|
parts[6] == 'ABS' and re.match(r'((.*/)?[-_a-zA-Z0-9]+\.(c|cc|cpp|cxx))?', parts[7])
|
||||||
|
|
||||||
|
readelf_s_result = subprocess.run(["eu-readelf", '-s', file],
|
||||||
|
stdout=subprocess.PIPE, encoding='utf-8', check=True)
|
||||||
|
has_file_symbols = any(line for line in readelf_s_result.stdout.split('\n') if contains_file_symbols(line))
|
||||||
|
|
||||||
|
# Test that there are no .gnu_debuglink sections pointing to another
|
||||||
|
# debuginfo file. There shouldn't be any debuginfo files, so the link makes
|
||||||
|
# no sense either.
|
||||||
|
has_gnu_debuglink = any(line for line in readelf_s_result.stdout.split('\n') if '] .gnu_debuglink' in line)
|
||||||
|
|
||||||
|
return ScanResult(file, has_debug_info, has_debug_abbrev, has_file_symbols, has_gnu_debuglink)
|
||||||
|
|
||||||
|
def is_elf(file):
|
||||||
|
result = subprocess.run(['file', file], stdout=subprocess.PIPE, encoding='utf-8', check=True)
|
||||||
|
return re.search(r'ELF 64-bit [LM]SB (?:pie )?(?:executable|shared object)', result.stdout)
|
||||||
|
|
||||||
|
def scan_file_if_sensible(file):
|
||||||
|
if is_elf(file):
|
||||||
|
return scan_file(file)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def scan_dir(dir):
|
||||||
|
results = []
|
||||||
|
for root, _, files in os.walk(dir):
|
||||||
|
for name in files:
|
||||||
|
result = scan_file_if_sensible(os.path.join(root, name))
|
||||||
|
if result:
|
||||||
|
results.append(result)
|
||||||
|
return results
|
||||||
|
|
||||||
|
def scan(file):
|
||||||
|
file = os.path.abspath(file)
|
||||||
|
if os.path.isdir(file):
|
||||||
|
return scan_dir(file)
|
||||||
|
elif os.path.isfile(file):
|
||||||
|
return [scan_file_if_sensible(file)]
|
||||||
|
|
||||||
|
def is_bad_result(result):
|
||||||
|
return not result.debug_info or not result.debug_abbrev or not result.file_symbols or result.gnu_debuglink
|
||||||
|
|
||||||
|
def print_scan_results(results, verbose):
|
||||||
|
# print(results)
|
||||||
|
for result in results:
|
||||||
|
file_name = result.file_name
|
||||||
|
found_issue = False
|
||||||
|
if not result.debug_info:
|
||||||
|
found_issue = True
|
||||||
|
print('error: missing .debug_info section in', file_name)
|
||||||
|
if not result.debug_abbrev:
|
||||||
|
found_issue = True
|
||||||
|
print('error: missing .debug_abbrev section in', file_name)
|
||||||
|
if not result.file_symbols:
|
||||||
|
found_issue = True
|
||||||
|
print('error: missing FILE symbols in', file_name)
|
||||||
|
if result.gnu_debuglink:
|
||||||
|
found_issue = True
|
||||||
|
print('error: unexpected .gnu_debuglink section in', file_name)
|
||||||
|
if verbose and not found_issue:
|
||||||
|
print('OK: ', file_name)
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
verbose = False
|
||||||
|
files = []
|
||||||
|
for arg in args:
|
||||||
|
if arg == '--verbose' or arg == '-v':
|
||||||
|
verbose = True
|
||||||
|
else:
|
||||||
|
files.append(arg)
|
||||||
|
|
||||||
|
results = []
|
||||||
|
for file in files:
|
||||||
|
results.extend(scan(file))
|
||||||
|
|
||||||
|
print_scan_results(results, verbose)
|
||||||
|
|
||||||
|
if any(is_bad_result(result) for result in results):
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main(sys.argv[1:]))
|
@ -0,0 +1,38 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Thalman <mthalman@microsoft.com>
|
||||||
|
Date: Tue, 24 Oct 2023 16:20:26 -0500
|
||||||
|
Subject: [PATCH] Use correct runtime package version
|
||||||
|
|
||||||
|
---
|
||||||
|
prereqs/git-info/AllRepoVersions.props | 2 +-
|
||||||
|
prereqs/git-info/runtime.props | 4 ++--
|
||||||
|
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/prereqs/git-info/AllRepoVersions.props b/prereqs/git-info/AllRepoVersions.props
|
||||||
|
index 79a789e1cd..a3f3ccf094 100644
|
||||||
|
--- a/prereqs/git-info/AllRepoVersions.props
|
||||||
|
+++ b/prereqs/git-info/AllRepoVersions.props
|
||||||
|
@@ -32,7 +32,7 @@
|
||||||
|
<roslynGitCommitHash>bdd9c5ba66b00beebdc3516acc5e29b83efd89af</roslynGitCommitHash>
|
||||||
|
<roslynOutputPackageVersion>4.8.0-3.23471.11</roslynOutputPackageVersion>
|
||||||
|
<runtimeGitCommitHash>0b25e38ad32a69cd83ae246104b32449203cc71c</runtimeGitCommitHash>
|
||||||
|
- <runtimeOutputPackageVersion>8.0.0-rc.2.23475.17</runtimeOutputPackageVersion>
|
||||||
|
+ <runtimeOutputPackageVersion>8.0.0-rc.2.23479.6</runtimeOutputPackageVersion>
|
||||||
|
<sdkGitCommitHash>67e671f384bee6937630b52b02cc78e69b27e280</sdkGitCommitHash>
|
||||||
|
<sdkOutputPackageVersion>8.0.100-rc.2.23480.5</sdkOutputPackageVersion>
|
||||||
|
<sourcebuildexternalsGitCommitHash>6dbf3aaa0fc9664df86462f5c70b99800934fccd</sourcebuildexternalsGitCommitHash>
|
||||||
|
diff --git a/prereqs/git-info/runtime.props b/prereqs/git-info/runtime.props
|
||||||
|
index 546469c3a0..20c2bf8840 100644
|
||||||
|
--- a/prereqs/git-info/runtime.props
|
||||||
|
+++ b/prereqs/git-info/runtime.props
|
||||||
|
@@ -2,8 +2,8 @@
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<GitCommitHash>0b25e38ad32a69cd83ae246104b32449203cc71c</GitCommitHash>
|
||||||
|
- <OfficialBuildId>20230925.17</OfficialBuildId>
|
||||||
|
- <OutputPackageVersion>8.0.0-rc.2.23475.17</OutputPackageVersion>
|
||||||
|
+ <OfficialBuildId>20230929.6</OfficialBuildId>
|
||||||
|
+ <OutputPackageVersion>8.0.0-rc.2.23479.6</OutputPackageVersion>
|
||||||
|
<PreReleaseVersionLabel>rc.2</PreReleaseVersionLabel>
|
||||||
|
<IsStable>false</IsStable>
|
||||||
|
</PropertyGroup>
|
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
# Set location for AppHost lookup
|
||||||
|
[ -z "$DOTNET_ROOT" ] && export DOTNET_ROOT=@LIBDIR@/dotnet
|
||||||
|
|
||||||
|
# Add dotnet tools directory to PATH
|
||||||
|
DOTNET_TOOLS_PATH="$HOME/.dotnet/tools"
|
||||||
|
case "$PATH" in
|
||||||
|
*"$DOTNET_TOOLS_PATH"* ) true ;;
|
||||||
|
* ) PATH="$PATH:$DOTNET_TOOLS_PATH" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Extract self-contained executables under HOME
|
||||||
|
# to avoid multi-user issues from using the default '/var/tmp'.
|
||||||
|
[ -z "$DOTNET_BUNDLE_EXTRACT_BASE_DIR" ] && export DOTNET_BUNDLE_EXTRACT_BASE_DIR="${XDG_CACHE_HOME:-"$HOME"/.cache}/dotnet_bundle_extract"
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"release": "8.0.0-rc.2",
|
||||||
|
"channel": "8.0",
|
||||||
|
"tag": "v8.0.0-rc.2.23479.6",
|
||||||
|
"sdkVersion": "8.0.100-rc.2.23502.2",
|
||||||
|
"runtimeVersion": "8.0.0-rc.2.23479.6",
|
||||||
|
"sourceRepository": "https://github.com/dotnet/dotnet",
|
||||||
|
"sourceVersion": "1e872358329855089d8d14cec1f06d5b075824b5"
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
diff --git a/src/roslyn-analyzers/src/PerformanceTests/Tests/PerformanceTests.csproj b/src/roslyn-analyzers/src/PerformanceTests/Tests/PerformanceTests.csproj
|
||||||
|
index 044a2aba4..b3f8f2611 100644
|
||||||
|
--- a/src/roslyn-analyzers/src/PerformanceTests/Tests/PerformanceTests.csproj
|
||||||
|
+++ b/src/roslyn-analyzers/src/PerformanceTests/Tests/PerformanceTests.csproj
|
||||||
|
@@ -4,6 +4,7 @@
|
||||||
|
<LangVersion>preview</LangVersion>
|
||||||
|
<Nullable>disable</Nullable>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
+ <UseAppHost>false</UseAppHost>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<NonShipping>true</NonShipping>
|
@ -0,0 +1,260 @@
|
|||||||
|
From 72f310a6c3dccbabf9edc29677b51ed78c87cc67 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sanjam Panda <sanjam.panda@ibm.com>
|
||||||
|
Date: Tue, 19 Sep 2023 15:16:02 +0200
|
||||||
|
Subject: [PATCH 1/3] [wasm] Endian fix for Webcil
|
||||||
|
|
||||||
|
'dotnet new blazorwasm' command failed on s390x and was throwing a not implemented exception
|
||||||
|
|
||||||
|
The issue was with with the WebCil writer and reader, specific endianness conversions relating to the webcil payload were not implemented for big endian machines.
|
||||||
|
|
||||||
|
We considered fixing the generic implementation, but there were only two structures in use: WebcilHeader and WebcilSectionHeader, so it was easier to handle them explicitly.
|
||||||
|
---
|
||||||
|
.../Microsoft.NET.WebAssembly.Webcil.csproj | 1 +
|
||||||
|
.../WebcilConverter.cs | 35 +++++++++++++-----
|
||||||
|
.../WebcilReader.cs | 37 +++++++++++++++----
|
||||||
|
3 files changed, 57 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj
|
||||||
|
index c35eb57e80686..d09ae4a569a59 100644
|
||||||
|
--- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj
|
||||||
|
+++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj
|
||||||
|
@@ -16,6 +16,7 @@
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- we need to keep the version of System.Reflection.Metadata in sync with dotnet/msbuild and dotnet/sdk -->
|
||||||
|
+ <PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
|
||||||
|
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" />
|
||||||
|
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
||||||
|
index a38af7270a2da..7b882c42d579e 100644
|
||||||
|
--- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
||||||
|
+++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
||||||
|
@@ -2,6 +2,7 @@
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
+using System.Buffers.Binary;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Reflection.PortableExecutable;
|
||||||
|
@@ -181,9 +182,6 @@ private static void WriteHeader(Stream s, WebcilHeader header)
|
||||||
|
|
||||||
|
private static void WriteSectionHeaders(Stream s, ImmutableArray<WebcilSectionHeader> sectionsHeaders)
|
||||||
|
{
|
||||||
|
- // FIXME: fixup endianness
|
||||||
|
- if (!BitConverter.IsLittleEndian)
|
||||||
|
- throw new NotImplementedException();
|
||||||
|
foreach (var sectionHeader in sectionsHeaders)
|
||||||
|
{
|
||||||
|
WriteSectionHeader(s, sectionHeader);
|
||||||
|
@@ -192,16 +190,38 @@ private static void WriteSectionHeaders(Stream s, ImmutableArray<WebcilSectionHe
|
||||||
|
|
||||||
|
private static void WriteSectionHeader(Stream s, WebcilSectionHeader sectionHeader)
|
||||||
|
{
|
||||||
|
+ if (!BitConverter.IsLittleEndian)
|
||||||
|
+ {
|
||||||
|
+ sectionHeader = new WebcilSectionHeader
|
||||||
|
+ (
|
||||||
|
+ virtualSize: BinaryPrimitives.ReverseEndianness(sectionHeader.VirtualSize),
|
||||||
|
+ virtualAddress: BinaryPrimitives.ReverseEndianness(sectionHeader.VirtualAddress),
|
||||||
|
+ sizeOfRawData: BinaryPrimitives.ReverseEndianness(sectionHeader.SizeOfRawData),
|
||||||
|
+ pointerToRawData: BinaryPrimitives.ReverseEndianness(sectionHeader.PointerToRawData)
|
||||||
|
+ );
|
||||||
|
+ }
|
||||||
|
WriteStructure(s, sectionHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ private static void WriteStructure(Stream s, WebcilHeader webcilHeader)
|
||||||
|
+ {
|
||||||
|
+ if (!BitConverter.IsLittleEndian)
|
||||||
|
+ {
|
||||||
|
+ webcilHeader.version_major = BinaryPrimitives.ReverseEndianness(webcilHeader.version_major);
|
||||||
|
+ webcilHeader.version_minor = BinaryPrimitives.ReverseEndianness(webcilHeader.version_minor);
|
||||||
|
+ webcilHeader.coff_sections = BinaryPrimitives.ReverseEndianness(webcilHeader.coff_sections);
|
||||||
|
+ webcilHeader.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_rva);
|
||||||
|
+ webcilHeader.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_size);
|
||||||
|
+ webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva);
|
||||||
|
+ webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size);
|
||||||
|
+ }
|
||||||
|
+ WriteStructure(s, webcilHeader);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
#if NETCOREAPP2_1_OR_GREATER
|
||||||
|
private static void WriteStructure<T>(Stream s, T structure)
|
||||||
|
where T : unmanaged
|
||||||
|
{
|
||||||
|
- // FIXME: fixup endianness
|
||||||
|
- if (!BitConverter.IsLittleEndian)
|
||||||
|
- throw new NotImplementedException();
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
byte* p = (byte*)&structure;
|
||||||
|
@@ -212,9 +232,6 @@ private static void WriteStructure<T>(Stream s, T structure)
|
||||||
|
private static void WriteStructure<T>(Stream s, T structure)
|
||||||
|
where T : unmanaged
|
||||||
|
{
|
||||||
|
- // FIXME: fixup endianness
|
||||||
|
- if (!BitConverter.IsLittleEndian)
|
||||||
|
- throw new NotImplementedException();
|
||||||
|
int size = Marshal.SizeOf<T>();
|
||||||
|
byte[] buffer = new byte[size];
|
||||||
|
IntPtr ptr = IntPtr.Zero;
|
||||||
|
diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
|
||||||
|
index 4f42f82798664..ac4f9d86095a9 100644
|
||||||
|
--- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
|
||||||
|
+++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
|
||||||
|
@@ -6,7 +6,7 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
-
|
||||||
|
+using System.Buffers.Binary;
|
||||||
|
using System.Reflection.Metadata;
|
||||||
|
using System.Reflection.PortableExecutable;
|
||||||
|
|
||||||
|
@@ -63,14 +63,20 @@ private unsafe bool ReadHeader()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
- if (!BitConverter.IsLittleEndian)
|
||||||
|
- {
|
||||||
|
- throw new NotImplementedException("TODO: implement big endian support");
|
||||||
|
- }
|
||||||
|
fixed (byte* p = buffer)
|
||||||
|
{
|
||||||
|
header = *(WebcilHeader*)p;
|
||||||
|
}
|
||||||
|
+ if (!BitConverter.IsLittleEndian)
|
||||||
|
+ {
|
||||||
|
+ header.version_major = BinaryPrimitives.ReverseEndianness(header.version_major);
|
||||||
|
+ header.version_minor = BinaryPrimitives.ReverseEndianness(header.version_minor);
|
||||||
|
+ header.coff_sections = BinaryPrimitives.ReverseEndianness(header.coff_sections);
|
||||||
|
+ header.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(header.pe_cli_header_rva);
|
||||||
|
+ header.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(header.pe_cli_header_size);
|
||||||
|
+ header.pe_debug_rva = BinaryPrimitives.ReverseEndianness(header.pe_debug_rva);
|
||||||
|
+ header.pe_debug_rva = BinaryPrimitives.ReverseEndianness(header.pe_debug_size);
|
||||||
|
+ }
|
||||||
|
if (header.id[0] != 'W' || header.id[1] != 'b'
|
||||||
|
|| header.id[2] != 'I' || header.id[3] != 'L'
|
||||||
|
|| header.version_major != Internal.Constants.WC_VERSION_MAJOR
|
||||||
|
@@ -346,6 +352,7 @@ private long TranslateRVA(uint rva)
|
||||||
|
|
||||||
|
private unsafe ImmutableArray<WebcilSectionHeader> ReadSections()
|
||||||
|
{
|
||||||
|
+ WebcilSectionHeader secheader;
|
||||||
|
var sections = ImmutableArray.CreateBuilder<WebcilSectionHeader>(_header.coff_sections);
|
||||||
|
var buffer = new byte[Marshal.SizeOf<WebcilSectionHeader>()];
|
||||||
|
_stream.Seek(SectionDirectoryOffset + _webcilInWasmOffset, SeekOrigin.Begin);
|
||||||
|
@@ -357,8 +364,24 @@ private unsafe ImmutableArray<WebcilSectionHeader> ReadSections()
|
||||||
|
}
|
||||||
|
fixed (byte* p = buffer)
|
||||||
|
{
|
||||||
|
- // FIXME endianness
|
||||||
|
- sections.Add(*(WebcilSectionHeader*)p);
|
||||||
|
+ secheader = (*(WebcilSectionHeader*)p);
|
||||||
|
+ }
|
||||||
|
+ if (!BitConverter.IsLittleEndian)
|
||||||
|
+ {
|
||||||
|
+ sections.Add
|
||||||
|
+ (
|
||||||
|
+ new WebcilSectionHeader
|
||||||
|
+ (
|
||||||
|
+ virtualSize: BinaryPrimitives.ReverseEndianness(secheader.VirtualSize),
|
||||||
|
+ virtualAddress: BinaryPrimitives.ReverseEndianness(secheader.VirtualAddress),
|
||||||
|
+ sizeOfRawData: BinaryPrimitives.ReverseEndianness(secheader.SizeOfRawData),
|
||||||
|
+ pointerToRawData: BinaryPrimitives.ReverseEndianness(secheader.PointerToRawData)
|
||||||
|
+ )
|
||||||
|
+ );
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ sections.Add(secheader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sections.MoveToImmutable();
|
||||||
|
|
||||||
|
From 0c78184347335db183a38cf6bd26e2fe69160931 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= <alklig@microsoft.com>
|
||||||
|
Date: Thu, 21 Sep 2023 14:31:12 -0400
|
||||||
|
Subject: [PATCH 2/3] Fix infinite recursion
|
||||||
|
|
||||||
|
---
|
||||||
|
.../WebcilConverter.cs | 25 ++++++++-----------
|
||||||
|
1 file changed, 10 insertions(+), 15 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
||||||
|
index 7b882c42d579e..fc95eded5bc33 100644
|
||||||
|
--- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
||||||
|
+++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
||||||
|
@@ -177,6 +177,16 @@ public unsafe void GatherInfo(PEReader peReader, out WCFileInfo wcInfo, out PEFi
|
||||||
|
|
||||||
|
private static void WriteHeader(Stream s, WebcilHeader header)
|
||||||
|
{
|
||||||
|
+ if (!BitConverter.IsLittleEndian)
|
||||||
|
+ {
|
||||||
|
+ webcilHeader.version_major = BinaryPrimitives.ReverseEndianness(webcilHeader.version_major);
|
||||||
|
+ webcilHeader.version_minor = BinaryPrimitives.ReverseEndianness(webcilHeader.version_minor);
|
||||||
|
+ webcilHeader.coff_sections = BinaryPrimitives.ReverseEndianness(webcilHeader.coff_sections);
|
||||||
|
+ webcilHeader.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_rva);
|
||||||
|
+ webcilHeader.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_size);
|
||||||
|
+ webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva);
|
||||||
|
+ webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size);
|
||||||
|
+ }
|
||||||
|
WriteStructure(s, header);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -203,21 +213,6 @@ private static void WriteSectionHeader(Stream s, WebcilSectionHeader sectionHead
|
||||||
|
WriteStructure(s, sectionHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
- private static void WriteStructure(Stream s, WebcilHeader webcilHeader)
|
||||||
|
- {
|
||||||
|
- if (!BitConverter.IsLittleEndian)
|
||||||
|
- {
|
||||||
|
- webcilHeader.version_major = BinaryPrimitives.ReverseEndianness(webcilHeader.version_major);
|
||||||
|
- webcilHeader.version_minor = BinaryPrimitives.ReverseEndianness(webcilHeader.version_minor);
|
||||||
|
- webcilHeader.coff_sections = BinaryPrimitives.ReverseEndianness(webcilHeader.coff_sections);
|
||||||
|
- webcilHeader.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_rva);
|
||||||
|
- webcilHeader.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_size);
|
||||||
|
- webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva);
|
||||||
|
- webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size);
|
||||||
|
- }
|
||||||
|
- WriteStructure(s, webcilHeader);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
#if NETCOREAPP2_1_OR_GREATER
|
||||||
|
private static void WriteStructure<T>(Stream s, T structure)
|
||||||
|
where T : unmanaged
|
||||||
|
|
||||||
|
From cecf4f09f0c52340c753811098f0f2d9593049aa Mon Sep 17 00:00:00 2001
|
||||||
|
From: Aleksey Kliger <alklig@microsoft.com>
|
||||||
|
Date: Thu, 21 Sep 2023 14:36:20 -0400
|
||||||
|
Subject: [PATCH 3/3] rename var
|
||||||
|
|
||||||
|
---
|
||||||
|
src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
||||||
|
index fc95eded5bc33..13c34bde4b8ea 100644
|
||||||
|
--- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
||||||
|
+++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
||||||
|
@@ -175,7 +175,7 @@ public unsafe void GatherInfo(PEReader peReader, out WCFileInfo wcInfo, out PEFi
|
||||||
|
SectionStart: firstWCSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
- private static void WriteHeader(Stream s, WebcilHeader header)
|
||||||
|
+ private static void WriteHeader(Stream s, WebcilHeader webcilHeader)
|
||||||
|
{
|
||||||
|
if (!BitConverter.IsLittleEndian)
|
||||||
|
{
|
||||||
|
@@ -187,7 +187,7 @@ private static void WriteHeader(Stream s, WebcilHeader header)
|
||||||
|
webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva);
|
||||||
|
webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size);
|
||||||
|
}
|
||||||
|
- WriteStructure(s, header);
|
||||||
|
+ WriteStructure(s, webcilHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteSectionHeaders(Stream s, ImmutableArray<WebcilSectionHeader> sectionsHeaders)
|
@ -0,0 +1,416 @@
|
|||||||
|
From 9aec1e3b0b9ddc02b81bd115399f8951288b261b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tom Deseyn <tom.deseyn@gmail.com>
|
||||||
|
Date: Wed, 11 Oct 2023 18:32:20 +0200
|
||||||
|
Subject: [PATCH] Support specifying multiple directories through SSL_CERT_DIR
|
||||||
|
|
||||||
|
Co-authored-by: Jeremy Barton <jbarton@microsoft.com>
|
||||||
|
Co-authored-by: Kevin Jones <vcsjones@github.com>
|
||||||
|
---
|
||||||
|
.../OpenSslCachedSystemStoreProvider.cs | 232 +++++++++---------
|
||||||
|
.../X509Certificates/X509StoreTests.Unix.cs | 42 +++-
|
||||||
|
2 files changed, 157 insertions(+), 117 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/runtime/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs b/src/runtime/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs
|
||||||
|
index 4c9643c01e2..e66b3d1ad11 100644
|
||||||
|
--- a/src/runtime/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs
|
||||||
|
+++ b/src/runtime/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs
|
||||||
|
@@ -21,14 +21,14 @@ internal sealed class OpenSslCachedSystemStoreProvider : IStorePal
|
||||||
|
private static readonly TimeSpan s_lastWriteRecheckInterval = TimeSpan.FromSeconds(5);
|
||||||
|
private static readonly TimeSpan s_assumeInvalidInterval = TimeSpan.FromMinutes(5);
|
||||||
|
private static readonly Stopwatch s_recheckStopwatch = new Stopwatch();
|
||||||
|
- private static DirectoryInfo? s_rootStoreDirectoryInfo = SafeOpenRootDirectoryInfo();
|
||||||
|
+ private static string[]? s_rootStoreDirectories;
|
||||||
|
private static bool s_defaultRootDir;
|
||||||
|
- private static readonly FileInfo? s_rootStoreFileInfo = SafeOpenRootFileInfo();
|
||||||
|
+ private static string? s_rootStoreFile;
|
||||||
|
+ private static DateTime[]? s_directoryLastWrite;
|
||||||
|
+ private static DateTime s_fileLastWrite;
|
||||||
|
|
||||||
|
// Use non-Value-Tuple so that it's an atomic update.
|
||||||
|
private static Tuple<SafeX509StackHandle, SafeX509StackHandle>? s_nativeCollections;
|
||||||
|
- private static DateTime s_directoryCertsLastWrite;
|
||||||
|
- private static DateTime s_fileCertsLastWrite;
|
||||||
|
|
||||||
|
private readonly bool _isRoot;
|
||||||
|
|
||||||
|
@@ -93,18 +93,11 @@ public void Remove(ICertificatePal cert)
|
||||||
|
{
|
||||||
|
lock (s_recheckStopwatch)
|
||||||
|
{
|
||||||
|
- FileInfo? fileInfo = s_rootStoreFileInfo;
|
||||||
|
- DirectoryInfo? dirInfo = s_rootStoreDirectoryInfo;
|
||||||
|
-
|
||||||
|
- fileInfo?.Refresh();
|
||||||
|
- dirInfo?.Refresh();
|
||||||
|
-
|
||||||
|
if (ret == null ||
|
||||||
|
elapsed > s_assumeInvalidInterval ||
|
||||||
|
- (fileInfo != null && fileInfo.Exists && ContentWriteTime(fileInfo) != s_fileCertsLastWrite) ||
|
||||||
|
- (dirInfo != null && dirInfo.Exists && ContentWriteTime(dirInfo) != s_directoryCertsLastWrite))
|
||||||
|
+ LastWriteTimesHaveChanged())
|
||||||
|
{
|
||||||
|
- ret = LoadMachineStores(dirInfo, fileInfo);
|
||||||
|
+ ret = LoadMachineStores();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -113,9 +106,37 @@ public void Remove(ICertificatePal cert)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
- private static Tuple<SafeX509StackHandle, SafeX509StackHandle> LoadMachineStores(
|
||||||
|
- DirectoryInfo? rootStorePath,
|
||||||
|
- FileInfo? rootStoreFile)
|
||||||
|
+ private static bool LastWriteTimesHaveChanged()
|
||||||
|
+ {
|
||||||
|
+ Debug.Assert(
|
||||||
|
+ Monitor.IsEntered(s_recheckStopwatch),
|
||||||
|
+ "LastWriteTimesHaveChanged assumes a lock(s_recheckStopwatch)");
|
||||||
|
+
|
||||||
|
+ if (s_rootStoreFile != null)
|
||||||
|
+ {
|
||||||
|
+ _ = TryStatFile(s_rootStoreFile, out DateTime lastModified);
|
||||||
|
+ if (lastModified != s_fileLastWrite)
|
||||||
|
+ {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (s_rootStoreDirectories != null && s_directoryLastWrite != null)
|
||||||
|
+ {
|
||||||
|
+ for (int i = 0; i < s_rootStoreDirectories.Length; i++)
|
||||||
|
+ {
|
||||||
|
+ _ = TryStatDirectory(s_rootStoreDirectories[i], out DateTime lastModified);
|
||||||
|
+ if (lastModified != s_directoryLastWrite[i])
|
||||||
|
+ {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private static Tuple<SafeX509StackHandle, SafeX509StackHandle> LoadMachineStores()
|
||||||
|
{
|
||||||
|
Debug.Assert(
|
||||||
|
Monitor.IsEntered(s_recheckStopwatch),
|
||||||
|
@@ -126,61 +147,76 @@ public void Remove(ICertificatePal cert)
|
||||||
|
SafeX509StackHandle intermedStore = Interop.Crypto.NewX509Stack();
|
||||||
|
Interop.Crypto.CheckValidOpenSslHandle(intermedStore);
|
||||||
|
|
||||||
|
- DateTime newFileTime = default;
|
||||||
|
- DateTime newDirTime = default;
|
||||||
|
-
|
||||||
|
var uniqueRootCerts = new HashSet<X509Certificate2>();
|
||||||
|
var uniqueIntermediateCerts = new HashSet<X509Certificate2>();
|
||||||
|
bool firstLoad = (s_nativeCollections == null);
|
||||||
|
|
||||||
|
- if (rootStoreFile != null && rootStoreFile.Exists)
|
||||||
|
+ if (firstLoad)
|
||||||
|
{
|
||||||
|
- newFileTime = ContentWriteTime(rootStoreFile);
|
||||||
|
- ProcessFile(rootStoreFile);
|
||||||
|
+ s_rootStoreDirectories = GetRootStoreDirectories(out s_defaultRootDir);
|
||||||
|
+ s_directoryLastWrite = new DateTime[s_rootStoreDirectories.Length];
|
||||||
|
+ s_rootStoreFile = GetRootStoreFile();
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ Debug.Assert(s_rootStoreDirectories is not null);
|
||||||
|
+ Debug.Assert(s_directoryLastWrite is not null);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (s_rootStoreFile != null)
|
||||||
|
+ {
|
||||||
|
+ ProcessFile(s_rootStoreFile, out s_fileLastWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasStoreData = false;
|
||||||
|
|
||||||
|
- if (rootStorePath != null && rootStorePath.Exists)
|
||||||
|
+ for (int i = 0; i < s_rootStoreDirectories.Length; i++)
|
||||||
|
{
|
||||||
|
- newDirTime = ContentWriteTime(rootStorePath);
|
||||||
|
- hasStoreData = ProcessDir(rootStorePath);
|
||||||
|
+ hasStoreData = ProcessDir(s_rootStoreDirectories[i], out s_directoryLastWrite[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstLoad && !hasStoreData && s_defaultRootDir)
|
||||||
|
{
|
||||||
|
- DirectoryInfo etcSslCerts = new DirectoryInfo("/etc/ssl/certs");
|
||||||
|
-
|
||||||
|
- if (etcSslCerts.Exists)
|
||||||
|
+ const string DefaultCertDir = "/etc/ssl/certs";
|
||||||
|
+ hasStoreData = ProcessDir(DefaultCertDir, out DateTime lastModified);
|
||||||
|
+ if (hasStoreData)
|
||||||
|
{
|
||||||
|
- DateTime tmpTime = ContentWriteTime(etcSslCerts);
|
||||||
|
- hasStoreData = ProcessDir(etcSslCerts);
|
||||||
|
-
|
||||||
|
- if (hasStoreData)
|
||||||
|
- {
|
||||||
|
- newDirTime = tmpTime;
|
||||||
|
- s_rootStoreDirectoryInfo = etcSslCerts;
|
||||||
|
- }
|
||||||
|
+ s_rootStoreDirectories = new[] { DefaultCertDir };
|
||||||
|
+ s_directoryLastWrite = new[] { lastModified };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- bool ProcessDir(DirectoryInfo dir)
|
||||||
|
+ bool ProcessDir(string dir, out DateTime lastModified)
|
||||||
|
{
|
||||||
|
+ if (!TryStatDirectory(dir, out lastModified))
|
||||||
|
+ {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
bool hasStoreData = false;
|
||||||
|
|
||||||
|
- foreach (FileInfo file in dir.EnumerateFiles())
|
||||||
|
+ foreach (string file in Directory.EnumerateFiles(dir))
|
||||||
|
{
|
||||||
|
- hasStoreData |= ProcessFile(file);
|
||||||
|
+ hasStoreData |= ProcessFile(file, out _, skipStat: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasStoreData;
|
||||||
|
}
|
||||||
|
|
||||||
|
- bool ProcessFile(FileInfo file)
|
||||||
|
+ bool ProcessFile(string file, out DateTime lastModified, bool skipStat = false)
|
||||||
|
{
|
||||||
|
bool readData = false;
|
||||||
|
|
||||||
|
- using (SafeBioHandle fileBio = Interop.Crypto.BioNewFile(file.FullName, "rb"))
|
||||||
|
+ if (skipStat)
|
||||||
|
+ {
|
||||||
|
+ lastModified = default;
|
||||||
|
+ }
|
||||||
|
+ else if (!TryStatFile(file, out lastModified))
|
||||||
|
+ {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ using (SafeBioHandle fileBio = Interop.Crypto.BioNewFile(file, "rb"))
|
||||||
|
{
|
||||||
|
// The handle may be invalid, for example when we don't have read permission for the file.
|
||||||
|
if (fileBio.IsInvalid)
|
||||||
|
@@ -274,114 +310,78 @@ bool ProcessFile(FileInfo file)
|
||||||
|
// on every call.
|
||||||
|
|
||||||
|
Volatile.Write(ref s_nativeCollections, newCollections);
|
||||||
|
- s_directoryCertsLastWrite = newDirTime;
|
||||||
|
- s_fileCertsLastWrite = newFileTime;
|
||||||
|
s_recheckStopwatch.Restart();
|
||||||
|
return newCollections;
|
||||||
|
}
|
||||||
|
|
||||||
|
- private static FileInfo? SafeOpenRootFileInfo()
|
||||||
|
+ private static string? GetRootStoreFile()
|
||||||
|
{
|
||||||
|
string? rootFile = Interop.Crypto.GetX509RootStoreFile();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(rootFile))
|
||||||
|
{
|
||||||
|
- try
|
||||||
|
- {
|
||||||
|
- return new FileInfo(rootFile);
|
||||||
|
- }
|
||||||
|
- catch (ArgumentException)
|
||||||
|
- {
|
||||||
|
- // If SSL_CERT_FILE is set to the empty string, or anything else which gives
|
||||||
|
- // "The path is not of a legal form", then the GetX509RootStoreFile value is ignored.
|
||||||
|
- }
|
||||||
|
+ return Path.GetFullPath(rootFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
- private static DirectoryInfo? SafeOpenRootDirectoryInfo()
|
||||||
|
+ private static string[] GetRootStoreDirectories(out bool isDefault)
|
||||||
|
{
|
||||||
|
- string? rootDirectory = Interop.Crypto.GetX509RootStorePath(out s_defaultRootDir);
|
||||||
|
+ string rootDirectory = Interop.Crypto.GetX509RootStorePath(out isDefault) ?? "";
|
||||||
|
|
||||||
|
- if (!string.IsNullOrEmpty(rootDirectory))
|
||||||
|
- {
|
||||||
|
- try
|
||||||
|
- {
|
||||||
|
- return new DirectoryInfo(rootDirectory);
|
||||||
|
- }
|
||||||
|
- catch (ArgumentException)
|
||||||
|
- {
|
||||||
|
- // If SSL_CERT_DIR is set to the empty string, or anything else which gives
|
||||||
|
- // "The path is not of a legal form", then the GetX509RootStoreFile value is ignored.
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return null;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- private static DateTime ContentWriteTime(FileInfo info)
|
||||||
|
- {
|
||||||
|
- string path = info.FullName;
|
||||||
|
- string? target = Interop.Sys.ReadLink(path);
|
||||||
|
-
|
||||||
|
- if (string.IsNullOrEmpty(target))
|
||||||
|
- {
|
||||||
|
- return info.LastWriteTimeUtc;
|
||||||
|
- }
|
||||||
|
+ string[] directories = rootDirectory.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
- if (target[0] != '/')
|
||||||
|
+ for (int i = 0; i < directories.Length; i++)
|
||||||
|
{
|
||||||
|
- target = Path.Join(info.Directory?.FullName, target);
|
||||||
|
+ directories[i] = Path.GetFullPath(directories[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- try
|
||||||
|
+ // Remove duplicates.
|
||||||
|
+ if (directories.Length > 1)
|
||||||
|
{
|
||||||
|
- var targetInfo = new FileInfo(target);
|
||||||
|
-
|
||||||
|
- if (targetInfo.Exists)
|
||||||
|
+ var set = new HashSet<string>(directories, StringComparer.Ordinal);
|
||||||
|
+ if (set.Count != directories.Length)
|
||||||
|
{
|
||||||
|
- return targetInfo.LastWriteTimeUtc;
|
||||||
|
+ // Preserve the original order.
|
||||||
|
+ string[] directoriesTrimmed = new string[set.Count];
|
||||||
|
+ int j = 0;
|
||||||
|
+ for (int i = 0; i < directories.Length; i++)
|
||||||
|
+ {
|
||||||
|
+ string directory = directories[i];
|
||||||
|
+ if (set.Remove(directory))
|
||||||
|
+ {
|
||||||
|
+ directoriesTrimmed[j++] = directory;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ Debug.Assert(set.Count == 0);
|
||||||
|
+ directories = directoriesTrimmed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- catch (ArgumentException)
|
||||||
|
- {
|
||||||
|
- // If we can't load information about the link path, just treat it as not a link.
|
||||||
|
- }
|
||||||
|
|
||||||
|
- return info.LastWriteTimeUtc;
|
||||||
|
+ return directories;
|
||||||
|
}
|
||||||
|
|
||||||
|
- private static DateTime ContentWriteTime(DirectoryInfo info)
|
||||||
|
- {
|
||||||
|
- string path = info.FullName;
|
||||||
|
- string? target = Interop.Sys.ReadLink(path);
|
||||||
|
-
|
||||||
|
- if (string.IsNullOrEmpty(target))
|
||||||
|
- {
|
||||||
|
- return info.LastWriteTimeUtc;
|
||||||
|
- }
|
||||||
|
+ private static bool TryStatFile(string path, out DateTime lastModified)
|
||||||
|
+ => TryStat(path, Interop.Sys.FileTypes.S_IFREG, out lastModified);
|
||||||
|
|
||||||
|
- if (target[0] != '/')
|
||||||
|
- {
|
||||||
|
- target = Path.Join(info.Parent?.FullName, target);
|
||||||
|
- }
|
||||||
|
+ private static bool TryStatDirectory(string path, out DateTime lastModified)
|
||||||
|
+ => TryStat(path, Interop.Sys.FileTypes.S_IFDIR, out lastModified);
|
||||||
|
|
||||||
|
- try
|
||||||
|
- {
|
||||||
|
- var targetInfo = new DirectoryInfo(target);
|
||||||
|
+ private static bool TryStat(string path, int fileType, out DateTime lastModified)
|
||||||
|
+ {
|
||||||
|
+ lastModified = default;
|
||||||
|
|
||||||
|
- if (targetInfo.Exists)
|
||||||
|
- {
|
||||||
|
- return targetInfo.LastWriteTimeUtc;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- catch (ArgumentException)
|
||||||
|
+ Interop.Sys.FileStatus status;
|
||||||
|
+ // Use Stat to follow links.
|
||||||
|
+ if (Interop.Sys.Stat(path, out status) < 0 ||
|
||||||
|
+ (status.Mode & Interop.Sys.FileTypes.S_IFMT) != fileType)
|
||||||
|
{
|
||||||
|
- // If we can't load information about the link path, just treat it as not a link.
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return info.LastWriteTimeUtc;
|
||||||
|
+ lastModified = DateTime.UnixEpoch + TimeSpan.FromTicks(status.MTime * TimeSpan.TicksPerSecond + status.MTimeNsec / TimeSpan.NanosecondsPerTick);
|
||||||
|
+ return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/src/runtime/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.Unix.cs b/src/runtime/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.Unix.cs
|
||||||
|
index 0efb6c12028..f460d6b9bd6 100644
|
||||||
|
--- a/src/runtime/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.Unix.cs
|
||||||
|
+++ b/src/runtime/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.Unix.cs
|
||||||
|
@@ -10,7 +10,6 @@ namespace System.Security.Cryptography.X509Certificates.Tests
|
||||||
|
{
|
||||||
|
public partial class X509StoreTests
|
||||||
|
{
|
||||||
|
-
|
||||||
|
[ConditionalFact(nameof(NotRunningAsRootAndRemoteExecutorSupported))] // root can read '2.pem'
|
||||||
|
[PlatformSpecific(TestPlatforms.Linux)] // Windows/OSX doesn't use SSL_CERT_{DIR,FILE}.
|
||||||
|
private void X509Store_MachineStoreLoadSkipsInvalidFiles()
|
||||||
|
@@ -50,6 +49,47 @@ private void X509Store_MachineStoreLoadSkipsInvalidFiles()
|
||||||
|
}, new RemoteInvokeOptions { StartInfo = psi }).Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
|
||||||
|
+ [PlatformSpecific(TestPlatforms.Linux)] // Windows/OSX doesn't use SSL_CERT_{DIR,FILE}.
|
||||||
|
+ private void X509Store_MachineStoreLoadsMutipleSslCertDirectories()
|
||||||
|
+ {
|
||||||
|
+ // Create 3 certificates and place them in two directories that will be passed
|
||||||
|
+ // using SSL_CERT_DIR.
|
||||||
|
+ string sslCertDir1 = GetTestFilePath();
|
||||||
|
+ Directory.CreateDirectory(sslCertDir1);
|
||||||
|
+ File.WriteAllBytes(Path.Combine(sslCertDir1, "1.pem"), TestData.SelfSigned1PemBytes);
|
||||||
|
+ File.WriteAllBytes(Path.Combine(sslCertDir1, "2.pem"), TestData.SelfSigned2PemBytes);
|
||||||
|
+ string sslCertDir2 = GetTestFilePath();
|
||||||
|
+ Directory.CreateDirectory(sslCertDir2);
|
||||||
|
+ File.WriteAllBytes(Path.Combine(sslCertDir2, "3.pem"), TestData.SelfSigned3PemBytes);
|
||||||
|
+
|
||||||
|
+ // Add a non-existing directory after each valid directory to verify they are ignored.
|
||||||
|
+ string sslCertDir = string.Join(Path.PathSeparator,
|
||||||
|
+ new[] {
|
||||||
|
+ sslCertDir1,
|
||||||
|
+ sslCertDir2,
|
||||||
|
+ "", // empty string
|
||||||
|
+ sslCertDir2, // duplicate directory
|
||||||
|
+ "/invalid2", // path that does not exist
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ var psi = new ProcessStartInfo();
|
||||||
|
+ psi.Environment.Add("SSL_CERT_DIR", sslCertDir);
|
||||||
|
+ // Set SSL_CERT_FILE to avoid loading the default bundle file.
|
||||||
|
+ psi.Environment.Add("SSL_CERT_FILE", "/nonexisting");
|
||||||
|
+ RemoteExecutor.Invoke(() =>
|
||||||
|
+ {
|
||||||
|
+ Assert.NotNull(Environment.GetEnvironmentVariable("SSL_CERT_DIR"));
|
||||||
|
+ using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine))
|
||||||
|
+ {
|
||||||
|
+ store.Open(OpenFlags.OpenExistingOnly);
|
||||||
|
+
|
||||||
|
+ // Check nr of certificates in store.
|
||||||
|
+ Assert.Equal(3, store.Certificates.Count);
|
||||||
|
+ }
|
||||||
|
+ }, new RemoteInvokeOptions { StartInfo = psi }).Dispose();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
public static bool NotRunningAsRootAndRemoteExecutorSupported => !Environment.IsPrivilegedProcess && RemoteExecutor.IsSupported;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
diff --git a/src/vstest/test/Intent/Intent.csproj b/src/vstest/test/Intent/Intent.csproj
|
||||||
|
index bb711c9256..6d0b199a9b 100644
|
||||||
|
--- a/src/vstest/test/Intent/Intent.csproj
|
||||||
|
+++ b/src/vstest/test/Intent/Intent.csproj
|
||||||
|
@@ -2,7 +2,7 @@
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
- <TargetFramework>net6.0</TargetFramework>
|
||||||
|
+ <TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue