diff --git a/internal/cbm/extract_defs.c b/internal/cbm/extract_defs.c index e0b6ca5f6..190252e9e 100644 --- a/internal/cbm/extract_defs.c +++ b/internal/cbm/extract_defs.c @@ -4926,14 +4926,14 @@ static void extract_var_names(CBMExtractCtx *ctx, TSNode node, const CBMLangSpec if (strcmp(kind, "require_directive") == 0 || strcmp(kind, "replace_directive") == 0) { uint32_t rc = ts_node_named_child_count(node); for (uint32_t i = 0; i < rc; i++) { - TSNode spec = ts_node_named_child(node, i); - const char *sk = ts_node_type(spec); + TSNode req_spec = ts_node_named_child(node, i); + const char *sk = ts_node_type(req_spec); if (strcmp(sk, "require_spec") != 0 && strcmp(sk, "replace_spec") != 0) { continue; } - TSNode mp = cbm_find_child_by_kind(spec, "module_path"); + TSNode mp = cbm_find_child_by_kind(req_spec, "module_path"); if (!ts_node_is_null(mp)) { - push_var_def(ctx, cbm_node_text(a, mp, ctx->source), spec); + push_var_def(ctx, cbm_node_text(a, mp, ctx->source), req_spec); } } } diff --git a/src/pipeline/pass_parallel.c b/src/pipeline/pass_parallel.c index ade59e95d..38e5b33eb 100644 --- a/src/pipeline/pass_parallel.c +++ b/src/pipeline/pass_parallel.c @@ -1266,6 +1266,12 @@ static void emit_http_async_service_edge(cbm_gbuf_t *gbuf, const cbm_gbuf_node_t static void emit_config_edge(cbm_gbuf_t *gbuf, const cbm_gbuf_node_t *source, const cbm_gbuf_node_t *target, const CBMCall *call, const cbm_resolution_t *res, const char *arg) { + /* emit_service_edge may be reached with target==NULL on the HTTP/ASYNC + * external-client bypass (#523); a CONFIGURES edge needs a real target, so + * never deref a NULL target here. */ + if (!target) { + return; + } char esc_c[CBM_SZ_256]; char esc_k[CBM_SZ_256]; cbm_json_escape(esc_c, sizeof(esc_c), call->callee_name); @@ -1280,6 +1286,11 @@ static void emit_config_edge(cbm_gbuf_t *gbuf, const cbm_gbuf_node_t *source, static void emit_normal_calls_edge(cbm_gbuf_t *gbuf, const cbm_gbuf_node_t *source, const cbm_gbuf_node_t *target, const CBMCall *call, const cbm_resolution_t *res) { + /* A CALLS edge needs a real target; the HTTP/ASYNC external-client bypass + * (#523) can reach emit_service_edge with target==NULL, so guard the deref. */ + if (!target) { + return; + } char esc_c[CBM_SZ_256]; cbm_json_escape(esc_c, sizeof(esc_c), call->callee_name); char props[CBM_SZ_2K];