Skip to content

[rustjava-next-slice-and-stale-next-pointer] fix(rustjava-runtime): EUC-KR 쌍이 readBuf 경계를 넘어가게 한다 — 그리고 ## 다음 을 전수 재측했다 - #90

Merged
Jun025 merged 1 commit into
mainfrom
feat/rustjava-next-slice-euckr-boundary
Sep 23, 2026
Merged

Jun025 merged 1 commit into
mainfrom
feat/rustjava-next-slice-euckr-boundary

Conversation

@Jun025

@Jun025 Jun025 commented Sep 23, 2026

Copy link
Copy Markdown
Owner

무엇을

LANE_IDLE rustjava(2026-09-23 · 1088분 조용 · 큐 0 · running 0)에 대한 회차. 오라클 판정은
「워커는 멀쩡하고 일이 안 들어온다 ⇒ 처방은 워커 증설이 아니라 발권」이었고, 발권이 멈춘 이유는
STATE.md ## 다음 의 최우선 항목이 이미 끝난 일을 가리켰기 때문이다.

★이 절이 그 병을 스스로 두 번 기록해 놓고 세 번째를 냈다 — 2026-09-11 에 「다음 실작업 = ③의
null-guard」로 고쳐 쓴 그 null-guard 가 같은 날 이미 닫혀 있었다(6da7d66f).

## 다음 전수 재측 — 8건 중 7건이 닫혀 있었다

전건 git merge-base --is-ancestor <sha> origin/main(★워킹트리 grep 미사용 · gh 는 전건 -R Jun025/RustJava):

「다음」이라 부르던 것 닫은 커밋 판정
① 꼬리 「다음 실작업 = ③의 null-guard」 6da7d66f 닫힘
② wie-ktf-hardening 잔존 2건 6da7d66f 닫힘
③-1 upstream-sync-s5…s8 / ③-2 null-guard (전건 착지) / 6da7d66f 닫힘
④-1 ⒝ 「makeConcat 남음」 e94cfe91 닫힘
④-1 ⒝ 「LambdaMetafactory 런타임 남음」 8c7b473f 닫힘
④-2 「남는 대역 = 1 · LdcDynamicNoBSM」 d9f45ebf 닫힘
④-3 InputStreamReader 디코더 경계 — ★열림

⇒ 새 ⓪살아 있는 후보 블록을 맨 위에 두고 ①~⑤ 를 사료로 접었다(지우지 않고 접었다).

고친 것 — EUC-KR 이 readBuf 경계에서 글자를 잃었다

사료는 「완화책이 ①의 머지로 들어오니 다시 재라」고 남겼다. 재 보니 들어오긴 했는데
두 멀티바이트 charset 중 하나만 옳았다.

UTF-8 역주사는 연속 바이트(0x80..=0xbf)가 선두와 서로소라 성립한다. EUC-KR 판은
「마지막 바이트 ≥ 0x81 이면 한 바이트 보류」였고, ★EUC-KR 후행 바이트는 선두 범위(0x81..=0xfe)와 겹친다
⇒ 완성된 쌍의 후행도 보류돼 그 쌍의 선두가 홀로 남고, read() 마다 새로 만드는
CharsetStreamDecoder 가 그 선두를 자기 상태로 삼킨 채 버려졌다.

실측: "12345678한"(EUC-KR 10바이트) → ★**"12345678\u{FFFD}"**.
처방 = 전방 주사(선두면 2, 아니면 1) · 6줄.

개악 대조쌍 — 3종 전건 red

개악 결과
M1 종전 술어(last() >= 0x81) 복원 red — left: "12345678\u{FFFD}"
M2 EUC-KR 보류 가지 통째 제거 red — left: "123456789" ★다른 실패 모양(소실)
M3 UTF-8 역주사 무력화 ★형제 2건 red · 새 테스트는 green

★M3 이 가장 값비싼 한 줄이다 — ⒜UTF-8 축은 형제 테스트로 이미 잠겨 있었고(사료가 절반은 참)
⒝새 테스트가 그 형제의 중복이 아니라 독립 프로브임을 동시에 말한다.
★green 을 보존의 증거로 읽지 않았다는 근거가 이것이다.

복원 후 8/8 green. 테스트는 3형상(경계 딱 맞음 / 진짜 갈림 / 두 쌍 걸침)으로 잠갔다 —
「한 바이트 보류가 우연히 맞는」 경우를 배제한다.

고치지 않은 것 / 안 만든 것

  • 「read() 마다 디코더를 새로 만든다」는 구조는 그대로다 — encoding_rs::Decoder 를 자바 필드에
    담을 수 없어 «보류 휴리스틱»이 설계다. ⇒ ★다섯째 멀티바이트 charset 을 더하면 되살아난다(후속 카드).
  • ★기계 강제는 계산해 보고 기각했다: 「## 다음 이 ## 완료 의 id 를 가리키면 red」는 13개 중
    9개가 걸리는데 대부분이 「해소됨·발권하지 마라」라고 «옳게» 적힌 주석이다 ⇒ 오탐이 지배적이다.
    AGENTS.md 의 워크로그 부재 판정과 같은 결론 — 못 재는 것을 재는 척하지 않는다.

검증

DoD 10명령 전건 rc=0(+beta·wasm32 포함) · cargo test --all 592 passed / 0 failed / 1 ignored.
check-dod-ci-parity.py → 「명령 9개 · toolchain 2개로 «둘 다 일치»」.

상세 = docs/worklog/2026-09-23-stale-next-pointer-and-euc-kr-boundary.{md,json}.

🤖 Generated with Claude Code

…UC-KR 쌍이 readBuf 경계를 넘어가게 한다 — 그리고 `## 다음` 을 전수 재측했다

`LANE_IDLE rustjava`(1088분)의 근인은 워커가 아니라 발권이었고, 발권이 멈춘 이유는
`STATE.md` `## 다음` 의 최우선 항목이 이미 끝난 일을 가리켰기 때문이다(세 번째 재발).

8개 후보를 `git merge-base --is-ancestor` 로 전수 재측해 7건이 닫혀 있음을 확인하고
사료로 접었다. 유일하게 열려 있던 ④-3(InputStreamReader 디코더 경계)이 실제 결함이었다.

EUC-KR 보류 술어가 「마지막 바이트 >= 0x81 이면 한 바이트 보류」였는데, EUC-KR 후행
바이트는 선두 범위(0x81..=0xfe)와 겹친다 ⇒ 완성된 쌍의 후행도 보류돼 그 쌍의 선두가
홀로 남고, read() 마다 새로 만드는 디코더가 그 선두를 자기 상태로 삼킨 채 버려졌다.
실측 "12345678한" → "12345678\u{FFFD}". 전방 주사(선두면 2, 아니면 1)로 고쳤다.

개악 3종 전건 red: M1 종전 술어 복원 → U+FFFD · M2 보류 가지 제거 → 글자 소실 ·
M3 UTF-8 역주사 무력화 → 형제 2건 red 이고 새 테스트는 green(독립 프로브임의 증거).
DoD 10명령 rc=0 · cargo test --all 592 passed / 0 failed / 1 ignored.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Jun025
Jun025 merged commit c654ae2 into main Sep 23, 2026
13 checks passed
@Jun025
Jun025 deleted the feat/rustjava-next-slice-euckr-boundary branch September 23, 2026 06:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant