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:
Vendored
+3
-3
@@ -308,7 +308,7 @@ el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body) {
|
|||||||
if (str_eq(method, EL_STR("POST")) && (str_eq(clean, EL_STR("/api/nodes")) || str_eq(clean, EL_STR("/nodes")))) {
|
if (str_eq(method, EL_STR("POST")) && (str_eq(clean, EL_STR("/api/nodes")) || str_eq(clean, EL_STR("/nodes")))) {
|
||||||
return route_create_node(method, path, body);
|
return route_create_node(method, path, body);
|
||||||
}
|
}
|
||||||
if (str_eq(method, EL_STR("GET")) && (str_eq(clean, EL_STR("/api/nodes")) || str_eq(clean, EL_STR("/nodes")) || str_eq(clean, EL_STR("/nodes/list")) || str_eq(clean, EL_STR("/api/nodes/list")))) {
|
if (str_eq(method, EL_STR("GET")) && (((str_eq(clean, EL_STR("/api/nodes")) || str_eq(clean, EL_STR("/nodes"))) || str_eq(clean, EL_STR("/nodes/list"))) || str_eq(clean, EL_STR("/api/nodes/list")))) {
|
||||||
return route_scan_nodes(method, path, body);
|
return route_scan_nodes(method, path, body);
|
||||||
}
|
}
|
||||||
if (str_eq(method, EL_STR("GET")) && (str_eq(clean, EL_STR("/api/edges")) || str_eq(clean, EL_STR("/edges")))) {
|
if (str_eq(method, EL_STR("GET")) && (str_eq(clean, EL_STR("/api/edges")) || str_eq(clean, EL_STR("/edges")))) {
|
||||||
@@ -351,8 +351,8 @@ el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int _argc, char** _argv) {
|
||||||
el_runtime_init_args(argc, argv);
|
el_runtime_init_args(_argc, _argv);
|
||||||
bind_str = env(EL_STR("ENGRAM_BIND"));
|
bind_str = env(EL_STR("ENGRAM_BIND"));
|
||||||
if (str_eq(bind_str, EL_STR(""))) {
|
if (str_eq(bind_str, EL_STR(""))) {
|
||||||
bind_str = EL_STR(":8742");
|
bind_str = EL_STR(":8742");
|
||||||
|
|||||||
@@ -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);
|
free(frontier); free(frontier_h); free(visited);
|
||||||
jb_putc(&b, ']'); return el_wrap_str(b.buf);
|
jb_putc(&b, ']'); return el_wrap_str(b.buf);
|
||||||
}
|
}
|
||||||
frontier[fc] = el_strdup(sid); frontier_h[fc] = 0; fc++;
|
/* Use plain strdup (not el_strdup) so arena doesn't track these pointers.
|
||||||
visited[vc++] = el_strdup(sid);
|
* 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;
|
int first = 1;
|
||||||
while (fc > 0) {
|
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));
|
char tmp[64]; snprintf(tmp, sizeof(tmp), ",\"hops\":%lld}", (long long)(h + 1));
|
||||||
jb_puts(&b, tmp);
|
jb_puts(&b, tmp);
|
||||||
first = 0;
|
first = 0;
|
||||||
if (vc < 1024) visited[vc++] = el_strdup(peer);
|
if (vc < 1024) visited[vc++] = strdup(peer);
|
||||||
if (fc < 1024 && h + 1 < depth) { frontier[fc] = el_strdup(peer); frontier_h[fc] = h + 1; fc++; }
|
if (fc < 1024 && h + 1 < depth) { frontier[fc] = strdup(peer); frontier_h[fc] = h + 1; fc++; }
|
||||||
}
|
}
|
||||||
free(cur);
|
free(cur);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user