mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 10:48:20 +00:00
fix(diagram): set an empty PlantUML operand id when there is none
dg_puml_operand set *label up front but *id only on its success paths, so an opener without its closer (`Alice ->: x`, `[-> Alice: x`, `class [Unclosed`) returned with *id unwritten. dg_puml_relation and dg_puml_decl then read an uninitialized dg_str_t and passed it to dg_element, which crashed the index worker on some stacks. The operand now starts with an empty id, so those lines take the existing `!lid.n` / `!rid.n` exits and declarations make no element. Fixes #2818 Signed-off-by: Rodion Kazennov <nefayran@gmail.com>
This commit is contained in:
1 parent
3be5a02708
commit
d68cd2e2af
2 files changed
+34
-1
No files matched your search
@@ -1225,9 +1225,11 @@ static bool dg_word_at(dg_str_t s, const char *word) {
|
||||
}
|
||||
|
||||
/* An operand of a PlantUML line: `[Comp]`, `(use case)`, `:actor:`, `"text"`,
|
||||
* an id, or `[*]`; its id in *id; the position after it (i when none). */
|
||||
* an id, or `[*]`; its id in *id; the position after it (i and an empty *id
|
||||
* when none, as for the diagram edge in `A ->: x` or `[-> A: x`). */
|
||||
static size_t dg_puml_operand(dg_str_t s, size_t i, dg_str_t *id, dg_str_t *label) {
|
||||
i = dg_skip_ws(s, i);
|
||||
*id = dg_s(NULL, 0);
|
||||
*label = dg_s(NULL, 0);
|
||||
if (i + CBM_SZ_3 <= s.n && memcmp(s.p + i, "[*]", CBM_SZ_3) == 0) {
|
||||
*id = dg_s(s.p + i, CBM_SZ_3);
|
||||
|
||||
@@ -329,6 +329,36 @@ TEST(diagrams_plantuml) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* #2818: a sequence message to or from the diagram edge (`A ->: x`, `A <-: x`,
|
||||
* `[-> A: x`) and a declaration with an unclosed bracket have no operand id;
|
||||
* they used to read an uninitialized one and crash the index worker. */
|
||||
TEST(diagrams_plantuml_edge_messages) {
|
||||
CBMFileResult *r = dg_file("@startuml\n"
|
||||
"participant Alice\n"
|
||||
"Alice ->: out\n"
|
||||
"Alice <-: in\n"
|
||||
"[-> Alice: from the edge\n"
|
||||
"Alice -> Bob : hello\n"
|
||||
"class [Unclosed\n"
|
||||
"@enduml\n",
|
||||
"docs/edge.puml");
|
||||
ASSERT_NOT_NULL(r);
|
||||
ASSERT_NOT_NULL(dg_def(r, "edge#diagram-1.Alice"));
|
||||
ASSERT_NOT_NULL(dg_def(r, "edge#diagram-1.Bob"));
|
||||
ASSERT_EQ(r->diagram_arrows.count, 1);
|
||||
ASSERT_EQ(dg_arrows(r, "#diagram-1.Alice", "#diagram-1.Bob", "message", "hello"), 1);
|
||||
int elements = 0;
|
||||
for (int i = 0; i < r->defs.count; i++) {
|
||||
const char *label = r->defs.items[i].label;
|
||||
if (label && strcmp(label, "DiagramElement") == 0) {
|
||||
elements++;
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(elements, 2);
|
||||
cbm_free_result(r);
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(diagrams_dot) {
|
||||
CBMFileResult *r =
|
||||
dg_file("digraph G {\n"
|
||||
@@ -1101,6 +1131,7 @@ SUITE(diagrams) {
|
||||
RUN_TEST(diagrams_mermaid_kinds);
|
||||
RUN_TEST(diagrams_other_fences);
|
||||
RUN_TEST(diagrams_plantuml);
|
||||
RUN_TEST(diagrams_plantuml_edge_messages);
|
||||
RUN_TEST(diagrams_dot);
|
||||
RUN_TEST(diagrams_d2);
|
||||
RUN_TEST(diagrams_drawio);
|
||||
|
||||
Reference in new issue
Block a user