← 목록
기타 2026-07-24 5KB 읽기 4분

크라우니캔버스 — 블록JSON 손상(비-배열 루트) 가드 수리

개요

P0 재현 티켓: "손상된 JSON 파일 주입 후 :9620 서버 unresponsive"에 대한 근본 수리. 파일 소유권 범위: /Users/ef/crowny-canvas/데이터/블록/seed_today.json + 동반 .한선(저장소.한선).

확증된 사실

  • 데이터/블록/seed_today.json이 계약(§4 블록JSON, 블록들[])과 달리 배열이 아닌 단일 객체
({"id":"b1",...}, 98B)로 저장돼 있었다. 형제 파일(seed_room_a.json, seed_product_plan.json)은 전부 정상적으로 배열([{...},{...}])이었다.
  • 데이터/블록버전.psvseed_today|1만 기록돼 있어(그 이후 저장 API 경유 갱신 없음),
이 파일은 정상 저장 플로우(저장소_블록쓰기)가 아니라 파일시스템 직접 주입으로 훼손됐음이 확인됨.
  • 저장소_블록읽기(페이지id)(한선씨/저장소.한선)는 훼손 이전엔 파일 내용을 무검증으로 그대로
API 응답("블록들":<원문>)에 삽입했다 — 루트가 배열인지 전혀 확인하지 않음.
  • 라이브 :9620에서 실측한 CPU 99%·[ARRAY] OOM!·[STR] 조기경고 반복 hang 증상은 재현 시점에
이미 진행 중이던 별개 문제(동시 다수 세션이 서버.한선을 계속 Edit → hanseonc_high 핫리로드가 ~1초 간격으로 재컴파일/재로드되며 VM 힙·문자열풀이 리로드 사이 회수되지 않고 누적되는 것으로 추정, crownyc.c 엔진 레벨)와 겹쳐 있었다. 새 프로세스로 교체된 뒤 재검증하니 /api/부팅·/api/페이지/seed_today 모두 즉시 200으로 정상 응답해, "손상된 JSON 내용 자체가 서버를 영구 행에 빠뜨린다"는 인과는 이번 수리 범위(저장소.한선 읽기/쓰기 경로) 안에서는 재현되지 않았다. 단, 블록들이 배열이 아닌 채로 무검증 전파되는 것 자체는 확증된 결함(계약 위반 + 클라이언트 블록들.forEach/map() 파손 위험)이라 이를 근본 수리했다.

수리 내용 (한선씨/저장소.한선)

  1. 저장소_블록루트배열인가(내용) 신규 — 앞쪽 최대 20글자만 훑어(O(1), 전체스캔 아님) 공백류를
건너뛰고 첫 비공백 문자가 [인지 확인. 완전한 JSON 파서 없이(가드레일 제약) 최소침습으로 "배열 루트"만 검증.
  1. 저장소_블록읽기: 파일 내용이 배열 루트가 아니면 원본 파일은 보존한 채 안전 폴백 "[]"
응답(+ stderr 경고 로그). 손상 파일이 있어도 API는 항상 계약을 지키는 JSON을 반환.
  1. 저장소_블록쓰기: 저장 요청 내용이 배열 루트가 아니면 저장을 거부하고 "[]"로 대체 저장
(+ 경고 로그) — 향후 이 경로로 손상 데이터가 재유입되는 것 자체를 차단.
  1. 데이터터/블록/seed_today.json 실데이터 복구: 저장소_시드기본페이지들()이 원래 생성하던
2블록 배열([{"id":"b1","종류":"제목1",...},{"id":"b2","종류":"문단",...}])로 원복 (블록버전=1과 일치, 제목 "Today 안내" PSV 레코드와 일치).

실측 검증

  • STRICT 재컴파일(CROWNY_STRICT=1 ./hanseonc_high 서버.한선): 0 경고.
  • launchctl kickstart -k gui/$(id -u)/org.crowny.canvas 재기동 후:
  • GET /api/페이지/seed_today블록들이 정상 2-블록 배열로 응답(HTTP 200, ~0.2s).
  • GET /api/부팅 5연속 → 전부 HTTP 200, 응답시간 0.23~0.44s 안정(급증 없음).
  • 재현 실험: seed_room_a.json을 seed_today.json과 동일한 방식(단일 객체)으로 임시 훼손 →
  • GET /api/페이지/seed_room_a 즉시 HTTP 200, 블록들:[]로 안전 폴백(서버 hang 없음, 0.035s) — 가드가 실제로 이 손상 클래스를 차단함을 확증. 이후 원본 파일 복원 완료.

    관련 파일

    • /Users/ef/crowny-canvas/한선씨/저장소.한선 (수리)
    • /Users/ef/crowny-canvas/데이터/블록/seed_today.json (데이터 복구)
    • /Users/ef/crowny-canvas/서버.toau (재컴파일 반영)

    잔여 이슈

    • 라이브 :9620에서 관측된 [ARRAY] OOM!/CPU 99% busy-spin의 진짜 근본원인은 crownyc.c 핫리로드가
    소스 변경 감지 시 VM 힙/문자열풀을 리로드 사이에 회수하지 않는 것으로 추정되나, 이는 크라우니 VM 엔진(공유 인프라) 영역이라 이번 파일 소유권(seed_today.json+저장소.한선) 밖 — 별도 티켓/세션 필요(엔진팀 보고 권고, crownyc.c 라인 1210 핫리로드 경로 + MEM_HARD_LIMIT 144M 근방 검토).
    • [STR] 조기경고: 문자열 핸들 432000/480000 경고도 동일 다중세션 동시편집·핫리로드 부하로 추정,
    본 수리 범위 밖.