fix: double-free in engram_neighbors_json BFS + rebuild engram.c

el_strdup tracks pointers in the arena. The BFS arrays in
engram_neighbors_json are manually freed — using el_strdup caused a
double-free when the arena was later popped. Changed to plain strdup
for those allocations.

engram/dist/engram.c rebuilt from engram/src/server.el with current
elc (minor codegen diff: parenthesisation and _argc/_argv rename).
This commit is contained in:
Will Anderson
2026-05-06 14:11:40 -05:00
parent bd7303447b
commit 6ced0f8009
2 changed files with 9 additions and 7 deletions
+6 -4
View File
@@ -7321,8 +7321,10 @@ el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t di
free(frontier); free(frontier_h); free(visited);
jb_putc(&b, ']'); return el_wrap_str(b.buf);
}
frontier[fc] = el_strdup(sid); frontier_h[fc] = 0; fc++;
visited[vc++] = el_strdup(sid);
/* Use plain strdup (not el_strdup) so arena doesn't track these pointers.
* The BFS loop manually frees them below arena would double-free them. */
frontier[fc] = strdup(sid); frontier_h[fc] = 0; fc++;
visited[vc++] = strdup(sid);
int first = 1;
while (fc > 0) {
@@ -7351,8 +7353,8 @@ el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t di
char tmp[64]; snprintf(tmp, sizeof(tmp), ",\"hops\":%lld}", (long long)(h + 1));
jb_puts(&b, tmp);
first = 0;
if (vc < 1024) visited[vc++] = el_strdup(peer);
if (fc < 1024 && h + 1 < depth) { frontier[fc] = el_strdup(peer); frontier_h[fc] = h + 1; fc++; }
if (vc < 1024) visited[vc++] = strdup(peer);
if (fc < 1024 && h + 1 < depth) { frontier[fc] = strdup(peer); frontier_h[fc] = h + 1; fc++; }
}
free(cur);
}