# Extended 3.11 — src/utilsMac.mm: strcpy of NSBundle path into PATH_MAX vmPath

Bug ref      : pharo.md §3.11
Severity     : HIGH (corrupts adjacent globals when app is in a deep directory path)
File         : src/utilsMac.mm
Lines (HEAD) : 8-11 (`fillApplicationDirectory`)

## Problem

```objc++
void fillApplicationDirectory(char* vmPath){
    NSURL *appFolder = [[[NSBundle mainBundle] bundleURL] URLByDeletingLastPathComponent];
    strcpy(vmPath, [appFolder fileSystemRepresentation]);
}
```

`[appFolder fileSystemRepresentation]` returns a path of arbitrary
length. `strcpy` writes without checking against `vmPath`'s size.
An app installed in a deeply nested directory (or behind a long
symlink chain) corrupts the adjacent globals.

The caller (`setVMPath`) passes its `vmPath` global which is
sized `PATH_MAX`.

## Fix

```diff
--- a/src/osx/utilsMac.mm
+++ b/src/osx/utilsMac.mm
@@ -1,11 +1,18 @@
 #import <Foundation/Foundation.h>
 #import <Cocoa/Cocoa.h>
+#import <limits.h>
+#import <string.h>
 
 extern "C" {    
     void fillApplicationDirectory(char* vmPath);
+    extern void logWarn(const char *, ...);
 }
 
 void fillApplicationDirectory(char* vmPath){
     NSURL *appFolder = [[[NSBundle mainBundle] bundleURL] URLByDeletingLastPathComponent];
-    strcpy(vmPath, [appFolder fileSystemRepresentation]);
+    const char *rep = [appFolder fileSystemRepresentation];
+    int n = snprintf(vmPath, PATH_MAX, "%s", rep);
+    if (n < 0 || n >= PATH_MAX) {
+        logWarn("fillApplicationDirectory: app path truncated to %d bytes", PATH_MAX - 1);
+    }
 }

```

## Test plan

- Install a test build into a deeply nested directory (e.g.
  `/Users/test/a/b/c/d/e/f/g/.../Pharo.app`) such that the bundle
  path exceeds PATH_MAX. Before: adjacent globals corrupted. After:
  warning logged.
- Normal install path: unchanged.

## Risk notes

- The signature passes `vmPath` without an explicit size; the
  caller in `setVMPath` always passes the `PATH_MAX`-sized global,
  so hard-coding PATH_MAX here matches the contract. If a future
  caller passes a smaller buffer, this still truncates safely (the
  output buffer is capped to PATH_MAX, but the caller is the only
  one passing it).
