From 249ee0686bf87f33acf2efde76f3645ef06bb886 Mon Sep 17 00:00:00 2001 From: Andi McClure Date: Tue, 1 Dec 2015 18:03:21 -0500 Subject: [PATCH] Fail cleanly when MonoPosixHelper.dll version is wrong (bug #35655) Add version keys to the C and C# versions of Mono.Posix and add static constructors which fail early if the version keys differ. --- mcs/class/Mono.Posix/Mono.Unix.Native/Stdlib.cs | 36 +++++++++++++++++++++++++ mcs/class/Mono.Posix/Mono.Unix/UnixSignal.cs | 5 ++++ support/map.h | 1 + support/stdlib.c | 7 +++++ 4 files changed, 49 insertions(+) diff --git a/mcs/class/Mono.Posix/Mono.Unix.Native/Stdlib.cs b/mcs/class/Mono.Posix/Mono.Unix.Native/Stdlib.cs index c2e50b8d259..e4c34cba317 100644 --- a/mcs/class/Mono.Posix/Mono.Unix.Native/Stdlib.cs +++ b/mcs/class/Mono.Posix/Mono.Unix.Native/Stdlib.cs @@ -381,6 +381,42 @@ namespace Mono.Unix.Native { internal const string LIBC = "msvcrt"; internal const string MPH = "MonoPosixHelper"; + // It is possible for Mono.Posix and MonoPosixHelper to get out of sync, + // for example if NuGet does something weird. To mitigate this, anyone + // editing Mono.Posix needs to observe two rules: + // 1. When introducing C-interface changes to MonoPosixHelper, update + // the version strings in VersionCheck below and also + // Mono_Unix_VersionString in the C sources. + // 2. Any class which performs a DllImport on Stdlib.MPH needs to call + // Stdlib.VersionCheck in its static constructor. + + [DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl, + EntryPoint="Mono_Unix_VersionString")] + private static extern IntPtr VersionStringPtr (); + private static bool versionCheckPerformed = false; + internal static void VersionCheck () + { + if (versionCheckPerformed) + return; + + // This string is arbitrary; it matters only that it is unique. + string assemblyVersion = "MonoProject-2015-12-1"; + string nativeVersion = Marshal.PtrToStringAnsi (VersionStringPtr ()); + if (assemblyVersion != nativeVersion) + { + throw new Exception ("Mono.Posix assembly loaded with a different version (\"" + + assemblyVersion + "\") than MonoPosixHelper (\"" + nativeVersion + + "\"). You may need to reinstall Mono.Posix."); + } + + versionCheckPerformed = true; + } + + static Stdlib () + { + VersionCheck (); + } + internal Stdlib () {} #region Declarations diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixSignal.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixSignal.cs index 883e044aea1..fe1f8beba8e 100644 --- a/mcs/class/Mono.Posix/Mono.Unix/UnixSignal.cs +++ b/mcs/class/Mono.Posix/Mono.Unix/UnixSignal.cs @@ -39,6 +39,11 @@ namespace Mono.Unix { private int signum; private IntPtr signal_info; + static UnixSignal () + { + Stdlib.VersionCheck (); + } + public UnixSignal (Signum signum) { this.signum = NativeConvert.FromSignum (signum); diff --git a/support/map.h b/support/map.h index 34cdb68ab4d..b121f032be7 100644 --- a/support/map.h +++ b/support/map.h @@ -2049,6 +2049,7 @@ int Mono_Posix_Stdlib_clearerr (void* stream); void* Mono_Posix_Stdlib_CreateFilePosition (void); int Mono_Posix_Stdlib_DumpFilePosition (char* buf, void* handle, int len); int Mono_Posix_Stdlib_EOF (void); +const char* Mono_Unix_VersionString (void); int Mono_Posix_Stdlib_EXIT_FAILURE (void); int Mono_Posix_Stdlib_EXIT_SUCCESS (void); int Mono_Posix_Stdlib_fgetpos (void* stream, void* pos); diff --git a/support/stdlib.c b/support/stdlib.c index 56df107016f..523ae924828 100644 --- a/support/stdlib.c +++ b/support/stdlib.c @@ -14,6 +14,13 @@ G_BEGIN_DECLS +// See Stdlib.cs +const char * +Mono_Unix_VersionString () +{ + return "MonoProject-2015-12-1"; +} + gint32 Mono_Posix_Stdlib_EXIT_FAILURE (void) { -- 2.11.4.GIT