Skip to content

Commit 0dc3d67

Browse files
DeusDataSelene29
andcommitted
Fix layout JSON: handle invalid UTF-8 and NaN in serialization
One non-UTF-8 node name crashed the entire /api/layout endpoint (HTTP 500). Force layout can also produce NaN/Inf positions. - Use YYJSON_WRITE_ALLOW_INVALID_UNICODE (matches MCP serializer) - Sanitize NaN/Inf: positions default to 0.0, size to 1.0 - Log yyjson error code on serialization failure Co-Authored-By: Selene29 <Selene29@users.noreply.github.com>
1 parent b2915b4 commit 0dc3d67

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

src/ui/layout3d.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -577,16 +577,20 @@ char *cbm_layout_to_json(const cbm_layout_result_t *r) {
577577
for (int i = 0; i < r->node_count; i++) {
578578
yyjson_mut_val *nd = yyjson_mut_obj(doc);
579579
yyjson_mut_obj_add_int(doc, nd, "id", r->nodes[i].id);
580-
yyjson_mut_obj_add_real(doc, nd, "x", (double)r->nodes[i].x);
581-
yyjson_mut_obj_add_real(doc, nd, "y", (double)r->nodes[i].y);
582-
yyjson_mut_obj_add_real(doc, nd, "z", (double)r->nodes[i].z);
580+
double nx = isfinite(r->nodes[i].x) ? (double)r->nodes[i].x : 0.0;
581+
double ny = isfinite(r->nodes[i].y) ? (double)r->nodes[i].y : 0.0;
582+
double nz = isfinite(r->nodes[i].z) ? (double)r->nodes[i].z : 0.0;
583+
yyjson_mut_obj_add_real(doc, nd, "x", nx);
584+
yyjson_mut_obj_add_real(doc, nd, "y", ny);
585+
yyjson_mut_obj_add_real(doc, nd, "z", nz);
583586
if (r->nodes[i].label)
584587
yyjson_mut_obj_add_str(doc, nd, "label", r->nodes[i].label);
585588
if (r->nodes[i].name)
586589
yyjson_mut_obj_add_str(doc, nd, "name", r->nodes[i].name);
587590
if (r->nodes[i].file_path)
588591
yyjson_mut_obj_add_str(doc, nd, "file_path", r->nodes[i].file_path);
589-
yyjson_mut_obj_add_real(doc, nd, "size", (double)r->nodes[i].size);
592+
double nsz = isfinite(r->nodes[i].size) ? (double)r->nodes[i].size : 1.0;
593+
yyjson_mut_obj_add_real(doc, nd, "size", nsz);
590594
char hex[CBM_SZ_8];
591595
snprintf(hex, sizeof(hex), "#%06x", r->nodes[i].color);
592596
yyjson_mut_obj_add_strcpy(doc, nd, "color", hex);
@@ -607,7 +611,15 @@ char *cbm_layout_to_json(const cbm_layout_result_t *r) {
607611
yyjson_mut_obj_add_int(doc, root, "total_nodes", r->total_nodes);
608612

609613
size_t len = 0;
610-
char *json = yyjson_mut_write(doc, 0, &len);
614+
yyjson_write_err write_err = {0};
615+
char *json =
616+
yyjson_mut_write_opts(doc, YYJSON_WRITE_ALLOW_INVALID_UNICODE, NULL, &len, &write_err);
611617
yyjson_mut_doc_free(doc);
618+
if (!json) {
619+
char code[CBM_SZ_32];
620+
snprintf(code, sizeof(code), "%u", write_err.code);
621+
cbm_log_error("layout.json.fail", "code", code, "msg",
622+
write_err.msg ? write_err.msg : "unknown");
623+
}
612624
return json;
613625
}

0 commit comments

Comments
 (0)