# Pharo VM — local PR collection (pharo-12)

Generated:   2026-05-13
Source repo: ~/esrc/pharo-vm-12 @ pharo-12 (upstream HEAD 0c6de9df5)
Audits:      ~/always.md (43 always-fire issues), ~/pharo.md (full audit)

These PRs are the pharo-10 collection (~/esrc/PR/) re-targeted at the
pharo-12 branch the upstream developers asked for, plus a few new
defects found while reviewing pharo-12-specific code.

The pharo-10 collection at `~/esrc/PR/` is preserved unchanged.


================================================================
Summary
================================================================

   PR group                                Files    Status
   --------------------------------------  -----    ------
   always/  (always-fire bugs)                37    all apply cleanly
   extended/  (edge-case / medium severity)   53    all apply cleanly
   new/  (pharo-12-only bugs)                  3    all apply cleanly
   fixed-upstream/  (no PR needed)             1    note only

   Total PRs that apply via git apply         93
   Test:                                      cd ~/esrc/pharo-vm-12 && git apply --check <pr>


================================================================
Restructuring between pharo-10 and pharo-12
================================================================

The biggest change against pharo-10 is a directory layout move:

   pharo-10                              →  pharo-12
   --------------------------------------    --------------------------------------
   extracted/vm/src/common/*.c              src/common/*.c
   extracted/vm/src/unix/*.c                src/unix/*.c
   extracted/vm/src/win/*.c                 src/win/*.c
   extracted/plugins/*                      plugins/*
   ffi/src/*                                src/ffi/*
   ffi/include/*                            include/pharovm/ffi/*
   src/debugUnix.c                          src/unix/debugUnix.c
   src/memoryUnix.c                         src/unix/memoryUnix.c
   src/macAlias.c                           src/osx/macAlias.c
   src/utilsMac.mm                          src/osx/utilsMac.mm
   src/fileUtilsWin.c                       plugins/FilePlugin/src/win/fileUtilsWin.c
   src/win32Main.c                          src/win/win32Main.c
   extracted/plugins/FilePlugin/src/osx/*   plugins/FilePlugin/src/unix/*  (osx folded)
   macros.cmake                             cmake/macros.cmake

Of the 91 pharo-10 patches:

  * 83 needed only a path rewrite (the bug code is byte-identical in
    pharo-12; just the file path moved).
  * 7 needed a path rewrite plus context tweaks because the surrounding
    code changed slightly (line-number drift only).
  * 1 (B09 — W^X) is addressed upstream in pharo-12. The mprotect hooks
    are now real, gated on a new `READ_ONLY_CODE_ZONE` cmake option.
    The pharo-10 patch is therefore unnecessary; see
    fixed-upstream/B09 for details.


================================================================
ALWAYS — bugs that fire on every benign run
================================================================

Same set as PR/always/ minus B09 (fixed upstream). All 37 PRs were
re-anchored to pharo-12 paths and verified with `git apply --check`.

  A01-sqNamedPrims-off-by-one.md            HIGH    src/common/sqNamedPrims.c
  A02-callbacks-stack-allocated.md          HIGH    src/ffi/callbacks/callbacks.c
  A03-typesPrimitives-setHandler...md       HIGH    src/ffi/typesPrimitives.c
  A04-threadSafeQueue-read-outside-mutex.md HIGH    src/threadSafeQueue/threadSafeQueue.c
  A05-SocketPlugin-destroy-AIO-UAF.md       HIGH    plugins/SocketPlugin/src/common/SocketPluginImpl.c
  A06-ffi-readString-unpinned-pointer.md    HIGH    src/ffi/utils.c
  A07-callbacks-runner-stack-unlocked.md    MEDIUM  src/ffi/callbacks/callbacks.c
  A08-pathUtilities-null-check-wrong-var.md HIGH    src/pathUtilities.c
  A09-pathUtilities-empty-string...md       MEDIUM  src/pathUtilities.c
  A10-externalPrimitives-module-name-...md  MEDIUM  src/externalPrimitives.c
  A11-debugUnix-async-signal-unsafe...md    HIGH    src/unix/debugUnix.c
  A12-debugUnix-sa-mask-uninitialized.md    MEDIUM  src/unix/debugUnix.c
  A13-debug-strerror_r-uninitialized.md     MEDIUM  src/debug.c
  A14-SocketPlugin-recvUDP-lastError-...md  MEDIUM  plugins/SocketPlugin/src/common/SocketPluginImpl.c
  A15-aioWin-alias-and-unchecked-malloc.md  MEDIUM  src/win/aioWin.c

  B01-04-sqUnixSSL-tls-hardening.md         CRIT    plugins/SqueakSSL/src/unix/sqUnixSSL.c
  B05-07-sqWin32SSL-tls-hardening.md        CRIT    plugins/SqueakSSL/src/win/sqWin32SSL.c
  B06-08-sqMacSSL-tls-hardening.md          CRIT    plugins/SqueakSSL/src/osx/sqMacSSL.c
  B10-debug-error-format-string-footgun.md  LOW     src/debug.c
  B11-ffi-getHandler-type-confusion.md      HIGH    src/ffi/typesPrimitives.c

  B12 .. B28                                build/supply-chain (no path renames):
                                            Jenkinsfile, scripts/runTests.sh,
                                            scripts/installCygwin.ps1, cmake/*,
                                            docker/*, .github/workflows/, CMakeLists.txt


================================================================
EXTENDED — bugs from pharo.md not in always.md
================================================================

All 53 PRs from PR/extended/ apply to pharo-12 after path translation.
No upstream fixes detected for any of these between pharo-10 and
pharo-12.

  2.1-2.2  DSAPrims missing-return                  CRITICAL
  2.3      JPEGReadWriter2 scanline bounds          CRITICAL
  2.4      JPEGReader blockIndex OOB                CRITICAL
  2.7      FFI primitiveCopyFromTo image size       CRITICAL
  3.1      UnixOSProcess realpath buffer            HIGH
  3.2      FileAttributes readlink off-by-one       HIGH
  3.3-3.4  MiscPrim decompress/compress overflow    HIGH
  3.5      BitBlt depth==0 + multiply overflow      HIGH
  3.6      SurfacePlugin width*depth overflow       HIGH
  3.7-3.8  B2D GWBufferTop / nSegments overflow     HIGH
  3.9      externalPrimitives lookupName strcpy     HIGH
  3.10     utils setVMName/Image/Path strcpy        HIGH
  3.11     utilsMac strcpy of NSBundle path         HIGH
  3.12     winDebugWindow newline-doubling          HIGH
  3.13     fileUtilsWin FILE_NAME_INFO NUL          HIGH
  3.14     sqUnixSSL unchecked alloc/realloc        HIGH
  3.15     sqWin32SSL alloca attacker-controlled    HIGH
  3.16     sqWin32SSL encrypt int-overflow          HIGH
  3.17     sqSSL handle negative-index OOB          HIGH
  3.18     sqUnixSSL peerName uninitialized         HIGH
  3.23-3.24 SocketPlugin stat/strncpy non-NUL       HIGH
  3.25     LargeIntegers digitLshift overflow       HIGH
  4.1, 4.4-4.11  crash bugs                         MEDIUM-HIGH
  5.5-5.26  medium-severity hardening               MEDIUM
  6.4      sqUnixSSL X509_check_host strnlen        MEDIUM


================================================================
NEW — bugs introduced by pharo-12-specific code
================================================================

`plugins/NewFilePlugin/` is a new plugin added in pharo-12. Audit
review surfaced these defects:

  N01-NewFilePlugin-Unix-memoryUnmap-inverted.md      HIGH
    UnixFile.c:301-303 — `if(!memoryMapCount) return;` is the inverse
    of what was intended. As written, `munmap` is never called when
    the refcount reaches zero, so every Unix-side mmap leaks. The
    Win32 sibling at Win32File.c:467-479 implements the same flow
    correctly with `if(memoryMapCount > 0) return;`.

  N02-NewFilePlugin-Unix-opendir-non-NUL.md           HIGH
    UnixFile.c:46-47 — `cpath` is computed as a NUL-terminated copy
    of `path` but then `opendir(path)` is called on the original
    non-NUL-terminated buffer. Same defect class as audit §3.23
    (SocketPlugin `stat()` on non-NUL-terminated image bytes).

  N03-NewFilePlugin-unchecked-mallocs.md              MEDIUM
    UnixFile.c:17-24, 52, 156; Win32File.c:38, 53, 72, 91 — every
    helper that allocates memory dereferences the result without a
    NULL check. Each is a clean NULL-deref on OOM, image-driven via
    every file-system primitive in the plugin.

These are not present in pharo-10 because NewFilePlugin did not
exist there. They should be addressed before pharo-12 ships, since
the plugin is in the build by default.


================================================================
FIXED UPSTREAM — bugs from pharo-10 no longer present in pharo-12
================================================================

  B09 — JIT pages mapped RWX permanently
      pharo-12 implements `sqMakeMemoryExecutableFromTo` and the
      "Not" sibling via real `mprotect` calls; `allocateJITMemory`
      can now map pages without PROT_EXEC under a new opt-in
      `READ_ONLY_CODE_ZONE` build flag (cmake/Linux.cmake:1). The
      pharo-10 patch is not needed. See fixed-upstream/B09 for the
      full discussion.

      Residual: the option is off by default on shipped Linux
      builds; operators need `-DREAD_ONLY_CODE_ZONE=ON`. Apple still
      uses RWX with MAP_JIT (would need pthread_jit_write_protect_np
      to fix properly; out of scope).


================================================================
How to use these PRs
================================================================

    cd ~/esrc/pharo-vm-12
    git apply --check ../PR-12/always/A01-sqNamedPrims-off-by-one.md   # verify
    git apply ../PR-12/always/A01-sqNamedPrims-off-by-one.md            # apply

Same caveats as PR/INDEX.md:

  * Diffs apply cleanly but compile/correctness/regression testing
    is still the human reviewer's responsibility before sending
    upstream.
  * The supply-chain PRs (B12, B13, B14, B15, B17, B18, B19) contain
    placeholder strings (`<FILL_IN_COMMIT_SHA>`, `<FILL_IN_DEBIAN_DIGEST>`,
    etc.) that an operator must replace with real values before the
    artifact will build.
  * A handful of PRs (5.13, 5.14, 5.19, 5.20, 5.21, 5.23) embed
    `/* FIXME: ... */` comments rather than full code fixes — the
    diff applies, but the underlying defect still needs a human to
    write the actual fix. Each PR's risk notes say so.
  * Patches that interact (especially A02, A06, A07 in `src/ffi/`)
    may conflict if applied as a single bundle; apply individually
    and re-roll context as needed.


================================================================
Where pharo-12 has moved forward
================================================================

Notable improvements observed during the re-anchor:

  * W^X infrastructure (`sqMakeMemoryExecutableFromTo` is real, opt-in
    via `READ_ONLY_CODE_ZONE`).
  * Cleaner directory layout (`extracted/` prefix dropped).
  * Bare `strcpy_s` calls in Windows utils.c now consistently pass
    the destination size (no longer the deprecated source length).
  * `setVMName` was removed (a global was eliminated).

Notable areas pharo-12 has *not* changed:

  * The SqueakSSL files on Windows and macOS are bit-for-bit identical
    aside from line-ending normalisation (CRLF→LF).
  * SocketPlugin AIO close-handler UAF, FFI heap-allocated callback,
    cipher list, no SSL_CTX_set_verify, … every memory-corruption
    bug in the audit is still present in pharo-12.
