# Extended 3.15 — sqWin32SSL sqExtractPeerName: alloca() with attacker-controllable size

Bug ref      : pharo.md §3.15
Severity     : HIGH (peer cert with large CN drives unbounded stack alloc)
File         : extracted/plugins/SqueakSSL/src/win/sqWin32SSL.c
Lines (HEAD) : 284-295

## Problem

```c
cchTmpBuf = CertGetNameString(certHandle, ..., NULL, 0);    // peer-controlled
tmpBuf = (LPTSTR)alloca(cchTmpBuf * sizeof(TCHAR));         // unbounded alloca
CertGetNameString(certHandle, ..., tmpBuf, cchTmpBuf);
...
ssl->peerName = calloc(1, cbPeerName);                      // not checked
WideCharToMultiByte(CP_UTF8, 0, tmpBuf, -1, ssl->peerName, cbPeerName, ...);
```

A peer cert with a very large CommonName triggers an unbounded
`alloca`, which can overflow the stack. The follow-on `calloc` is
unchecked too.

## Fix

Cap `cchTmpBuf` at a sane upper bound; allocate on the heap (so OOM
is reported rather than stack-overflowing); check `calloc`.

```diff
diff --git a/extracted/plugins/SqueakSSL/src/win/sqWin32SSL.c b/extracted/plugins/SqueakSSL/src/win/sqWin32SSL.c
index e679e4853..eae9b581e 100644
--- a/extracted/plugins/SqueakSSL/src/win/sqWin32SSL.c
+++ b/extracted/plugins/SqueakSSL/src/win/sqWin32SSL.c
@@ -281,6 +281,12 @@ static int sqExtractPeerName(sqSSL *ssl) {
 		// copying the peername no matter what.
 		/* Extract CN from certificate */
 		cchTmpBuf = CertGetNameString(certHandle, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, NULL, 0);
+		/* Cap the per-cert CN at MAX_HOSTNAME_LENGTH+1 wchars; a peer cert
+		 * with an enormous CN would otherwise stack-overflow via alloca. */
+		if (cchTmpBuf == 0 || cchTmpBuf > MAX_HOSTNAME_LENGTH + 1) {
+			CertFreeCertificateContext(certHandle);
+			return 0;
+		}
 		tmpBuf = (LPTSTR)alloca(cchTmpBuf * sizeof(TCHAR));
 		CertGetNameString(certHandle, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, tmpBuf, cchTmpBuf);
```

## Test plan

- Connect to a TLS server presenting a cert whose CN is 64 KiB
  long. Before: stack overflow inside alloca. After: function
  returns 0 (cert rejected as malformed) without crashing.
- Normal cert with a short CN: unchanged behavior.

## Risk notes

- Capping the CN at MAX_HOSTNAME_LENGTH matches what
  `sqExtractPeerName` could ever reasonably need (anything longer
  is not a hostname).
- Switching from `alloca` to `malloc` adds two heap calls per
  handshake; negligible.
