private static bool DoVerifyIL(Resolver resolver, SandboxConfig config, PEReader peReader, MetadataReader reader) { Logger.DebugS("res.typecheck", "Verifying IL..."); var sw = Stopwatch.StartNew(); var ver = new Verifier(resolver); ver.SetSystemModuleName(new AssemblyName(config.SystemAssemblyName)); var verifyErrors = false; foreach (var res in ver.Verify(peReader)) { if (config.AllowedVerifierErrors.Contains(res.Code)) { continue; } var msg = $"ILVerify: {res.Message}"; try { if (!res.Method.IsNil) { var method = reader.GetMethodDefinition(res.Method); var methodSig = method.DecodeSignature(new TypeProvider(), 0); var type = GetTypeFromDefinition(reader, method.GetDeclaringType()); var methodName = $"{methodSig.ReturnType} {type}.{reader.GetString(method.Name)}({string.Join(", ", methodSig.ParameterTypes)})"; msg = $"{msg}, method: {methodName}"; } if (!res.Type.IsNil) { var type = GetTypeFromDefinition(reader, res.Type); msg = $"{msg}, type: {type}"; } } catch (UnsupportedMetadataException e) { Logger.ErrorS("res.typecheck", $"{e}"); } verifyErrors = true; Logger.ErrorS("res.typecheck", msg); } Logger.DebugS("res.typecheck", $"Verified IL in {sw.Elapsed.TotalMilliseconds}ms"); if (verifyErrors) { return(false); } return(true); }
private static void CheckMemberReferences(List <MMemberRef> members, SandboxConfig config, ConcurrentBag <SandboxError> errors) { Parallel.ForEach(members, memberRef => { MType baseType = memberRef.ParentType; while (!(baseType is MTypeReferenced)) { switch (baseType) { case MTypeGeneric generic: { baseType = generic.GenericType; break; } case MTypeArray array: { // For this kind of array we just need access to the type itself. if (!IsTypeAccessAllowed((MTypeReferenced)array.ElementType, config, out _)) { errors.Add(new SandboxError($"Access to type not allowed: {array}")); } return; // Found } default: { throw new ArgumentOutOfRangeException(); } } } var baseTypeReferenced = (MTypeReferenced)baseType; if (!IsTypeAccessAllowed(baseTypeReferenced, config, out var typeCfg)) { errors.Add(new SandboxError($"Access to type not allowed: {baseTypeReferenced}")); return; } if (typeCfg.All) { // Fully whitelisted for the type, we good. return; } switch (memberRef) { case MMemberRefField mMemberRefField: { foreach (var field in typeCfg.FieldsParsed) { if (field.Name == mMemberRefField.Name && mMemberRefField.FieldType.WhitelistEquals(field.FieldType)) { return; // Found } } errors.Add(new SandboxError($"Access to field not allowed: {mMemberRefField}")); break; } case MMemberRefMethod mMemberRefMethod: foreach (var parsed in typeCfg.MethodsParsed) { if (parsed.Name == mMemberRefMethod.Name && mMemberRefMethod.ReturnType.WhitelistEquals(parsed.ReturnType) && mMemberRefMethod.ParameterTypes.Length == parsed.ParameterTypes.Length && mMemberRefMethod.GenericParameterCount == parsed.GenericParameterCount) { for (var i = 0; i < mMemberRefMethod.ParameterTypes.Length; i++) { var a = mMemberRefMethod.ParameterTypes[i]; var b = parsed.ParameterTypes[i]; if (!a.WhitelistEquals(b)) { goto paramMismatch; } } return; // Found } paramMismatch:; } errors.Add(new SandboxError($"Access to method not allowed: {mMemberRefMethod}")); break; default: throw new ArgumentOutOfRangeException(nameof(memberRef)); } }); }