From 300877bc8d85284423e0d0eb23fe4c49c585fb75 Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Tue, 13 Oct 2026 03:47:14 +0200 Subject: [PATCH] fix(lsp): no pointer offset on an empty C# or Java definition array The C# and Java Tier-2 registry builders register types, finalize, then register the rest from `defs + type_count`. With no definitions of that language the array is NULL, and NULL + 0 is undefined: clang's UBSan reports "applying zero offset to null pointer" at cs_lsp.c:3886 on the macOS legs of dry run 38321896354 (reached by incremental_k8s_edits_reach_other_files, a project without C# files). The second registration now runs only when there is something to register; both finalize calls are unchanged. cs_lsp, cs_lsp_bench, java_lsp, java_lsp_coverage, lsp_resolution_probe: 529 passed (macOS). The report reproduces on CI's macOS clang, not on the local toolchain, so CI's macOS legs are the check. Signed-off-by: Martin Vogel --- internal/cbm/lsp/cs_lsp.c | 4 +++- internal/cbm/lsp/java_lsp.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/internal/cbm/lsp/cs_lsp.c b/internal/cbm/lsp/cs_lsp.c index c5ee1a87b..023a963af 100644 --- a/internal/cbm/lsp/cs_lsp.c +++ b/internal/cbm/lsp/cs_lsp.c @@ -3883,7 +3883,9 @@ CBMTypeRegistry *cbm_cs_build_cross_registry(CBMArena *arena, CBMLSPDef *defs, i } cs_register_lsp_defs(arena, reg, cs, type_count); cbm_registry_finalize(reg); - cs_register_lsp_defs(arena, reg, cs + type_count, total - type_count); + if (total > type_count) { /* cs is NULL for an empty corpus: no offset */ + cs_register_lsp_defs(arena, reg, cs + type_count, total - type_count); + } cbm_registry_finalize(reg); reg->read_only = true; /* seal: shared Tier-2 registry is read-only during resolve */ return reg; diff --git a/internal/cbm/lsp/java_lsp.c b/internal/cbm/lsp/java_lsp.c index 2b518d890..cf221f06e 100644 --- a/internal/cbm/lsp/java_lsp.c +++ b/internal/cbm/lsp/java_lsp.c @@ -3879,7 +3879,9 @@ CBMTypeRegistry *cbm_java_build_cross_registry(CBMArena *arena, CBMLSPDef *defs, } cbm_java_register_lsp_defs(arena, reg, jvm, type_count); cbm_registry_finalize(reg); - cbm_java_register_lsp_defs(arena, reg, jvm + type_count, total - type_count); + if (total > type_count) { /* jvm is NULL for an empty corpus: no offset */ + cbm_java_register_lsp_defs(arena, reg, jvm + type_count, total - type_count); + } cbm_registry_finalize(reg); reg->read_only = true; /* seal: shared Tier-2 registry is read-only during resolve */ return reg;