-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
…fix small bug with the server view model not clearing old Downloads
- Loading branch information
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Reflection.Metadata; | ||
using System.Reflection.PortableExecutable; | ||
using System.Threading.Tasks; | ||
using ILVerify; | ||
using UnitystationLauncher.Constants; | ||
using UnitystationLauncher.Models.ConfigFile; | ||
|
||
namespace UnitystationLauncher.ContentScanning.Scanners; | ||
|
||
internal static class IlScanner | ||
{ | ||
private static readonly bool _parallelIlScanning = false; | ||
Check notice on line 16 in UnitystationLauncher/ContentScanning/Scanners/IlScanner.cs Codacy Production / Codacy Static Code AnalysisUnitystationLauncher/ContentScanning/Scanners/IlScanner.cs#L16
|
||
|
||
internal static bool DoVerifyIl(string name, IResolver resolver, PEReader peReader, | ||
MetadataReader reader, Action<string> info, Action<string> logErrors, SandboxConfig loadedCfg) | ||
{ | ||
info.Invoke($"{name}: Verifying IL..."); | ||
Stopwatch sw = Stopwatch.StartNew(); | ||
ConcurrentBag<VerificationResult> bag = new(); | ||
|
||
// TODO: We should probably just pick one of these and remove the other | ||
if (_parallelIlScanning) | ||
{ | ||
IlScanner.ParallelIlScanning(reader, resolver, peReader, bag); | ||
} | ||
else | ||
{ | ||
IlScanner.NonParallelIlScanning(reader, resolver, peReader, bag); | ||
} | ||
|
||
bool verifyErrors = false; | ||
foreach (VerificationResult res in bag) | ||
{ | ||
bool error = AssemblyTypeCheckerHelpers.CheckVerificationResult(loadedCfg, res, name, reader, logErrors); | ||
if (error) | ||
{ | ||
verifyErrors = true; | ||
} | ||
} | ||
|
||
info.Invoke($"{name}: Verified IL in {sw.Elapsed.TotalMilliseconds}ms"); | ||
|
||
if (verifyErrors) | ||
{ | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
private static void ParallelIlScanning(MetadataReader reader, IResolver resolver, PEReader peReader, ConcurrentBag<VerificationResult> bag) | ||
{ | ||
OrderablePartitioner<TypeDefinitionHandle> partitioner = Partitioner.Create(reader.TypeDefinitions); | ||
Parallel.ForEach(partitioner.GetPartitions(Environment.ProcessorCount), handle => | ||
{ | ||
Verifier ver = new(resolver); | ||
ver.SetSystemModuleName(new(AssemblyNames.SystemAssemblyName)); | ||
while (handle.MoveNext()) | ||
{ | ||
foreach (VerificationResult? result in ver.Verify(peReader, handle.Current, verifyMethods: true)) | ||
{ | ||
bag.Add(result); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
private static void NonParallelIlScanning(MetadataReader reader, IResolver resolver, PEReader peReader, ConcurrentBag<VerificationResult> bag) | ||
{ | ||
Verifier ver = new(resolver); | ||
//mscorlib | ||
ver.SetSystemModuleName(new(AssemblyNames.SystemAssemblyName)); | ||
foreach (TypeDefinitionHandle definition in reader.TypeDefinitions) | ||
{ | ||
IEnumerable<VerificationResult> errors = ver.Verify(peReader, definition, verifyMethods: true); | ||
foreach (VerificationResult error in errors) | ||
{ | ||
bag.Add(error); | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using UnitystationLauncher.Models.ConfigFile; | ||
using UnitystationLauncher.Models.ContentScanning; | ||
using UnitystationLauncher.Models.ContentScanning.ScanningTypes; | ||
using UnitystationLauncher.Models.Enums; | ||
|
||
namespace UnitystationLauncher.ContentScanning.Scanners; | ||
|
||
internal static class InheritanceScanner | ||
{ | ||
internal static void CheckInheritance( | ||
SandboxConfig sandboxConfig, | ||
List<(MType type, MType parent, ArraySegment<MType> interfaceImpls)> inherited, | ||
ConcurrentBag<SandboxError> errors) | ||
{ | ||
// This inheritance whitelisting primarily serves to avoid content doing funny stuff | ||
// by e.g. inheriting Type. | ||
foreach ((MType _, MType baseType, ArraySegment<MType> interfaces) in inherited) | ||
{ | ||
if (CanInherit(baseType) == false) | ||
{ | ||
errors.Add(new($"Inheriting of type not allowed: {baseType}")); | ||
} | ||
|
||
foreach (MType @interface in interfaces) | ||
{ | ||
if (CanInherit(@interface) == false) | ||
{ | ||
errors.Add(new($"Implementing of interface not allowed: {@interface}")); | ||
} | ||
} | ||
|
||
bool CanInherit(MType inheritType) | ||
{ | ||
MTypeReferenced realBaseType = inheritType switch | ||
{ | ||
MTypeGeneric generic => (MTypeReferenced)generic.GenericType, | ||
MTypeReferenced referenced => referenced, | ||
_ => throw new InvalidOperationException() // Can't happen. | ||
}; | ||
|
||
if (realBaseType.IsTypeAccessAllowed(sandboxConfig, out TypeConfig? cfg) == false) | ||
{ | ||
return false; | ||
} | ||
|
||
return cfg.Inherit != InheritMode.Block && (cfg.Inherit == InheritMode.Allow || cfg.All); | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
using UnitystationLauncher.Models.ConfigFile; | ||
using UnitystationLauncher.Models.ContentScanning; | ||
using UnitystationLauncher.Models.ContentScanning.ScanningTypes; | ||
|
||
namespace UnitystationLauncher.ContentScanning.Scanners; | ||
|
||
internal static class MemberReferenceScanner | ||
Check warning on line 11 in UnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs Codacy Production / Codacy Static Code AnalysisUnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs#L11
|
||
{ | ||
private static readonly bool _parallelMemberReferencesScanning = true; | ||
|
||
public static void CheckMemberReferences(SandboxConfig sandboxConfig, List<MMemberRef> members, ConcurrentBag<SandboxError> errors) | ||
{ | ||
// TODO: We should probably just pick one of these and remove the other | ||
if (_parallelMemberReferencesScanning) | ||
{ | ||
ParallelCheckMemberReferences(sandboxConfig, members, errors); | ||
} | ||
else | ||
{ | ||
NonParallelCheckMemberReferences(sandboxConfig, members, errors); | ||
} | ||
} | ||
|
||
|
||
private static void ParallelCheckMemberReferences(SandboxConfig sandboxConfig, List<MMemberRef> members, ConcurrentBag<SandboxError> errors) | ||
Check failure on line 29 in UnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs Codacy Production / Codacy Static Code AnalysisUnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs#L29
Check warning on line 29 in UnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs Codacy Production / Codacy Static Code AnalysisUnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs#L29
|
||
{ | ||
Parallel.ForEach(members, memberRef => | ||
{ | ||
MType baseType = memberRef.ParentType; | ||
while (!(baseType is MTypeReferenced)) | ||
{ | ||
switch (baseType) | ||
{ | ||
case MTypeGeneric generic: | ||
{ | ||
baseType = generic.GenericType; | ||
|
||
break; | ||
} | ||
case MTypeWackyArray: | ||
{ | ||
// Members on arrays (not to be confused with vectors) are all fine. | ||
// See II.14.2 in ECMA-335. | ||
return; | ||
} | ||
case MTypeDefined: | ||
{ | ||
// Valid for this to show up, safe to ignore. | ||
return; | ||
} | ||
default: | ||
{ | ||
throw new ArgumentOutOfRangeException(); | ||
} | ||
} | ||
} | ||
|
||
MTypeReferenced baseTypeReferenced = (MTypeReferenced)baseType; | ||
|
||
if (baseTypeReferenced.IsTypeAccessAllowed(sandboxConfig, out TypeConfig? typeCfg) == false) | ||
{ | ||
// Technically this error isn't necessary since we have an earlier pass | ||
// checking all referenced types. That should have caught this | ||
// We still need the typeCfg so that's why we're checking. Might as well. | ||
errors.Add(new($"Access to type not allowed: {baseTypeReferenced}")); | ||
return; | ||
} | ||
|
||
if (typeCfg.All) | ||
{ | ||
// Fully whitelisted for the type, we good. | ||
return; | ||
} | ||
|
||
switch (memberRef) | ||
{ | ||
case MMemberRefField mMemberRefField: | ||
{ | ||
foreach (WhitelistFieldDefine field in typeCfg.FieldsParsed) | ||
{ | ||
if (field.Name == mMemberRefField.Name && | ||
mMemberRefField.FieldType.WhitelistEquals(field.FieldType)) | ||
{ | ||
return; // Found | ||
} | ||
} | ||
|
||
errors.Add(new($"Access to field not allowed: {mMemberRefField}")); | ||
break; | ||
} | ||
case MMemberRefMethod mMemberRefMethod: | ||
Check warning on line 95 in UnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs Codacy Production / Codacy Static Code AnalysisUnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs#L95
|
||
foreach (WhitelistMethodDefine parsed in typeCfg.MethodsParsed) | ||
{ | ||
bool notParamMismatch = true; | ||
|
||
if (parsed.Name == mMemberRefMethod.Name && | ||
mMemberRefMethod.ReturnType.WhitelistEquals(parsed.ReturnType) && | ||
mMemberRefMethod.ParameterTypes.Length == parsed.ParameterTypes.Count && | ||
mMemberRefMethod.GenericParameterCount == parsed.GenericParameterCount) | ||
{ | ||
for (int i = 0; i < mMemberRefMethod.ParameterTypes.Length; i++) | ||
Check failure on line 105 in UnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs Codacy Production / Codacy Static Code AnalysisUnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs#L105
|
||
{ | ||
MType a = mMemberRefMethod.ParameterTypes[i]; | ||
MType b = parsed.ParameterTypes[i]; | ||
|
||
if (a.WhitelistEquals(b) == false) | ||
{ | ||
notParamMismatch = false; | ||
break; | ||
} | ||
} | ||
|
||
if (notParamMismatch) | ||
Check failure on line 117 in UnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs Codacy Production / Codacy Static Code AnalysisUnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs#L117
|
||
{ | ||
return; // Found | ||
} | ||
} | ||
} | ||
|
||
errors.Add(new($"Access to method not allowed: {mMemberRefMethod}")); | ||
break; | ||
default: | ||
throw new ArgumentOutOfRangeException(nameof(memberRef)); | ||
} | ||
}); | ||
} | ||
|
||
private static void NonParallelCheckMemberReferences(SandboxConfig sandboxConfig, List<MMemberRef> members, ConcurrentBag<SandboxError> errors) | ||
Check failure on line 132 in UnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs Codacy Production / Codacy Static Code AnalysisUnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs#L132
Check warning on line 132 in UnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs Codacy Production / Codacy Static Code AnalysisUnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs#L132
|
||
{ | ||
foreach (MMemberRef memberRef in members) | ||
{ | ||
MType baseType = memberRef.ParentType; | ||
while (!(baseType is MTypeReferenced)) | ||
{ | ||
switch (baseType) | ||
{ | ||
case MTypeGeneric generic: | ||
{ | ||
baseType = generic.GenericType; | ||
|
||
break; | ||
} | ||
case MTypeWackyArray: | ||
{ | ||
// Members on arrays (not to be confused with vectors) are all fine. | ||
// See II.14.2 in ECMA-335. | ||
continue; | ||
} | ||
case MTypeDefined: | ||
{ | ||
// Valid for this to show up, safe to ignore. | ||
continue; | ||
} | ||
default: | ||
{ | ||
throw new ArgumentOutOfRangeException(); | ||
} | ||
} | ||
} | ||
|
||
MTypeReferenced baseTypeReferenced = (MTypeReferenced)baseType; | ||
|
||
if (baseTypeReferenced.IsTypeAccessAllowed(sandboxConfig, out TypeConfig? typeCfg) == false) | ||
{ | ||
// Technically this error isn't necessary since we have an earlier pass | ||
// checking all referenced types. That should have caught this | ||
// We still need the typeCfg so that's why we're checking. Might as well. | ||
errors.Add(new($"Access to type not allowed: {baseTypeReferenced}")); | ||
continue; | ||
} | ||
|
||
if (typeCfg.All) | ||
{ | ||
// Fully whitelisted for the type, we good. | ||
continue; | ||
} | ||
|
||
switch (memberRef) | ||
{ | ||
case MMemberRefField mMemberRefField: | ||
{ | ||
foreach (WhitelistFieldDefine field in typeCfg.FieldsParsed) | ||
{ | ||
if (field.Name == mMemberRefField.Name && | ||
Check failure on line 188 in UnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs Codacy Production / Codacy Static Code AnalysisUnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs#L188
|
||
mMemberRefField.FieldType.WhitelistEquals(field.FieldType)) | ||
{ | ||
continue; // Found | ||
} | ||
} | ||
|
||
errors.Add(new($"Access to field not allowed: {mMemberRefField}")); | ||
break; | ||
} | ||
case MMemberRefMethod mMemberRefMethod: | ||
bool notParamMismatch = true; | ||
foreach (WhitelistMethodDefine parsed in typeCfg.MethodsParsed) | ||
{ | ||
if (parsed.Name == mMemberRefMethod.Name && | ||
Check failure on line 202 in UnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs Codacy Production / Codacy Static Code AnalysisUnitystationLauncher/ContentScanning/Scanners/MemberReferenceScanner.cs#L202
|
||
mMemberRefMethod.ReturnType.WhitelistEquals(parsed.ReturnType) && | ||
mMemberRefMethod.ParameterTypes.Length == parsed.ParameterTypes.Count && | ||
mMemberRefMethod.GenericParameterCount == parsed.GenericParameterCount) | ||
{ | ||
for (int i = 0; i < mMemberRefMethod.ParameterTypes.Length; i++) | ||
{ | ||
MType a = mMemberRefMethod.ParameterTypes[i]; | ||
MType b = parsed.ParameterTypes[i]; | ||
|
||
if (!a.WhitelistEquals(b)) | ||
{ | ||
notParamMismatch = false; | ||
break; | ||
|
||
} | ||
} | ||
|
||
if (notParamMismatch) | ||
{ | ||
break; // Found | ||
} | ||
break; | ||
} | ||
} | ||
|
||
if (notParamMismatch == false) | ||
{ | ||
continue; | ||
} | ||
|
||
errors.Add(new($"Access to method not allowed: {mMemberRefMethod}")); | ||
break; | ||
default: | ||
throw new ArgumentOutOfRangeException(nameof(memberRef)); | ||
} | ||
} | ||
} | ||
} |