From 67a5eefa39bdd35668c0e2ca4953927a8e35ea7c Mon Sep 17 00:00:00 2001 From: "Xamarin Public Jenkins (auto-signing)" Date: Wed, 3 May 2017 16:24:32 +0000 Subject: [PATCH] Imported Upstream version 5.0.0.94 Former-commit-id: 09772966aff74491c7b98b6eda49852cfc4aa874 --- .../AppContextDefaultValues.cs | 28 +++++++++ .../ReferenceSources/AppContextSwitches.cs | 7 --- .../CustomAttributeBuilderTest.cs | 55 ++++++++++++++++++ .../CancellationTokenSourceTest.cs | 22 ++++--- mcs/class/corlib/corlib.dll.sources | 3 +- .../1050000000/mscorlib.dll.REMOVED.git-id | 2 +- .../mscorlib/system/AppContext/AppContext.cs | 8 +-- .../system/AppContext/AppContextSwitches.cs | 6 ++ mcs/tools/cil-strip/AssemblyStripper.cs | 2 + mono/metadata/sre-internals.h | 3 + mono/metadata/sre-save.c.REMOVED.git-id | 2 +- mono/metadata/sre.c.REMOVED.git-id | 2 +- mono/mini/Makefile.am | 2 +- mono/mini/Makefile.am.in | 2 +- mono/mini/Makefile.in.REMOVED.git-id | 2 +- mono/mini/jit-icalls.c | 11 +++- mono/mini/mini-arm.c.REMOVED.git-id | 2 +- mono/mini/version.h | 2 +- mono/tests/Makefile.am | 2 + mono/tests/Makefile.in | 2 + mono/tests/generic-special2.2.cs | 54 +++++++++++++++++ po/mcs/de.gmo | Bin 5406 -> 5406 bytes po/mcs/de.po.REMOVED.git-id | 2 +- po/mcs/es.gmo | Bin 16329 -> 16329 bytes po/mcs/es.po.REMOVED.git-id | 2 +- po/mcs/ja.gmo | Bin 20863 -> 20863 bytes po/mcs/ja.po.REMOVED.git-id | 2 +- po/mcs/mcs.pot | 2 +- po/mcs/pt_BR.gmo | Bin 73161 -> 73161 bytes po/mcs/pt_BR.po.REMOVED.git-id | 2 +- 30 files changed, 191 insertions(+), 38 deletions(-) create mode 100644 mcs/class/corlib/ReferenceSources/AppContextDefaultValues.cs delete mode 100644 mcs/class/corlib/ReferenceSources/AppContextSwitches.cs create mode 100644 mono/tests/generic-special2.2.cs diff --git a/mcs/class/corlib/ReferenceSources/AppContextDefaultValues.cs b/mcs/class/corlib/ReferenceSources/AppContextDefaultValues.cs new file mode 100644 index 0000000000..c5d66e05f9 --- /dev/null +++ b/mcs/class/corlib/ReferenceSources/AppContextDefaultValues.cs @@ -0,0 +1,28 @@ +using System; + +namespace System +{ + internal static class AppContextDefaultValues + { + internal const string SwitchNoAsyncCurrentCulture = "Switch.System.Globalization.NoAsyncCurrentCulture"; + internal const string SwitchThrowExceptionIfDisposedCancellationTokenSource = "Switch.System.Threading.ThrowExceptionIfDisposedCancellationTokenSource"; + internal const string SwitchPreserveEventListnerObjectIdentity = "Switch.System.Diagnostics.EventSource.PreserveEventListnerObjectIdentity"; + internal const string SwitchUseLegacyPathHandling = "Switch.System.IO.UseLegacyPathHandling"; + internal const string SwitchBlockLongPaths = "Switch.System.IO.BlockLongPaths"; + internal const string SwitchDoNotAddrOfCspParentWindowHandle = "Switch.System.Security.Cryptography.DoNotAddrOfCspParentWindowHandle"; + internal const string SwitchSetActorAsReferenceWhenCopyingClaimsIdentity = "Switch.System.Security.ClaimsIdentity.SetActorAsReferenceWhenCopyingClaimsIdentity"; + + public static void PopulateDefaultValues () { + } + + //TODO Use the values in app.config + public static bool TryGetSwitchOverride (string switchName, out bool overrideValue) + { + // The default value for a switch is 'false' + overrideValue = false; + + return false; + } + } +} + diff --git a/mcs/class/corlib/ReferenceSources/AppContextSwitches.cs b/mcs/class/corlib/ReferenceSources/AppContextSwitches.cs deleted file mode 100644 index 8874423d84..0000000000 --- a/mcs/class/corlib/ReferenceSources/AppContextSwitches.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace System { - static class AppContextSwitches { - public static readonly bool ThrowExceptionIfDisposedCancellationTokenSource = true; - public static readonly bool SetActorAsReferenceWhenCopyingClaimsIdentity = false; - public static readonly bool NoAsyncCurrentCulture = false; - } -} \ No newline at end of file diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/CustomAttributeBuilderTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/CustomAttributeBuilderTest.cs index eb6eff866c..c57616753f 100644 --- a/mcs/class/corlib/Test/System.Reflection.Emit/CustomAttributeBuilderTest.cs +++ b/mcs/class/corlib/Test/System.Reflection.Emit/CustomAttributeBuilderTest.cs @@ -790,6 +790,61 @@ namespace MonoTests.System.Reflection.Emit Assert.IsInstanceOfType (typeof (PublicVisibleCustomAttribute), attrs[1]); Assert.IsInstanceOfType (typeof (PublicVisibleCustomAttribute), attrs[2]); } + + [Test] + public void CustomAttributeSameAssembly () { + // Regression test for 55681 + // + // We build: + // class MyAttr : Attr { public MyAttr () { } } + // [assembly:MyAttr()] + // + // the important bit is that we pass the ConstructorBuilder to the CustomAttributeBuilder + var assemblyName = new AssemblyName ("Repro55681"); + var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.Save, tempDir); + var moduleBuilder = assemblyBuilder.DefineDynamicModule ("Repro55681", "Repro55681.dll"); + var typeBuilder = moduleBuilder.DefineType ("MyAttr", TypeAttributes.Public, typeof (Attribute)); + ConstructorBuilder ctor = typeBuilder.DefineDefaultConstructor (MethodAttributes.Public); + typeBuilder.CreateType (); + + assemblyBuilder.SetCustomAttribute (new CustomAttributeBuilder (ctor, new object [] { })); + + assemblyBuilder.Save ("Repro55681.dll"); + } + + [Test] + public void CustomAttributeAcrossAssemblies () { + // Regression test for 55681 + // + // We build: + // assembly1: + // class MyAttr : Attr { public MyAttr () { } } + // assembly2: + // class Dummy { } + // [assembly:MyAttr()] + // + // the important bit is that we pass the ConstructorBuilder to the CustomAttributeBuilder + var assemblyName1 = new AssemblyName ("Repro55681-2a"); + var assemblyBuilder1 = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName1, AssemblyBuilderAccess.Save, tempDir); + var moduleBuilder1 = assemblyBuilder1.DefineDynamicModule ("Repro55681-2a", "Repro55681-2a.dll"); + var typeBuilder1 = moduleBuilder1.DefineType ("MyAttr", TypeAttributes.Public, typeof (Attribute)); + ConstructorBuilder ctor = typeBuilder1.DefineDefaultConstructor (MethodAttributes.Public); + typeBuilder1.CreateType (); + + var assemblyName2 = new AssemblyName ("Repro55681-2b"); + var assemblyBuilder2 = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName2, AssemblyBuilderAccess.Save, tempDir); + var moduleBuilder2 = assemblyBuilder2.DefineDynamicModule ("Repro55681-2b", "Repro55681-2b.dll"); + + var typeBuilder2 = moduleBuilder2.DefineType ("Dummy", TypeAttributes.Public); + typeBuilder2.DefineDefaultConstructor (MethodAttributes.Public); + typeBuilder2.CreateType (); + + assemblyBuilder2.SetCustomAttribute (new CustomAttributeBuilder (ctor, new object [] { })); + + assemblyBuilder2.Save ("Repro55681-2b.dll"); + assemblyBuilder1.Save ("Repro55681-2a.dll"); + } + } } diff --git a/mcs/class/corlib/Test/System.Threading/CancellationTokenSourceTest.cs b/mcs/class/corlib/Test/System.Threading/CancellationTokenSourceTest.cs index f5b4dd9a3b..59d9b8cbba 100644 --- a/mcs/class/corlib/Test/System.Threading/CancellationTokenSourceTest.cs +++ b/mcs/class/corlib/Test/System.Threading/CancellationTokenSourceTest.cs @@ -325,10 +325,14 @@ namespace MonoTests.System.Threading } catch (ObjectDisposedException) { } - try { - token.Register (() => { }); - Assert.Fail ("#3"); - } catch (ObjectDisposedException) { + bool throwOnDispose = false; + AppContext.TryGetSwitch ("Switch.System.Threading.ThrowExceptionIfDisposedCancellationTokenSource", out throwOnDispose); + if (throwOnDispose) { + try { + token.Register (() => { }); + Assert.Fail ("#3"); + } catch (ObjectDisposedException) { + } } try { @@ -337,10 +341,12 @@ namespace MonoTests.System.Threading } catch (ObjectDisposedException) { } - try { - CancellationTokenSource.CreateLinkedTokenSource (token); - Assert.Fail ("#5"); - } catch (ObjectDisposedException) { + if (throwOnDispose) { + try { + CancellationTokenSource.CreateLinkedTokenSource (token); + Assert.Fail ("#5"); + } catch (ObjectDisposedException) { + } } try { diff --git a/mcs/class/corlib/corlib.dll.sources b/mcs/class/corlib/corlib.dll.sources index 1099b6e3fe..6b30c90bb8 100644 --- a/mcs/class/corlib/corlib.dll.sources +++ b/mcs/class/corlib/corlib.dll.sources @@ -870,7 +870,6 @@ System.Threading.Tasks/DecoupledTask.cs ../Mono.Parallel/Mono.Threading/AtomicBoolean.cs ReferenceSources/__ConsoleStream.cs -ReferenceSources/AppContextSwitches.cs ReferenceSources/Array.cs ReferenceSources/BCLDebug.cs ReferenceSources/CalendarData.cs @@ -1053,6 +1052,8 @@ ReferenceSources/Type.cs ../referencesource/mscorlib/system/version.cs ../referencesource/mscorlib/system/AppContext/AppContext.cs +../referencesource/mscorlib/system/AppContext/AppContextSwitches.cs +ReferenceSources/AppContextDefaultValues.cs ../referencesource/mscorlib/system/collections/arraylist.cs ../referencesource/mscorlib/system/collections/bitarray.cs diff --git a/mcs/class/lib/monolite/1050000000/mscorlib.dll.REMOVED.git-id b/mcs/class/lib/monolite/1050000000/mscorlib.dll.REMOVED.git-id index dabd8534d8..3cd99304d8 100644 --- a/mcs/class/lib/monolite/1050000000/mscorlib.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/1050000000/mscorlib.dll.REMOVED.git-id @@ -1 +1 @@ -7994e5dac7692b46aba8982a568232486c9ab689 \ No newline at end of file +320d4a5e541cb9f48bd256bfb8f3f98ddbcbc1d6 \ No newline at end of file diff --git a/mcs/class/referencesource/mscorlib/system/AppContext/AppContext.cs b/mcs/class/referencesource/mscorlib/system/AppContext/AppContext.cs index 48b508d50d..e192edb7da 100644 --- a/mcs/class/referencesource/mscorlib/system/AppContext/AppContext.cs +++ b/mcs/class/referencesource/mscorlib/system/AppContext/AppContext.cs @@ -49,13 +49,13 @@ namespace System #endif #region Switch APIs -#if !MONO + static AppContext() { // populate the AppContext with the default set of values AppContextDefaultValues.PopulateDefaultValues(); } -#endif + /// /// Try to get the value of the switch. /// @@ -102,7 +102,6 @@ namespace System { return true; } -#if !MONO // 3. The switch has a valid value, but we need to check for overrides. // Regardless of whether or not the switch has an override, we need to update the value to reflect // the fact that we checked for overrides. @@ -112,7 +111,6 @@ namespace System // we found an override! isEnabled = overrideValue; } -#endif // Update the switch in the dictionary to mark it as 'checked for override' s_switchMap[switchName] = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue) | SwitchValueState.HasLookedForOverride; @@ -132,7 +130,6 @@ namespace System // In this case, we want to capture the fact that we looked for a value and found nothing by adding // an entry in the dictionary with the 'sentinel' value of 'SwitchValueState.UnknownValue'. // Example: This will prevent us from trying to find overrides for values that we don't have in the dictionary -#if !MONO // 1. The value has an override specified. bool overrideValue; if (AppContextDefaultValues.TryGetSwitchOverride(switchName, out overrideValue)) @@ -145,7 +142,6 @@ namespace System return true; } -#endif // 2. The value does not have an override. s_switchMap[switchName] = SwitchValueState.UnknownValue; } diff --git a/mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs b/mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs index 72eb1cccb1..cc4ec0e2d0 100644 --- a/mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs +++ b/mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs @@ -11,6 +11,11 @@ namespace System internal static class AppContextSwitches { +#if MOBILE + public static readonly bool ThrowExceptionIfDisposedCancellationTokenSource = false; + public static readonly bool SetActorAsReferenceWhenCopyingClaimsIdentity = false; + public static readonly bool NoAsyncCurrentCulture = false; +#else private static int _noAsyncCurrentCulture; public static bool NoAsyncCurrentCulture { @@ -120,5 +125,6 @@ namespace System switchValue = isSwitchEnabled ? 1 /*true*/ : -1 /*false*/; return isSwitchEnabled; } +#endif } } diff --git a/mcs/tools/cil-strip/AssemblyStripper.cs b/mcs/tools/cil-strip/AssemblyStripper.cs index 3e5b0b9254..0ad4bfcd69 100644 --- a/mcs/tools/cil-strip/AssemblyStripper.cs +++ b/mcs/tools/cil-strip/AssemblyStripper.cs @@ -147,6 +147,8 @@ namespace Mono.CilStripper { for (int i = 0; i < methodTable.Rows.Count; i++) { MethodRow methodRow = methodTable[i]; + methodRow.ImplFlags |= MethodImplAttributes.NoInlining; + MetadataToken methodToken = MetadataToken.FromMetadataRow (TokenType.Method, i); MethodDefinition method = (MethodDefinition) assembly.MainModule.LookupByToken (methodToken); diff --git a/mono/metadata/sre-internals.h b/mono/metadata/sre-internals.h index 3d7f3b7108..e179c76303 100644 --- a/mono/metadata/sre-internals.h +++ b/mono/metadata/sre-internals.h @@ -137,5 +137,8 @@ mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflecti guint32 mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error); +guint32 +mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec); + #endif /* __MONO_METADATA_SRE_INTERNALS_H__ */ diff --git a/mono/metadata/sre-save.c.REMOVED.git-id b/mono/metadata/sre-save.c.REMOVED.git-id index 3688d3ef31..3bf9a894d9 100644 --- a/mono/metadata/sre-save.c.REMOVED.git-id +++ b/mono/metadata/sre-save.c.REMOVED.git-id @@ -1 +1 @@ -20d9e47a4a3945453e3fdd0d96653f273a3722c2 \ No newline at end of file +f430028e861594daad59c28c417cdc6ecc937005 \ No newline at end of file diff --git a/mono/metadata/sre.c.REMOVED.git-id b/mono/metadata/sre.c.REMOVED.git-id index f5164fbbd7..2ca615c9c8 100644 --- a/mono/metadata/sre.c.REMOVED.git-id +++ b/mono/metadata/sre.c.REMOVED.git-id @@ -1 +1 @@ -276dd704cf9028688997bee53c1446b26dacbe41 \ No newline at end of file +7811483ae97cbb92b3dd2d062ba511dee9a0248c \ No newline at end of file diff --git a/mono/mini/Makefile.am b/mono/mini/Makefile.am index dafb703520..6aea0961c1 100644 --- a/mono/mini/Makefile.am +++ b/mono/mini/Makefile.am @@ -878,7 +878,7 @@ EXTRA_DIST = TestDriver.cs \ Makefile.am.in version.h: Makefile - echo "#define FULL_VERSION \"Stable 5.0.0.78/ba317ed\"" > version.h + echo "#define FULL_VERSION \"Stable 5.0.0.94/1d0445b\"" > version.h # Utility target for patching libtool to speed up linking patch-libtool: diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index dafb703520..6aea0961c1 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -878,7 +878,7 @@ EXTRA_DIST = TestDriver.cs \ Makefile.am.in version.h: Makefile - echo "#define FULL_VERSION \"Stable 5.0.0.78/ba317ed\"" > version.h + echo "#define FULL_VERSION \"Stable 5.0.0.94/1d0445b\"" > version.h # Utility target for patching libtool to speed up linking patch-libtool: diff --git a/mono/mini/Makefile.in.REMOVED.git-id b/mono/mini/Makefile.in.REMOVED.git-id index 719fe64f8f..319ebd9dc7 100644 --- a/mono/mini/Makefile.in.REMOVED.git-id +++ b/mono/mini/Makefile.in.REMOVED.git-id @@ -1 +1 @@ -43f05751d1510288b0377dca9681ef0ce35220e4 \ No newline at end of file +c56a1bc4df9e6127aab55d56ef2a1e6f03caccc9 \ No newline at end of file diff --git a/mono/mini/jit-icalls.c b/mono/mini/jit-icalls.c index 7130aeab31..b310555b38 100644 --- a/mono/mini/jit-icalls.c +++ b/mono/mini/jit-icalls.c @@ -887,11 +887,16 @@ mono_class_static_field_address (MonoDomain *domain, MonoClassField *field) //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset); - if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field))) + if (field->offset == -1) { + /* Special static */ + g_assert (domain->special_static_fields); + mono_domain_lock (domain); + addr = g_hash_table_lookup (domain->special_static_fields, field); + mono_domain_unlock (domain); addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr)); - else + } else { addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset; - + } return addr; } diff --git a/mono/mini/mini-arm.c.REMOVED.git-id b/mono/mini/mini-arm.c.REMOVED.git-id index e0f307bb5a..c5bf57714d 100644 --- a/mono/mini/mini-arm.c.REMOVED.git-id +++ b/mono/mini/mini-arm.c.REMOVED.git-id @@ -1 +1 @@ -58964502b7fcbb47b0a892f7fc74319537b605ff \ No newline at end of file +341b4b589b8237f2ce8bae1faf0d58cf3c93ae3c \ No newline at end of file diff --git a/mono/mini/version.h b/mono/mini/version.h index 88aaa95661..23f9f65c4a 100644 --- a/mono/mini/version.h +++ b/mono/mini/version.h @@ -1 +1 @@ -#define FULL_VERSION "Stable 5.0.0.78/ba317ed" +#define FULL_VERSION "Stable 5.0.0.94/1d0445b" diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index c752104156..1d7db785ea 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -320,6 +320,7 @@ BASE_TEST_CS_SRC= \ generic-static-methods.2.cs \ generic-null-call.2.cs \ generic-special.2.cs \ + generic-special2.2.cs \ generic-exceptions.2.cs \ generic-virtual2.2.cs \ generic-valuetype-interface.2.cs \ @@ -1645,6 +1646,7 @@ GSHARED_TESTS_SRC = \ generic-tailcall2.2.cs \ generic-array-exc.2.cs \ generic-special.2.cs \ + generic-special2.2.cs \ generic-exceptions.2.cs \ generic-delegate2.2.cs \ generic-virtual2.2.cs \ diff --git a/mono/tests/Makefile.in b/mono/tests/Makefile.in index b6dcdb1433..3d26684e25 100644 --- a/mono/tests/Makefile.in +++ b/mono/tests/Makefile.in @@ -820,6 +820,7 @@ BASE_TEST_CS_SRC = \ generic-static-methods.2.cs \ generic-null-call.2.cs \ generic-special.2.cs \ + generic-special2.2.cs \ generic-exceptions.2.cs \ generic-virtual2.2.cs \ generic-valuetype-interface.2.cs \ @@ -1358,6 +1359,7 @@ GSHARED_TESTS_SRC = \ generic-tailcall2.2.cs \ generic-array-exc.2.cs \ generic-special.2.cs \ + generic-special2.2.cs \ generic-exceptions.2.cs \ generic-delegate2.2.cs \ generic-virtual2.2.cs \ diff --git a/mono/tests/generic-special2.2.cs b/mono/tests/generic-special2.2.cs new file mode 100644 index 0000000000..625d873659 --- /dev/null +++ b/mono/tests/generic-special2.2.cs @@ -0,0 +1,54 @@ +using System; +using System.Reflection; +using System.IO; +using System.Collections.Generic; +using System.Threading; + +internal class GenericType { + [ThreadStatic] + internal static object static_var; + + public static void AccessStaticVar () + { + if (static_var != null && static_var.GetType () != typeof (List)) + throw new Exception ("Corrupted static var"); + GenericType.static_var = new List (); + } +} + +public static class Program { + private static bool stress; + + /* Create a lot of static vars */ + private static void CreateVTables () + { + Type[] nullArgs = new Type[0]; + Assembly ass = Assembly.GetAssembly (typeof (int)); + foreach (Type type in ass.GetTypes ()) { + try { + Type inst = typeof (GenericType<>).MakeGenericType (type); + Activator.CreateInstance (inst); + } catch { + } + } + } + + private static void StressStaticFieldAddr () + { + while (stress) { + GenericType.AccessStaticVar (); + } + } + + public static void Main (string[] args) + { + Thread thread = new Thread (StressStaticFieldAddr); + + stress = true; + thread.Start (); + CreateVTables (); + stress = false; + + thread.Join (); + } +} diff --git a/po/mcs/de.gmo b/po/mcs/de.gmo index 65482d4540be4e7818d4fe471451728aaad81427..f7914927725a416d927cf003ecf8c5ee13a06345 100644 GIT binary patch delta 23 ecmbQIHBW29BQ7peT?1nULo+Kw)6H+VjJN1I>KDRKa0RtG)+ delta 23 ecmX?Ef3kjqwj!5_u92C7fu)tH$!1f\n" "Language-Team: LANGUAGE \n" diff --git a/po/mcs/pt_BR.gmo b/po/mcs/pt_BR.gmo index 41bd75977c750b83d427759466be3f18d7496345..a30543c61a92e165496682e019b608ca1adb55e8 100644 GIT binary patch delta 25 hcmX@Po8{zgmJQ<5xJ-2oj1>&ctPD*zD^6R{4gh;)2>k#6 delta 25 hcmX@Po8{zgmJQ<5xJ-17%oGePtxQceD^6R{4gh<*2?hWF diff --git a/po/mcs/pt_BR.po.REMOVED.git-id b/po/mcs/pt_BR.po.REMOVED.git-id index df99df7c1c..395f8b364e 100644 --- a/po/mcs/pt_BR.po.REMOVED.git-id +++ b/po/mcs/pt_BR.po.REMOVED.git-id @@ -1 +1 @@ -255e57977118fef3187ede3a0ff62dd3a09ca217 \ No newline at end of file +f08602364bd40e296101f38b07540e1c9b41c7a2 \ No newline at end of file