# Extended 3.14 — sqUnixSSL sqCreateSSL: unchecked calloc + realloc + BIO_new

Bug ref      : pharo.md §3.14
Severity     : HIGH (NULL deref on OOM; realloc-NULL also leaks the old buffer)
File         : extracted/plugins/SqueakSSL/src/unix/sqUnixSSL.c
Lines (HEAD) : 152-176 (`sqCreateSSL`)

## Problem

```c
sqInt sqCreateSSL(void) {
    sqInt handle = 0;
    sqSSL *ssl = NULL;

    ssl = calloc(1, sizeof(sqSSL));
    ssl->bioRead = BIO_new(BIO_s_mem());     // ssl may be NULL → SEGV
    ssl->bioWrite = BIO_new(BIO_s_mem());    // BIO_new return unchecked
    ...
    for(handle = 1; handle < handleMax; handle++)
        if(handleBuf[handle] == NULL) break;

    if(handle >= handleMax) {
        int i, delta = 100;
        handleBuf = realloc(handleBuf, (handleMax+delta)*sizeof(void*));
        for(i = handleMax; i < handleMax+delta; i++)
            handleBuf[i] = NULL;             // NULL deref on realloc fail
        handleMax += delta;                  // ...and old handleBuf leaked
    }
    handleBuf[handle] = ssl;
    return handle;
}
```

Three independent issues:
  1. `calloc` not checked → first `ssl->bioRead = …` SEGVs on OOM.
  2. `BIO_new(BIO_s_mem())` not checked → later code dereferences NULL.
  3. `realloc` failure aliases NULL into `handleBuf`, leaking the
     original buffer and then NULL-dereferencing it.

## Fix

```diff
diff --git a/plugins/SqueakSSL/src/unix/sqUnixSSL.c b/plugins/SqueakSSL/src/unix/sqUnixSSL.c
index 1af71037e..0a0dfbd5c 100644
--- a/plugins/SqueakSSL/src/unix/sqUnixSSL.c
+++ b/plugins/SqueakSSL/src/unix/sqUnixSSL.c
@@ -154,8 +154,20 @@ sqInt sqCreateSSL(void) {
 	sqSSL *ssl = NULL;
 
 	ssl = calloc(1, sizeof(sqSSL));
+	if (ssl == NULL) {
+		return 0;
+	}
 	ssl->bioRead = BIO_new(BIO_s_mem());
+	if (ssl->bioRead == NULL) {
+		free(ssl);
+		return 0;
+	}
 	ssl->bioWrite = BIO_new(BIO_s_mem());
+	if (ssl->bioWrite == NULL) {
+		BIO_free(ssl->bioRead);
+		free(ssl);
+		return 0;
+	}
 	BIO_set_close(ssl->bioRead, BIO_CLOSE);
 	BIO_set_close(ssl->bioWrite, BIO_CLOSE);
 
@@ -166,7 +178,15 @@ sqInt sqCreateSSL(void) {
 	if(handle >= handleMax) {
 		int i, delta = 100;
 		/* Resize the handle buffer */
-		handleBuf = realloc(handleBuf, (handleMax+delta)*sizeof(void*));
+		void **resized = realloc(handleBuf, (handleMax+delta)*sizeof(void*));
+		if (resized == NULL) {
+			/* Old handleBuf still valid; clean up the SSL we built. */
+			BIO_free(ssl->bioWrite);
+			BIO_free(ssl->bioRead);
+			free(ssl);
+			return 0;
+		}
+		handleBuf = (sqSSL **)resized;
 		for(i = handleMax; i < handleMax+delta; i++)
 			handleBuf[i] = NULL;
 		handleMax += delta;

```

## Test plan

- Under an OOM injection (LD_PRELOAD malloc shim), call sqCreateSSL.
  Before: SEGV on the first dereference. After: returns 0.
- Repeated sqCreateSSL until realloc fails: the old handleBuf is
  preserved, the partial sqSSL is freed cleanly, return 0.

## Risk notes

- Returning 0 on failure matches `sqDestroySSL`'s assumption that
  handle 0 is the sentinel.
- BIO_free works on a single BIO; the pair use BIO_set_close to
  manage memory but the explicit cleanup here is safer when one of
  the two creations failed.
