<pre style='margin:0'>
Christopher Nielsen (mascguy) pushed a commit to branch master
in repository macports-legacy-support.

</pre>
<p><a href="https://github.com/macports/macports-legacy-support/commit/02422662607d29e1769ee898e483a4e290a177d3">https://github.com/macports/macports-legacy-support/commit/02422662607d29e1769ee898e483a4e290a177d3</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 02422662607d29e1769ee898e483a4e290a177d3
</span>Author: Fred Wright <fw@fwright.net>
AuthorDate: Wed Jul 2 11:17:31 2025 -0700

<span style='display:block; white-space:pre;color:#404040;'>    util: New module for common utilities.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Initially this just contains the access checker from fcntl.c.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    The checker is now improved to avoid an extra call in the single-page
</span><span style='display:block; white-space:pre;color:#404040;'>    case, as well as handling multi-page ranges correctly.  It also now
</span><span style='display:block; white-space:pre;color:#404040;'>    accepts an optional known-valid address, and avoids the full check
</span><span style='display:block; white-space:pre;color:#404040;'>    if the target range lies within the known-valid page.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    TESTED:
</span><span style='display:block; white-space:pre;color:#404040;'>    Tests pass on all platforms.
</span>---
 src/fcntl.c |  41 +++---------------------
 src/util.c  | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/util.h  |  31 ++++++++++++++++++
 3 files changed, 138 insertions(+), 37 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/fcntl.c b/src/fcntl.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 50a34da..8cd3b5c 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/fcntl.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/fcntl.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -42,48 +42,15 @@
</span> #include <fcntl.h>
 #include <pthread.h>
 #include <stdarg.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stddef.h>
</span> #include <stdint.h>
 #include <stdlib.h>
 #include <unistd.h>
 
 #include <sys/param.h>
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <mach/mach.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <mach/mach_vm.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span> #include "compiler.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-int
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-check_access(void *adr, mach_vm_size_t size, vm_prot_t access)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  vm_map_t task = mach_task_self();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  mach_vm_address_t address;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  mach_vm_size_t msize;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  vm_region_basic_info_data_64_t info;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  mach_msg_type_number_t count;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  mach_port_t object_name;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  kern_return_t ret;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  address = (mach_vm_address_t) adr;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  msize = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  count = VM_REGION_BASIC_INFO_COUNT_64;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  ret = mach_vm_region(task, &address, &msize, VM_REGION_BASIC_INFO_64,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                       (vm_region_info_t)&info, &count, &object_name);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (ret != KERN_SUCCESS) return -1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  if ((mach_vm_address_t) adr < address) return -1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (access & ~info.protection) return -1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  address = (mach_vm_address_t) ((uint8_t *) adr + size -1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  msize = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  count = VM_REGION_BASIC_INFO_COUNT_64;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  ret = mach_vm_region(task, &address, &msize, VM_REGION_BASIC_INFO_64,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                       (vm_region_info_t)&info, &count, &object_name);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (ret != KERN_SUCCESS) return -1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  if ((mach_vm_address_t) adr < address) return -1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (access & ~info.protection) return -1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  return 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include "util.h"
</span> 
 static pthread_mutex_t path_lock = PTHREAD_MUTEX_INITIALIZER;
 static char pathbuf[MAXPATHLEN];
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -171,8 +138,8 @@ fcntl(int fildes, int cmd, ...)
</span>   /* If not a 64-bit issue, just punt (probably genuine bad adr). */
   if ((uint64_t) arg.ptr < (1ULL << 32)) return -1;
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  /* Now do a correct access check on the result buffer, & fail if bad */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (check_access(arg.ptr, MAXPATHLEN, VM_PROT_WRITE)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* Now do a correct access check on the result buffer, and fail if bad */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (__mpls_check_access(arg.ptr, MAXPATHLEN, VM_PROT_WRITE, NULL)) {
</span>     errno = EFAULT;
     return -1;
   }
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/util.c b/src/util.c
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..3d8adef
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/util.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,103 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2025 Frederick H. G. Wright II <fw@fwright.net>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Permission to use, copy, modify, and distribute this software for any
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * purpose with or without fee is hereby granted, provided that the above
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * copyright notice and this permission notice appear in all copies.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* This (conditionally) contains miscellaneous global utility features. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include "util.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if __MPLS_NEED_CHECK_ACCESS__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdint.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <unistd.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <mach/mach.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <mach/mach_vm.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include "compiler.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* ptr->int casts require matching sizes */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#ifndef __LP64__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+typedef uint32_t adrint_t;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+typedef uint64_t adrint_t;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Check a given address and size for validity and needed access.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Unfortunately there's no straightforward call for this, so it has
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * to resort to checking for a compatible memory region, and then
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * iterating as needed for any additional range.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * If the okadr arg is not NULL, then it represents a known valid address.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * If the range to be checked lies within the same page, we can skip the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OS validation.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+__mpls_check_access(void *adr, mach_vm_size_t size, vm_prot_t access,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    void *okadr)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  vm_map_t task = mach_task_self();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  mach_vm_address_t address;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  mach_vm_size_t msize;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  vm_region_basic_info_data_64_t info;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  mach_msg_type_number_t count;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  mach_port_t object_name;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  kern_return_t ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  adrint_t start_adr = (adrint_t) adr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  adrint_t end_adr = start_adr + size;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  adrint_t okpage;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  static adrint_t pagemask = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (okadr) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (MPLS_SLOWPATH(!pagemask)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      pagemask = getpagesize();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      if (pagemask) --pagemask;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    okpage = ((adrint_t) okadr) & ~pagemask;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((start_adr & ~pagemask) == okpage
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        && ((end_adr - 1) & ~pagemask) == okpage) return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  address = start_adr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  msize = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  count = VM_REGION_BASIC_INFO_COUNT_64;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  ret = mach_vm_region(task, &address, &msize, VM_REGION_BASIC_INFO_64,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                       (vm_region_info_t)&info, &count, &object_name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (ret != KERN_SUCCESS) return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   * If the first valid region on or after our address is later, then
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   * our address is invalid.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (start_adr < address) return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (access & ~info.protection) return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* Verify that we have contiguous valid regions covering our range. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  while (end_adr > (address += msize)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    msize = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    count = VM_REGION_BASIC_INFO_COUNT_64;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ret = mach_vm_region(task, &address, &msize, VM_REGION_BASIC_INFO_64,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                         (vm_region_info_t)&info, &count, &object_name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (ret != KERN_SUCCESS) return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (end_adr <= address) return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (access & ~info.protection) return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __MPLS_NEED_CHECK_ACCESS__ */
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/util.h b/src/util.h
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..347e761
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/util.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,31 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2025 Frederick H. G. Wright II <fw@fwright.net>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Permission to use, copy, modify, and distribute this software for any
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * purpose with or without fee is hereby granted, provided that the above
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * copyright notice and this permission notice appear in all copies.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* This (conditionally) contains miscellaneous global utility features. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* MP support header */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include "MacportsLegacySupport.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define __MPLS_NEED_CHECK_ACCESS__ __MPLS_LIB_FIX_TIGER_PPC64__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if __MPLS_NEED_CHECK_ACCESS__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <mach/mach_vm.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int __mpls_check_access(void *adr, mach_vm_size_t size, vm_prot_t access,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        void *okadr);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __MPLS_NEED_CHECK_ACCESS__ */
</span></pre><pre style='margin:0'>

</pre>