[merp] Use macOS version not Darwin version in MERP reports (mono/mono#17130)
authorKyle White <kdubau@gmail.com>
Wed, 2 Oct 2019 02:01:35 +0000 (22:01 -0400)
committerAleksey Kliger (λgeek) <alklig@microsoft.com>
Wed, 2 Oct 2019 02:01:35 +0000 (22:01 -0400)
* Use macOS version not Darwin version in MERP

Fixes mono/mono#17004

* Update mono-merp.c

Ensure this is only for Mac

* Don't allocate in macos_version_string

Use a static buffer.

Also some formatting fixes.

Commit migrated from https://github.com/mono/mono/commit/0004522028ad30bfb7299a6e50cbab98a63ffeaf

src/mono/mono/utils/mono-merp.c

index c8ba887..3438a23 100644 (file)
@@ -42,7 +42,7 @@
 #include <utils/mono-threads-debug.h>
 
 static const char *
-os_version_string (void)
+kernel_version_string (void)
 {
 #ifdef HAVE_SYS_UTSNAME_H
        static struct utsname name;
@@ -64,6 +64,61 @@ os_version_string (void)
        return "";
 }
 
+static gboolean
+starts_with (const char *pre, size_t pre_sz, const char *str)
+{
+    return strncmp (pre, str, pre_sz) == 0;
+}
+
+static const char *
+macos_version_string (void)
+{
+       /* Can't allocate in here, could be called from a signal handler in a
+        * crashed process.
+        */
+       static const char *version_string;
+       static char buf[256];
+       static const size_t buf_size = sizeof (buf);
+
+       if (version_string)
+               return version_string;
+
+       /* macOS 10.13.6 or later */
+       if (!version_string) {
+               size_t size = 0;
+               if (sysctlbyname ("kern.osproductversion", NULL, &size, NULL, 0) < 0 || size >= buf_size) {
+                       /* if we couldn't get the size or if it needs more space that we have in buf, leave it empty */
+                       version_string = "";
+                       return version_string;
+               }
+
+               if (sysctlbyname ("kern.osproductversion", (char*)buf, &size, NULL, 0) >= 0)
+                       version_string = &buf[0];
+       }
+       /* macOS 10.13.5 or older */
+       if (!version_string) {
+               const char *kv_string = kernel_version_string ();
+               if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("17"), kv_string))
+                       version_string = "10.13"; // High Sierra
+               else if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("16"), kv_string))
+                       version_string = "10.12"; // Sierra
+               else if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("15"), kv_string))
+                       version_string = "10.11"; // El Capitan
+               else if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("14"), kv_string))
+                       version_string = "10.10"; // Yosemite
+               else if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("13"), kv_string))
+                       version_string = "10.9"; // Mavericks
+               else if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("12"), kv_string))
+                       version_string = "10.8"; // Mountain Lion
+               else if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("11"), kv_string))
+                       version_string = "10.7"; // Lion
+       }
+       if (!version_string)
+               version_string = "";
+
+       return version_string;
+}
+
 // To get the path of the running process
 #include <libproc.h>
 
@@ -352,8 +407,11 @@ mono_init_merp (const intptr_t crashed_pid, const char *signal, MonoStackHash *h
        merp->moduleOffset = 0;
 
        merp->uiLidArg = MONO_LOCALE_INVARIANT;
-
-       merp->osVersion = os_version_string ();
+#if defined (TARGET_OSX)
+       merp->osVersion = macos_version_string ();
+#else
+       merp->osVersion = kernel_version_string ();
+#endif
 
        // FIXME: THis is apple-only for now
        merp->systemManufacturer = "apple";