thanks we will check this.
> On 13 May 2026, at 19:24, Aaron Wohl <[email protected]> wrote: > > I had Claude create PRs for the current git main and for the version 12 you > asked for. > I didn't submit them because they are AI-generated. I have no interest in > doing manual work that an AI can do. On copyright: if not being able to > copyright AI work is the issue, perhaps you could copyright the collection > (of source lines)? > > For pharo-12 there are 93 bug fixes posted here. > https://www.awohl.com/pharo-bugs-2026-05-13/ > > ----- Original message ----- > From: stephane ducasse <[email protected]> > To: Aaron Wohl <[email protected]> > Cc: [email protected], Pharo Development List > <[email protected]> > Subject: Re: [Pharo-dev] claude.ai code review of pharo-v > Date: Wednesday, May 13, 2026 8:14 AM > > Hi aaron > > Today I discussed with Guille (who was and still a bit sick and under > recovery) and did not have the opportunity to discuss with Pablo (who is on > vacation) > > We are interested in pullrequests that improve the security and code of the > VM and pluggins. > So your analyses are definitively worth. > > We would love to have PRs and for us this is great if you do them and not an > IA so that we can control the copyright concerns. > > So thank you for your time and idea. > Guille may contact you directly. > > S (this week we have 3 working days) and next week we have also some > non-working days. > The month of may is a gruyere. > > >> On 12 May 2026, at 09:10, Aaron Wohl via Pharo-dev >> <[email protected]> wrote: >> >> I regularly have Claude.AI review my code https://awohl.com, I pointed >> Claude at the Pharo-VM to see what it could see. A lot of the issues it >> found are things like strcpy without bounds checks with strings no one would >> ever make that big. However, it found some issues that are always triggered. >> >> Full list of issues >> https://github.com/avwohl/iospharo/blob/main/docs/pharo-vm-code-reivew-2026-05-11.md >> >> I did not make an AI-generated patch list. [email protected] >> mentioned copyright concerns by [email protected] of accepting AI >> code. I assume this is due to the inability to copyright AI-generated work >> and to AI's tendency to steal others' work and lie about its origins. >> However, a lot of the fixes are so trivial, like off-by-one errors, that I >> don't know how much of an issue it is. If you want me to PR fixes and or >> tests that trigger for the full list, or always list, let me know. >> >> Many of the issues would only happen if someone were trying to break things >> (MAXLEN symlinks, damaged image files). If one were a mindset, it could be >> called AI slop. However, here is a short list of things that always cause >> issues in everyday operation: for example, every plugin loaded damages heap >> memory, or the nightly build of signed code disables SSL checks, so a simple >> DNS hack could get malicious code signed. >> >> Source: ~/pharo.md (review of /Users/wohl/esrc/pharo-vm @ pharo-10, >> 2026-05-11) >> Filter: only items that fire in normal benign operation, not edge cases >> requiring huge/crafted strings or attacker-chosen sizes. >> >> ================================================================ >> A. ALWAYS — MEMORY DAMAGE / UNDEFINED BEHAVIOR >> ================================================================ >> >> 1. sqNamedPrims.c:56-57 — calloc(sizeof(ModuleEntry)+strlen(name)) then >> strcpy writes strlen+1; 1-byte heap overflow on every plugin load. [#3.26] >> 2. ffi/callbacks/callbacks.c:14-32 — stack-allocated CallbackInvocation >> registered in runner->callbackStack/global queue; sig_longjmp exit leaves >> dangling stack pointer after every same-thread callback. [#2.8] >> 3. ffi/typesPrimitives.c:174-188 — setHandler(receiver, structType) stores >> pointer before failed()/ffi_get_struct_offsets checks; any error path frees >> memory while receiver still holds the dangling handle. [#2.6] >> 4. threadSafeQueue.c:113-137 — queue->first and node->element read outside >> the mutex; lock-holder's free(node) leaves the other consumer walking freed >> memory on every concurrent dequeue (hit by every FFI workload). [#3.21] >> 5. SocketPluginImpl.c:1109-1123 — sqSocketDestroy frees PSP(s) after >> sqSocketAbortConnection queues a closeHandler against pss; AIO dispatch >> fires on freed memory. [#3.22] >> 6. ffi/utils.c:43-50 — readString returns an un-pinned image-memory pointer; >> GC between strlen() and the caller's strcpy invalidates the length and the >> address. [#5.27] >> 7. ffi/callbacks/callbacks.c:24-29 — runner->callbackStack chain updated >> without any lock; reentrant callbacks from multiple threads on the same >> Runner corrupt the linked list. [#5.4] >> 8. pathUtilities.c:233-237 — strrchr(name,'.') result stored in >> fileExtension, but the NULL guard tests the unrelated `extension` variable; >> strcmp(NULL,...) crashes on any directory entry without a dot (e.g. >> "Makefile"). [#4.2] >> 9. pathUtilities.c:163 — first[strlen(first)-1] reads first[-1] (one byte >> before the buffer) whenever first is "", reachable from parameters.c:210-212 >> fallback. [#4.3] >> 10. externalPrimitives.c:57,66 — module path assembled in a file-static >> moduleNameBuffer with no lock; concurrent loads scribble each other's path >> and dlopen/LoadLibrary sees a torn string. [#5.3] >> 11. debugUnix.c:88-95,122-162 — SIGSEGV/SIGBUS/SIGFPE handler calls >> fopen/vfprintf/backtrace_symbols_fd/ctime_r/semaphore_wait (none >> async-signal-safe) and uses SA_NODEFER so the handler can re-enter itself on >> every crash. [#5.1] >> 12. debugUnix.c:123,144,154 — sigaction.sa_mask never initialized via >> sigemptyset for term_handler_action and sigpipe_handler_action; kernel reads >> uninitialized stack to decide what to mask on every install. [#5.2] >> 13. debug.c:57-66 — glibc strerror_r returns a pointer that may not write to >> the supplied buffer; caller prints the buffer unconditionally, leaking >> uninitialized stack bytes on every error path. [#5.7] >> 14. SocketPluginImpl.c:2494-2496 — sqSocket lastError stored in a >> file-static, clobbered across sockets; every concurrent socket failure >> overwrites another socket's error state. [#5.17] >> 15. aioWin.c:457/465 — heap-interior alias into allHandles transiently >> equals a freshly malloc'd region; any early return between the two >> assignments leaves a free-of-interior or double-use hazard. [#1/§9 PARTIAL] >> >> >> ================================================================ >> B. ALWAYS — SECURITY / CORRECTNESS (NOT MEMORY DAMAGE) >> ================================================================ >> >> TLS / SqueakSSL >> --------------- >> 1. sqUnixSSL.c:89-143 — SSL_CTX_set_verify never called; >> SSL_get_verify_result returns X509_V_OK by default → no certificate >> validation on any TLS connection. [#2.9] >> 2. sqUnixSSL.c:102-107 — SSLv23_method with only SSLv2/v3 disabled; TLS 1.0 >> and 1.1 still accepted on every handshake. [#2.9 / #6.3] >> 3. sqUnixSSL.c:115 — cipher list "!ADH:HIGH:MEDIUM:@STRENGTH" permits MEDIUM >> ciphers. [#2.9] >> 4. sqUnixSSL.c:107 — no SSL_OP_NO_COMPRESSION (CRIME), no >> SSL_OP_NO_RENEGOTIATION, no SSL_OP_CIPHER_SERVER_PREFERENCE. [#6.3] >> 5. sqWin32SSL.c:269-275,215,349-353 — sqExtractPeerName copies serverName >> verbatim into peerName instead of extracting the cert subject; >> epp.pwszServerName=NULL disables SChannel's hostname check, so image-side >> peerName==serverName is meaningless on every connection. [#3.19] >> 6. sqMacSSL.c:154-201,262-272,363-383 — kSSLSessionOptionBreakOnServerAuth >> disables auto verification; manual SecTrustEvaluate runs with no SSL policy >> carrying the hostname, so hostname is never checked. [#3.20] >> 7. sqWin32SSL.c:216-218 — SP_PROT_TLS1_0/1_1/1_2 enabled for both client and >> server roles. [#6.1] >> 8. sqMacSSL.c:154-164 — SSLSetProtocolVersionMin(ctx, kTLSProtocol1) sets >> minimum to TLS 1.0. [#6.2] >> >> VM internals >> ------------ >> 9. memoryUnix.c:66-89,109-111 — JIT pages mmap'd >> PROT_READ|PROT_WRITE|PROT_EXEC permanently; sqMakeMemoryExecutableFromTo / >> NotExecutable hooks are commented out, so W^X is defeated on Linux/FreeBSD. >> [#5.24] >> 10. debug.c:45 — error(char*) forwards the argument as the format string >> into the vfprintf-style logger; exported API contract leaks a %n/%s >> primitive to any future caller-controlled string. [#4.10] >> 11. ffi/typesPrimitives.c:170-172 — getHandler() returns the first slot of >> any oop with no class tag check; libffi consumes attacker-shaped ffi_type >> fields on every struct cif build, giving a controlled-dispatch primitive to >> anyone who can register an FFI struct. [#2.5] >> >> Build / supply chain (every build / every CI run) >> ------------------------------------------------- >> 12. Jenkinsfile:84,249 — fetch-and-execute installer via `wget … | bash` >> over plain HTTP. [#7] >> 13. scripts/runTests.sh:31 — `wget -O - https://get.pharo.org/64/80 | bash`, >> executed from PR workflows. [#7] >> 14. scripts/installCygwin.ps1:7-9 — Cygwin installer + mirror retrieved over >> plain HTTP. [#7] >> 15. cmake/importLibFFI.cmake / importLibGit2.cmake / importSDL2.cmake — >> dependencies pinned to mutable git tags, no commit-SHA. [#7] >> 16. macros.cmake:69-103 + every cmake/import*.cmake using files.pharo.org — >> DownloadProject calls omit URL_HASH for libgit2, libssh2, openssl, zlib, >> SDL2, cairo, pixman, libpng, freetype, fontconfig, harfbuzz, gcc-runtime. >> [#7] >> 17. cmake/importFreetype2.cmake:47-49 — direct savannah.gnu.org download >> with no URL_HASH. [#7] >> 18. docker/ubuntu-arm64/Dockerfile, docker/debian10-armv7/Dockerfile — base >> images unpinned (no @sha256 digest). [#7] >> 19. Jenkinsfile:97-403 — every upload uses `scp -o StrictHostKeyChecking=no` >> against files.pharo.org. [#7] >> 20. Jenkinsfile:138 + cmake/sign.cmake:8-11 — SIGN_CERT_PASSWORD passed >> through environment under a broad withCredentials() block. [#7] >> 21. .github/workflows/continuous-integration-workflow.yaml:2 — `on: [push, >> pull_request]` with no `permissions:` block; fork PRs can edit runTests.sh >> and execute with the workflow GITHUB_TOKEN scope. [#7] >> 22. .github/workflows/...:11,14,68 — EOL runners (ubuntu-18.04, >> windows-2016) and EOL actions (checkout@v1, upload-artifact@v1). [#7] >> 23. cmake/packaging.cmake:92 — CPACK_PACKAGE_CHECKSUM "SHA1". [#7] >> 24. scripts/installCygwin.ps1:35-48 — `cygwin -q` suppresses signature >> warnings during install. [#7] >> 25. CMakeLists.txt:206,266-296 + cmake/Linux.cmake:1 — no >> -D_FORTIFY_SOURCE=2, no -fstack-protector-strong, no -fPIE/-pie, no >> -Wformat-security, no -Wl,-z,relro / -z,now / -z,noexecstack on Linux >> release builds. [#7] >> 26. CMakeLists.txt:206,266-296 — -Wno-int-conversion and -Wno-pointer-sign >> actively silenced; both classes of warning catch real bugs. [#7] >> 27. cmake/Linux.cmake:1 — Linux rpath set to "." (relative to CWD) instead >> of "$ORIGIN". [#7] >> 28. CMakeLists.txt:206 — Windows/Cygwin builds lack /GS, /guard:cf, >> /DYNAMICBASE, /NXCOMPAT. [#7] >
