# B10 — debug: error(char*) forwards argument as format string

Bug ref      : always.md B.10 ; pharo.md §4.10
Severity     : LOW today (no caller-controlled string today), LATENT footgun
File         : src/debug.c
Lines (HEAD) : 44-49 (`error`)

## Problem

```c
void error(char *errorMessage){
    logError(errorMessage);          // <-- errorMessage used as format
    logError("Aborting the execution of the VM");
    printStatusAfterError();
    abort();
}
```

`logError` is a macro that expands to `logMessage(LOG_ERROR, …,
__VA_ARGS__)`, and `logMessage` treats the first variadic argument as
a printf-style format string (debug.c:112-115). `error(char *)` is an
exported API; today all in-tree callers pass literal strings, but the
API contract permits any caller to pass a `char *` they computed at
runtime — at which point a `%n`/`%s`/`%p` token gives the caller an
arbitrary-read / arbitrary-write primitive.

Cost to fix is one line; cost to misuse later is large.

## Fix

Pass the argument as a `%s` value, not as a format.

```diff
diff --git a/src/debug.c b/src/debug.c
index be1afeaf6..915f926f6 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -42,7 +42,7 @@ EXPORT(int) isLogDebug(){
 }
 
 void error(char *errorMessage){
-    logError(errorMessage);
+    logError("%s", errorMessage);
 	logError("Aborting the execution of the VM");
 	printStatusAfterError();
     abort();
```

## Test plan

- `error("test message")` still produces `[ERROR] … test message`
  in the log.
- `error("%s%s%s%s%s")` (or any other format-token-bearing string)
  no longer triggers undefined behaviour or stack walking.
- All other `logError(…)` call sites are unaffected; only the
  `error()` wrapper changed.

## Risk notes

- Behaviour is unchanged on every in-tree caller (they pass literal
  strings without `%`).
- Closes a class of bugs at the API boundary so a future caller
  passing user-controlled data does not silently introduce an
  exploitable primitive.
