Prevent Mono.Posix from using multiple C runtimes on Windows
authorNiklas Therning <niklas@therning.org>
Tue, 15 Nov 2016 15:22:33 +0000 (16:22 +0100)
committerNiklas Therning <niklas@therning.org>
Wed, 16 Nov 2016 08:14:25 +0000 (09:14 +0100)
Since libMonoPosixHelper.dll is linked against ucrtbase.dll the C runtime
wrapper functions in it will call into ucrtbase.dll. Some pinvokes in
Mono.Unix.Native.Stdlib, however, bind directly to C runtime functions in
msvcrt. This is problematic if a resource (heap memory, file pointer, etc) is
allocated using one C runtime and then operated upon using funcitons form the
other C runtime. E.g., Stdlib.malloc() calls into a wrapper in
libMonoPosixHelper so it will use the ucrtbase heap while Stdlib.free() calls
directly into msvcrt's free() which will abort the process since it's called
with a pointer in an unknown heap.

This commit adds libMonoPosixHelper wrappers for all memory and file related
functions in Stdlib to ensure that all such functions use the same C runtime.

Some of the Mono.Posix tests still fail but at least the test suite doesn't
crash after this change. The test failures will be addressed in a future PR.

mcs/class/Mono.Posix/Mono.Unix.Native/Stdlib.cs
mcs/class/Mono.Posix/Mono.Unix/StdioFileStream.cs
msvc/monoposixhelper.def
support/map.h
support/stdio.c
support/stdlib.c

index e4c34cba317f28629d885cb370e536fc3cabb29f..86cdb7126fe305d62a5283fc7bed694d3ec264b2 100644 (file)
@@ -675,7 +675,8 @@ namespace Mono.Unix.Native {
                                [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
                                string newpath);
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               SetLastError=true, EntryPoint="Mono_Posix_Stdlib_tmpfile")]
                public static extern IntPtr tmpfile ();
 
                private static object tmpnam_lock = new object ();
@@ -704,18 +705,22 @@ namespace Mono.Unix.Native {
                        }
                }
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fclose")]
                public static extern int fclose (IntPtr stream);
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fflush")]
                public static extern int fflush (IntPtr stream);
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fopen")]
                public static extern IntPtr fopen (
                                [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
                                string path, string mode);
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               SetLastError=true, EntryPoint="Mono_Posix_Stdlib_freopen")]
                public static extern IntPtr freopen (
                                [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
                                string path, string mode, IntPtr stream);
@@ -741,8 +746,8 @@ namespace Mono.Unix.Native {
                        return setvbuf (stream, (IntPtr) buf, mode, size);
                }
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
-                               EntryPoint="fprintf")]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               EntryPoint="Mono_Posix_Stdlib_fprintf")]
                private static extern int sys_fprintf (IntPtr stream, string format, string message);
 
                public static int fprintf (IntPtr stream, string message)
@@ -846,11 +851,12 @@ namespace Mono.Unix.Native {
                 *    vsscanf(3)
                 */
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fgetc")]
                public static extern int fgetc (IntPtr stream);
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
-                               SetLastError=true, EntryPoint="fgets")]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fgets")]
                private static extern IntPtr sys_fgets (StringBuilder sb, int size, IntPtr stream);
 
                public static StringBuilder fgets (StringBuilder sb, int size, IntPtr stream)
@@ -866,22 +872,28 @@ namespace Mono.Unix.Native {
                        return fgets (sb, sb.Capacity, stream);
                }
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fputc")]
                public static extern int fputc (int c, IntPtr stream);
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fputs")]
                public static extern int fputs (string s, IntPtr stream);
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
-               public static extern int getc (IntPtr stream);
+               public static int getc (IntPtr stream)
+               {
+                       return fgetc (stream);
+               }
 
                [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
                public static extern int getchar ();
 
                /* SKIP: gets(3) */
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
-               public static extern int putc (int c, IntPtr stream);
+               public static int putc (int c, IntPtr stream)
+               {
+                       return fputc (c, stream);
+               }
 
                [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
                public static extern int putchar (int c);
@@ -889,7 +901,8 @@ namespace Mono.Unix.Native {
                [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
                public static extern int puts (string s);
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               SetLastError=true, EntryPoint="Mono_Posix_Stdlib_ungetc")]
                public static extern int ungetc (int c, IntPtr stream);
 
                [CLSCompliant (false)]
@@ -993,10 +1006,12 @@ namespace Mono.Unix.Native {
                                SetLastError=true, EntryPoint="Mono_Posix_Stdlib_clearerr")]
                public static extern int clearerr (IntPtr stream);
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               SetLastError=true, EntryPoint="Mono_Posix_Stdlib_feof")]
                public static extern int feof (IntPtr stream);
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               SetLastError=true, EntryPoint="Mono_Posix_Stdlib_ferror")]
                public static extern int ferror (IntPtr stream);
 
                [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, 
@@ -1050,7 +1065,8 @@ namespace Mono.Unix.Native {
                                SetLastError=true, EntryPoint="Mono_Posix_Stdlib_calloc")]
                public static extern IntPtr calloc (ulong nmemb, ulong size);
 
-               [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               EntryPoint="Mono_Posix_Stdlib_free")]
                public static extern void free (IntPtr ptr);
 
                // malloc(3):
index 7eed08157b0748ff075ad7bcc362aa8709d4b74a..1d0ef97e9f7e5aeb081304271e8211a586084abe 100644 (file)
@@ -60,35 +60,43 @@ namespace Mono.Unix {
 
                public StdioFileStream (string path)
                {
+                       if (path == null)
+                               throw new ArgumentNullException ("path");
                        InitStream (Fopen (path, "rb"), true);
                }
 
                public StdioFileStream (string path, string mode)
                {
+                       if (path == null)
+                               throw new ArgumentNullException ("path");
                        InitStream (Fopen (path, mode), true);
                }
 
                public StdioFileStream (string path, FileMode mode)
                {
+                       if (path == null)
+                               throw new ArgumentNullException ("path");
                        InitStream (Fopen (path, ToFopenMode (path, mode)), true);
                }
 
                public StdioFileStream (string path, FileAccess access)
                {
+                       if (path == null)
+                               throw new ArgumentNullException ("path");
                        InitStream (Fopen (path, ToFopenMode (path, access)), true);
                        InitCanReadWrite (access);
                }
 
                public StdioFileStream (string path, FileMode mode, FileAccess access)
                {
+                       if (path == null)
+                               throw new ArgumentNullException ("path");
                        InitStream (Fopen (path, ToFopenMode (path, mode, access)), true);
                        InitCanReadWrite (access);
                }
 
                private static IntPtr Fopen (string path, string mode)
                {
-                       if (path == null)
-                               throw new ArgumentNullException ("path");
                        if (path.Length == 0)
                                throw new ArgumentException ("path");
                        if (mode == null)
index 027280d5a91a2549a63e5564db72035a76070536..bd2ac9f5a8389707eaae5efecb3c7b31d977f2bc 100644 (file)
@@ -49,8 +49,20 @@ Mono_Posix_Stdlib__IOLBF
 Mono_Posix_Stdlib__IONBF\r
 Mono_Posix_Stdlib_calloc\r
 Mono_Posix_Stdlib_clearerr\r
+Mono_Posix_Stdlib_fclose\r
+Mono_Posix_Stdlib_feof\r
+Mono_Posix_Stdlib_ferror\r
+Mono_Posix_Stdlib_fflush\r
+Mono_Posix_Stdlib_fgetc\r
 Mono_Posix_Stdlib_fgetpos\r
+Mono_Posix_Stdlib_fgets\r
+Mono_Posix_Stdlib_fopen\r
+Mono_Posix_Stdlib_fprintf\r
+Mono_Posix_Stdlib_fputc\r
+Mono_Posix_Stdlib_fputs\r
 Mono_Posix_Stdlib_fread\r
+Mono_Posix_Stdlib_free\r
+Mono_Posix_Stdlib_freopen\r
 Mono_Posix_Stdlib_fseek\r
 Mono_Posix_Stdlib_fsetpos\r
 Mono_Posix_Stdlib_ftell\r
@@ -65,6 +77,8 @@ Mono_Posix_Stdlib_stderr
 Mono_Posix_Stdlib_stdin\r
 Mono_Posix_Stdlib_stdout\r
 Mono_Posix_Stdlib_strlen\r
+Mono_Posix_Stdlib_tmpfile\r
+Mono_Posix_Stdlib_ungetc\r
 Mono_Posix_ToAccessModes\r
 Mono_Posix_ToConfstrName\r
 Mono_Posix_ToDirectoryNotifyFlags\r
index ccd221b106a219d161e744e9e6f42828089f7130..8c6ef5000f2fc22c8dea1fac92404d3e2284ba74 100644 (file)
@@ -2181,10 +2181,24 @@ int Mono_Posix_Stdlib_MB_CUR_MAX (void);
 int Mono_Posix_Stdlib_perror (const char* s, int err);
 int Mono_Posix_Stdlib_RAND_MAX (void);
 void* Mono_Posix_Stdlib_realloc (void* ptr, guint64 size);
+void Mono_Posix_Stdlib_free (void* p);
 int Mono_Posix_Stdlib_rewind (void* stream);
 int Mono_Posix_Stdlib_setbuf (void* stream, void* buf);
 void Mono_Posix_Stdlib_SetLastError (int error);
 int Mono_Posix_Stdlib_setvbuf (void* stream, void* buf, int mode, guint64 size);
+void* Mono_Posix_Stdlib_fopen (char* path, char* mode);
+void* Mono_Posix_Stdlib_freopen (char* path, char* mode, void *stream);
+gint32 Mono_Posix_Stdlib_fprintf (void* stream, char* format, char *message);
+gint32 Mono_Posix_Stdlib_fgetc (void* stream);
+char* Mono_Posix_Stdlib_fgets (char* str, gint32 size, void* stream);
+gint32 Mono_Posix_Stdlib_fputc (gint32 c, void* stream);
+gint32 Mono_Posix_Stdlib_fputs (char* s, void* stream);
+gint32 Mono_Posix_Stdlib_fclose (void* stream);
+gint32 Mono_Posix_Stdlib_fflush (void* stream);
+void* Mono_Posix_Stdlib_tmpfile (void);
+gint32 Mono_Posix_Stdlib_ungetc (gint32 c, void* stream);
+gint32 Mono_Posix_Stdlib_feof (void* stream);
+gint32 Mono_Posix_Stdlib_ferror (void* stream);
 void* Mono_Posix_Stdlib_SIG_DFL (void);
 void* Mono_Posix_Stdlib_SIG_ERR (void);
 void* Mono_Posix_Stdlib_SIG_IGN (void);
index e5b54da47b909f222d3664480c522d34d40ca1f8..b914dfdb1d098ec4d4518fd5b28f13b770200b2c 100644 (file)
@@ -142,6 +142,12 @@ Mono_Posix_Stdlib_TMP_MAX (void)
        return TMP_MAX;
 }
 
+void*
+Mono_Posix_Stdlib_tmpfile (void)
+{
+       return tmpfile ();
+}
+
 gint32
 Mono_Posix_Stdlib_setvbuf (void* stream, void *buf, int mode, mph_size_t size)
 {
@@ -156,6 +162,60 @@ Mono_Posix_Stdlib_setbuf (void* stream, void* buf)
        return 0;
 }
 
+void*
+Mono_Posix_Stdlib_fopen (char* path, char* mode)
+{
+       return fopen (path, mode);
+}
+
+void*
+Mono_Posix_Stdlib_freopen (char* path, char* mode, void *stream)
+{
+       return freopen (path, mode, stream);
+}
+
+gint32
+Mono_Posix_Stdlib_fprintf (void* stream, char* format, char *message)
+{
+       return fprintf (stream, format, message);
+}
+
+gint32
+Mono_Posix_Stdlib_fgetc (void* stream)
+{
+       return fgetc (stream);
+}
+
+char*
+Mono_Posix_Stdlib_fgets (char* str, gint32 size, void* stream)
+{
+       return fgets (str, size, stream);
+}
+
+gint32
+Mono_Posix_Stdlib_fputc (gint32 c, void* stream)
+{
+       return fputc (c, stream);
+}
+
+gint32
+Mono_Posix_Stdlib_fputs (char* s, void* stream)
+{
+       return fputs (s, stream);
+}
+
+gint32
+Mono_Posix_Stdlib_fclose (void* stream)
+{
+       return fclose (stream);
+}
+
+gint32
+Mono_Posix_Stdlib_fflush (void* stream)
+{
+       return fflush (stream);
+}
+
 gint32
 Mono_Posix_Stdlib_fseek (void* stream, gint64 offset, int origin)
 {
@@ -207,6 +267,24 @@ Mono_Posix_Stdlib_clearerr (void* stream)
        return 0;
 }
 
+gint32
+Mono_Posix_Stdlib_ungetc (gint32 c, void* stream)
+{
+       return ungetc (c, stream);
+}
+
+gint32
+Mono_Posix_Stdlib_feof (void* stream)
+{
+       return feof (stream);
+}
+
+gint32
+Mono_Posix_Stdlib_ferror (void* stream)
+{
+       return ferror (stream);
+}
+
 int
 Mono_Posix_Stdlib_perror (const char* s, int err)
 {
index 0c4358a51402d3d7b2b577db88eef64497857af2..077a85e58f56388f1ab9357ccbfbc5f2ba8cdc4f 100644 (file)
@@ -72,6 +72,12 @@ Mono_Posix_Stdlib_realloc (void* ptr, mph_size_t size)
        return realloc (ptr, (size_t) size);
 }
 
+void
+Mono_Posix_Stdlib_free (void* p)
+{
+       free (p);
+}
+
 G_END_DECLS
 
 /*