Pharo-dev
By thread
pharo-dev@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
May 2026
- 19 messages
Re: claude.ai code review of pharo-v
by Aaron Wohl
It has been in the news that Anthropic delayed the release of Mythos to invite groups to fix the AI's bugs. The news reports suggest that the big open-source projects are accepting AI bug fixes (not just bug reports). If the linux kernal and chrome are accepting AI code how can they do it and pharo can not?
https://www.linuxfoundation.org/blog/project-glasswing-gives-maintainers-ad…
I am not suggesting that AI code should be blindly accepted, some of AI bugs and fixes are fine. It is faster to have a human review than to generate fixes.
----- Original message -----
From: stephane ducasse <stephane.ducasse(a)inria.fr>
To: Aaron Wohl <xphu(a)awohl.com>
Cc: guillermo.polito(a)inria.fr, Pharo-dev <pharo-dev(a)lists.pharo.org>
Subject: Re: [Pharo-dev] claude.ai code review of pharo-v
Date: Wednesday, May 13, 2026 3:26 PM
thanks we will check this.
> On 13 May 2026, at 19:24, Aaron Wohl <xphu(a)awohl.com> 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 <stephane.ducasse(a)inria.fr>
> To: Aaron Wohl <xphu(a)awohl.com>
> Cc: guillermo.polito(a)inria.fr, Pharo Development List <pharo-dev(a)lists.pharo.org>
> 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 <pharo-dev(a)lists.pharo.org> 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…
>>
>> I did not make an AI-generated patch list. stephane.ducasse(a)free.fr mentioned copyright concerns by guillermo.polito(a)inria.fr 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]
>
May 14, 2026
Re: claude.ai code review of pharo-v
by stephane ducasse
thanks we will check this.
> On 13 May 2026, at 19:24, Aaron Wohl <xphu(a)awohl.com> 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 <stephane.ducasse(a)inria.fr>
> To: Aaron Wohl <xphu(a)awohl.com>
> Cc: guillermo.polito(a)inria.fr, Pharo Development List <pharo-dev(a)lists.pharo.org>
> 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 <pharo-dev(a)lists.pharo.org> 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…
>>
>> I did not make an AI-generated patch list. stephane.ducasse(a)free.fr mentioned copyright concerns by guillermo.polito(a)inria.fr 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]
>
May 13, 2026
Re: claude.ai code review of pharo-v
by Aaron Wohl
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 <stephane.ducasse(a)inria.fr>
To: Aaron Wohl <xphu(a)awohl.com>
Cc: guillermo.polito(a)inria.fr, Pharo Development List <pharo-dev(a)lists.pharo.org>
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 <pharo-dev(a)lists.pharo.org> 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…
>
> I did not make an AI-generated patch list. stephane.ducasse(a)free.fr mentioned copyright concerns by guillermo.polito(a)inria.fr 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]
May 13, 2026
Re: claude.ai code review of pharo-v
by stephane ducasse
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 <pharo-dev(a)lists.pharo.org> 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…
>
> I did not make an AI-generated patch list. stephane.ducasse(a)free.fr mentioned copyright concerns by guillermo.polito(a)inria.fr 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]
May 13, 2026
Fwd: claude.ai code review of pharo-v
by Aaron Wohl
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…
I did not make an AI-generated patch list. stephane.ducasse(a)free.fr mentioned copyright concerns by guillermo.polito(a)inria.fr 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]
May 12, 2026
Re: "Claude, My New Pair Programming Partner" â New blog post on all: objects all: theTime
by Sebastian Jordan
> Le 8 mai 2026 à 10:17, Nicolas Anquetil <nicolas.anquetil(a)inria.fr> a écrit :
>
> About AI and truck factor
>
> This post https://www.shapeandship.ai/p/cheap-to-build-costly-to-keep argues that with AI coding the truck factor tends toward 0...
> In a post-mortem, this surfaces as "nobody knew this code existed," which is worse than "only one person knew. »
>
Indeed, this is a real problem. However I think that using coding agents can be very useful for Pharo. It can help us to develop features that otherwise we will simply not do. For example I am thinink about Morphic and its window managing system. Morphic is already old code that we do not understand and that we will get rid off. I would like to experiment with Claude to see if we can have that implemented (There is one person on Discord that did this for example: www.youtube.com/watch?v=NF2Bcl2Mu3Q <http://www.youtube.com/watch?v=NF2Bcl2Mu3Q>)
Also, Firefox people found and fixed insane security bugs thanks to LLMs too: https://hacks.mozilla.org/2026/05/behind-the-scenes-hardening-firefox/
We could also benefit from that.
> They talk about "comprehension debt" (evolution of the technical debt concept)
>
> cheers
>
> nicolas
>
> On 2026-05-07 22:01, Koen De Hondt wrote:
>> Dear Pharo users and developers,
>>
>> I posted a first article in a series about using AI in Pharo development. After seeing the world embrace agentic development tools, I decided it was time to look into them and see how they can be used for software development in Pharo.
>>
>> https://all-objects-all-the-time.st/#/blog/posts/24
>>
>> As always, all feedback is welcome.
>>
>> Happy reading!
>>
>> Ciao,
>> Koen
> --
> Nicolas Anquetil
> Evref team -- Inria Lille
May 9, 2026
Re: "Claude, My New Pair Programming Partner" â New blog post on all: objects all: theTime
by omar abedelkader
Hello Koen and everyone.
Itâs really nice to see people getting more and more interested in AI, especially for Pharo.
But I think you are wrong about ChatPharo. I understand very clearly your point that the AI for and in Pharo is in his realy stagses. But Iâm working very hard to make it more usable for more and more people ( people are also scared of using AI in Pharo because they had bad experiences with ChatGPT when it was launched in 2022). It wasnât created to do code generation tasks.
That said. I wanted to clarify some points about ChatPharo:
- ChatPharo is not a toy. It has a big engineering part inside of it (Multiple people, including PhDs, and engineers, contribute to it). Indeed, Iâm not doing a lot of publicity because i also doing my PhD at the same time.
- From an AI engineer's POV, the dependencies on the company that provides models accessible from the web are not very convenient. I agreed that Claude is the best model for code generation (and it appears everything else but you are limited to the company API and the backend. FYI: the newest Claude and OpenAI models have more than 1T parameters.) But let me ask you a question, what if tmrw claude changes its policies now after their deal with SpaceX? (They will expect more and more people that subscirbe to their 20 euros, right? ) Well, in that case, any CEO in his right mind will increase the price ( it will be one million cause of that, of course, why do they do that, whatever they tell, the people will buy it because now they canât live without it). Thatâs why itâs not very convenient ( this is what i think).
- Ollama ( that were considered one of the best companies that provided the models for free (local and on the cloud). Now you should pay for the model inference on the cloud ( it was free ), because they saw that more people are getting interested in the model that runs on the cloud ( and itâs free), they now prohibit you from using it unless you pay 20 euros.
- Why do you think that the model that appears now is getting better? Itâs not training or something else. There's nothing left in the whole internet to train on anyway. They now want real data ( you might see in most of the newest technical papers the sentence high quality token. You might ask yourself a question about where this data appears if there is nothing left on the internet to train?
Now, make no mistakes, Iâm not telling you NOT to use AI for Pharo. I and (we) are and (wonât) be able to concure with the companies that have models that have > 1T of parameters. (We don't have the budget, nor the resources for that). Iâm just trying to justify that chatpharo for now is not (and wonât) be capable of competing with the models from the biggest company. Ofc everyone is free. But I wanted to just shed light on a few points that more and more people ask questions about.
Have a good weekend!
â
OA
https://github.com/pharo-llm
> Le 7 mai 2026 à 22:01, Koen De Hondt <koen(a)all-objects-all-the-time.st> a écrit :
>
> Dear Pharo users and developers,
>
> I posted a first article in a series about using AI in Pharo development. After seeing the world embrace agentic development tools, I decided it was time to look into them and see how they can be used for software development in Pharo.
>
> https://all-objects-all-the-time.st/#/blog/posts/24
>
> As always, all feedback is welcome.
>
> Happy reading!
>
> Ciao,
> Koen
May 9, 2026
Re: "Claude, My New Pair Programming Partner" â New blog post on all: objects all: theTime
by Nicolas Anquetil
About AI and truck factor
This post https://www.shapeandship.ai/p/cheap-to-build-costly-to-keep
argues that with AI coding the truck factor tends toward 0...
/In a post-mortem, this surfaces as "nobody knew this code existed,"
which is worse than "only one person knew."/
They talk about "comprehension debt" (evolution of the technical debt
concept)
cheers
nicolas
On 2026-05-07 22:01, Koen De Hondt wrote:
> Dear Pharo users and developers,
>
> I posted a first article in a series about using AI in Pharo
> development. After seeing the world embrace agentic development tools,
> I decided it was time to look into them and see how they can be used
> for software development in Pharo.
>
> https://all-objects-all-the-time.st/#/blog/posts/24
>
> As always, all feedback is welcome.
>
> Happy reading!
>
> Ciao,
> Koen
--
Nicolas Anquetil
Evref team -- Inria Lille
May 8, 2026
"Claude, My New Pair Programming Partner" â New blog post on all: objects all: theTime
by Koen De Hondt
Dear Pharo users and developers,
I posted a first article in a series about using AI in Pharo development. After seeing the world embrace agentic development tools, I decided it was time to look into them and see how they can be used for software development in Pharo.
https://all-objects-all-the-time.st/#/blog/posts/24
As always, all feedback is welcome.
Happy reading!
Ciao,
Koen
May 7, 2026