Skip to content

Commit 78a2811

Browse files
jun0claude
andcommitted
[rustjava-next-slice-and-stale-next-pointer] fix(rustjava-runtime): EUC-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>
1 parent 1ec83a1 commit 78a2811

6 files changed

Lines changed: 385 additions & 7 deletions

File tree

‎REPORT.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
11
# REPORT
2+
## [2026-09-23] `## 다음` 이 세 번째로 낡았고, 그 밑에서 EUC-KR 한 글자가 조용히 사라지고 있었다 (rustjava-next-slice-and-stale-next-pointer)
3+
- 무엇을: `STATE.md` `## 다음` 의 모든 「다음 후보」를 `git merge-base --is-ancestor` 로 **전수 재측**해 **8건 중 7건이 이미 닫혀 있음**을 확인하고 사료로 접었으며, 살아 있는 후보만 새 `⓪` 블록에 올렸다. 재측 과정에서 유일하게 «열려 있던» 항목(④-3 `InputStreamReader` 디코더)이 실제 결함임이 드러나 **그 자리에서 고쳤다**.
4+
- 왜: `LANE_IDLE rustjava`(2026-09-23 · ★**1088분** 조용 · 큐 0 · running 0). 근인은 워커가 아니라 **발권**이었고, 발권이 멈춘 이유는 `## 다음` 의 최우선 항목이 **이미 끝난 일**을 가리켰기 때문이다. ★**이 절이 그 병을 스스로 두 번 기록해 놓고 세 번째를 냈다** — 2026-09-11 에 「다음 실작업 = ③의 null-guard」로 고쳐 쓴 그 null-guard 가 **같은 날 이미 닫혀 있었다**(`6da7d66f`).
5+
- 사용자 영향: ★**EUC-KR 로 읽는 파일에서 문자가 사라지던 것이 멈춘다.** `new InputStreamReader(in)` 가 `file.encoding=EUC-KR` 에서 10바이트 읽기 경계에 걸린 한글을 `\u{FFFD}` 로 바꾸거나 **통째로 버렸다**. 실측 `"12345678한"` → ★`"12345678\u{FFFD}"`. 이제 원문 그대로다.
6+
- ★★**근인 — 「완화책이 들어왔다」와 「완화책이 옳다」는 다른 문장이다.** 사료는 upstream 완화책이 ①의 머지로 들어온다고 적고 「다시 재라」고 남겼다. 들어오긴 했는데 **두 멀티바이트 charset 중 하나만 옳았다**: UTF-8 역주사는 연속 바이트(`0x80..=0xbf`)가 선두 바이트와 **서로소**라 성립하는데, EUC-KR 판은 「마지막 바이트 ≥ 0x81 이면 한 바이트 보류」였고 ★**EUC-KR 후행 바이트는 선두 범위(`0x81..=0xfe`)와 겹친다** ⇒ **완성된 쌍**의 후행도 보류돼 그 쌍의 선두가 홀로 남고, `read()` 마다 새로 만드는 `CharsetStreamDecoder` 가 그 선두를 **자기 상태로 삼킨 채 버려졌다**. 처방 = 전방 주사(선두면 2, 아니면 1 · **6줄**).
7+
- ★**개악 대조쌍 3종 전건 red**: **M1** 종전 술어로 되돌림 → `left: "12345678\u{FFFD}"` · **M2** 보류 가지 통째 제거 → `left: "123456789"`(★**다른 실패 모양** — 이번엔 대체문자가 아니라 **소실**) · **M3** UTF-8 역주사 무력화 → ★**형제 테스트 2건이 red 이고 내 테스트는 green**(= 새 테스트가 EUC-KR 축의 독립 프로브이지 형제의 중복이 아니라는 증거). 복원 후 8/8 green.
8+
- ★**고치지 «않은» 것**: 「`read()` 마다 디코더를 새로 만든다」는 구조는 그대로다 — `encoding_rs::Decoder` 를 자바 필드에 담을 수 없어 **보류 휴리스틱이 설계**다. ⇒ ★**다섯째 charset 을 더하면 이 함정이 되살아난다**(후속 카드).
9+
- ★**기계 강제는 «안 만들었다»**: 「`## 다음` 이 `## 완료` 에 있는 id 를 가리키면 red」를 실제로 계산해 보니 지금 13개 중 **9개가 걸리는데 그중 대부분이 «해소됨·발권하지 마라»라고 «옳게» 적힌 주석**이었다 ⇒ 오탐이 지배적이라 검사기로 세울 수 없다. `AGENTS.md` 의 워크로그 부재 판정과 같은 결론(문서에만 두는 것이 가장 나쁘지만, 못 재는 것을 재는 척하는 것은 더 나쁘다).
10+
- 검증: DoD 10명령 rc 0. 상세 = `docs/worklog/2026-09-23-stale-next-pointer-and-euc-kr-boundary.{md,json}`.
11+
212
## [2026-09-21] 추천 후속작업 **2건 기각** — 보드에서 내리되 기록에서 내리지 않는다 (rustjava-prune-declined-followup-proposals-2026-09-21)
313
- 무엇을: 운영자 지시(2026-09-21 「우선순위 낮은 작업은 추천 목록에서 정리하라」)에 따라 이 repo 의 열린 제안 **4건 중 2건**을 `declinedProposals` 로 닫았다. ★**제품 코드 0줄 · 새 제안 0 · 검사기/CI 신설 0.**
414
- ★**닫은 둘**(둘 다 **검사기 다듬기**이고 사용자가 닿는 결함이 아니다): `2026-09-19-nonliteral-blind-spot-is-reported-not-gated#p0`(예외 이름 보고의 제품/테스트 구분) · `2026-09-20-lock-script-output-order#p0`(출력순서 잠금의 튜플 언패킹 구멍). ★**남긴 둘**(런타임 축): `2026-09-20-string-array-hiding-overflows-stack#p0` · `2026-09-20-name-the-missing-bootstrap-class#p0`.

‎STATE.md‎

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,6 +1510,52 @@
15101510

15111511
## 다음
15121512

1513+
### ⓪살아 있는 후보 — ★★**[2026-09-23 전수 재측] 이 블록«만» 읽어라. ①~⑤ 는 사료다.**
1514+
1515+
★★★**이 절이 자기 규율(「닫히는 즉시 닫아라」)을 «세 번» 어겼다** — ⑴③-0 `…claude-md-prune-disposition`(2026-08-27 해소)이
1516+
최우선에 남아 레인이 조용해졌고 ⑵①의 「다음은 S5」가 8일 낡은 채 남아 2026-09-11 **중복 발권**을 만들었고
1517+
⑶그 자리를 고치며 ①의 꼬리를 「다음 실작업 = ③의 null-guard」로 바꿨는데 **그 null-guard 는 같은 날 이미 닫혀 있었다**
1518+
⇒ ★**`LANE_IDLE rustjava` 1088분**(2026-09-23 13:41 · 큐 0 · running 0). ★**네 번째를 만들지 마라 — 닫으면 그 턴에 여기서 지워라.**
1519+
1520+
★**닫힌 것을 «측정»으로 확인했다**(`git merge-base --is-ancestor <sha> origin/main` · 전건 ANCESTOR):
1521+
1522+
| ①~⑤ 가 「다음」이라 부르던 것 | 닫은 커밋 | 판정 |
1523+
|---|---|---|
1524+
| ① 꼬리 「다음 실작업 = ③의 null-guard」 | `6da7d66f` | ★**닫힘** — 지목 자체가 낡았다 |
1525+
| ② `wie-ktf-hardening` 잔존 2건(`arraycopy`·`String.<init>`) | `6da7d66f` | ★**전건 닫힘** — 유효 잔존 **0** |
1526+
| ③-1 `rustjava-upstream-sync-s5…s8` | (S5~S8 전건 착지) | 닫힘 |
1527+
| ③-2 `rustjava-null-guard-string-init-and-arraycopy` | `6da7d66f` | 닫힘 |
1528+
| ③-3 / ④-1 ⒝ 의 「`makeConcat` 남음」 | `e94cfe91`(#60 리니지) | ★**닫힘** — `jvm-bytecode/src/string_concat.rs` 의 `FACTORY_NAME_NO_RECIPE` |
1529+
| ④-1 ⒝ 의 「`LambdaMetafactory` 런타임 남음」 | `8c7b473f` | ★**닫힘** — `jvm-bytecode/src/lambda.rs` · `Opcode::InvokedynamicLambda` |
1530+
| ④-2 의 「★남는 대역 = 1 · `LdcDynamicNoBSM`」 | `d9f45ebf` | ★**닫힘** — `validation.rs` 의 `bootstrap_method_indices_resolve` |
1531+
| ④-3 `InputStreamReader` 디코더 경계 | 아래 참조 | ★**절반이 틀렸다** — 사료의 「완화책은 ①로 들어온다」는 **들어왔고**(필드 `endOfInput` 실재), 그러나 EUC-KR 축은 **깨진 채**였다 |
1532+
1533+
★**열려 있음을 «근거와 함께» 적는다**(「PR 제목·개설일만 보고 썼다가 둘 다 틀린」 선례가 이 레인에 있다):
1534+
1535+
1. ★★**`java.lang.invoke` 패키지 — 여전히 «0»**(④-1 ⒝ 의 «마지막» 칸).
1536+
근거 = `ls rustjava-runtime/src/classes/java/lang/` 에 `invoke` **부재**(디렉터리 0 · 파일 0).
1537+
⇒ 링크는 **콜사이트를 opcode 로 내려써서** 돌고 있고(`string_concat.rs`·`lambda.rs`), `MethodHandle`/`MethodType`/`CallSite`
1538+
**객체**는 아직 만들 수 없다. 열린 카드가 그 축에 셋 붙어 있다 —
1539+
`2026-09-17-link-lambdametafactory#p0`(M · 어댑터를 박싱부터 넓혀라) · `#p1`(S · 람다 클래스를 리플렉션에 보일지 «결정») ·
1540+
`2026-09-17-string-concat-recipe-arity#p1`(S · **선행 = `java.lang.invoke` 실재**).
1541+
★**순서는 `#p1`(결정) → `#p0`(어댑터) → 패키지** — 결정이 패키지의 크기를 정한다.
1542+
2. `2026-09-18-bootstrap-argument-index-and-tag#p0`(S) — 직전 착지 `1ec83a14`(#73)의 승계. 「이미 손에 든 수를 버리는」
1543+
나머지 `validation.rs` 규칙을 **센다**. ★계수 회차라 위험 0 이고 다음 진단 회차의 크기를 정한다.
1544+
3. `2026-09-12-zip-getinputstream-guard-lock#p0`(S) · `2026-09-12-test-class-scratch-premise#p0`(M) — 런타임/테스트 축.
1545+
이 둘은 ①~⑤ 어디에도 적혀 있지 않았다 ⇒ ★**「다음」의 정본은 이 절이 아니라 `docs/worklog/*.json` 의 열린 카드**임을 적어 둔다
1546+
(2026-09-23 실측 **열린 카드 30건** · 그중 upstream 캠페인·형제 repo(wie·qts) 것이 **11건**이라 이 레인이 칠 수 있는 것은 그보다 적다).
1547+
4. ★**게이트③ 미착지 1건**: PR **#81**(`feat/rustjava-sorted-findings`) — ★`mergeable=CONFLICTING`·`mergeStateStatus=DIRTY`
1548+
(2026-09-23 워밍 후 재조회). 충돌 해소가 선행이다. ★**열린 PR 은 이 1건뿐**이다(⑤의 표는 낡았다).
1549+
1550+
★**④-3 은 이 회차가 닫았다** — `InputStreamReader` 의 EUC-KR 경계. 사료는 「디코더를 read 마다 새로 만든다 = 경계 유실」이라고만
1551+
적고 「①로 완화책이 들어오니 다시 재라」고 남겼는데, **재 보니 완화책은 두 축 중 «하나»만 옳았다**:
1552+
UTF-8 은 역주사(연속 바이트 `0x80..=0xbf` 가 선두 바이트와 **서로소**라 성립)로 옳고 테스트로도 잠겨 있었는데,
1553+
EUC-KR 은 「마지막 바이트 >= 0x81 이면 한 바이트 보류」였다 — ★**EUC-KR 의 후행 바이트는 선두 범위(`0x81..=0xfe`)와 «겹친다»**
1554+
⇒ **완성된 쌍**의 후행 바이트도 보류돼 그 쌍의 선두 바이트가 홀로 남고, 매 read 마다 새로 만드는 디코더가 그것을 **자기 상태로 삼켜** 버렸다.
1555+
실측 = `"12345678한"`(EUC-KR 10바이트) → ★**`"12345678\u{FFFD}"`**. 처방은 전방 주사(선두면 2, 아니면 1)이고 테스트 3형상으로 잠갔다.
1556+
1557+
---- 이하 ①~⑤ 는 사료다. ★**「다음」으로 읽지 마라** ----
1558+
15131559
### ①(최우선이 «아니게 됐다») upstream 동기화 — ★★**[2026-09-11 갱신] 캠페인 «종료». 동기 회차를 열지 마라.**
15141560

15151561
★실측(2026-09-11): **S5(#21)·S6(#22)·S7(#23)·S8(#24) 전건 `--merge` 착지** · `merge-base origin/main
@@ -1518,7 +1564,9 @@ upstream/main` = **`bd42427`** · behind **1**(`2ce4717` · dependabot encoding_
15181564
주 1회 `.github/workflows/upstream-behind.yml`(PR #31)이고, **기계가 재고 사람(총괄)이 발권한다**.
15191565
★★**구판 「다음은 S5」는 8일 낡은 채 이 절에 남아 2026-09-11 중복 발권**(`rustjava-upstream-sync-s5-java12-api` ·
15201566
blocked)**을 만들었다** — ③ 절 「이미 끝난 일을 가리키면 레인이 조용해진다 · 닫히는 즉시 닫아라」의 두 번째 재현.
1521-
⇒ ★**다음 실작업 = ③의 null-guard 티켓**(①의 뒤라는 선행 조건이 이제 충족됐다).
1567+
~~⇒ ★**다음 실작업 = ③의 null-guard 티켓**(①의 뒤라는 선행 조건이 이제 충족됐다).~~
1568+
★★**[2026-09-23 닫음] 그 지목은 «쓰인 날 이미 낡아 있었다»** — ③-2 는 같은 2026-09-11 에 `…-p0` 로 닫혔다(`6da7d66f`).
1569+
★**이 한 줄이 세 번째 재발이고 `LANE_IDLE` 1088분의 근인이다.** 살아 있는 후보는 ⓪ 블록에 있다.
15221570

15231571
---- 이하 사료(S4 회차 실측 · 타이머 여백 근거 — 단정 불변이라 보존) ----
15241572

@@ -1558,7 +1606,11 @@ green 전건 rc=0 · `cargo test --all` **261 passed / 0 failed / 1 ignored**(S3
15581606
해소 전략은 불변이다:
15591607
**upstream 본문을 뼈대로 취하고 `#[tracing::instrument]` 한 줄만 PR #4 의 수동 span 으로 치환**한다.
15601608

1561-
### ②`wie-ktf-hardening` 잔존분 — 2026-08-15 재판정으로 **4건 → 2건**
1609+
### ②`wie-ktf-hardening` 잔존분 — ★★**[2026-09-23 닫음] 2건 → «0». 이 절 전체가 사료다.**
1610+
★아래 표의 「유효 잔존」 두 행(`System.arraycopy` null 가드 · `String.<init>` null 가드)은 **둘 다 `6da7d66f` 로 닫혔고**
1611+
그 사실이 표 안에 이미 적혀 있었는데 ★**절 제목만 「2건」으로 남아** 다음 사람이 잔존이 있다고 읽게 돼 있었다.
1612+
⇒ ★**제목과 본문이 어긋나면 제목을 고쳐라** — 본문만 고치면 목차만 보는 다음 회차가 속는다.
1613+
---- 이하 사료(2026-08-15 재판정 당시 기재) ----
15621614
★**선행 확인 종결**: upstream `agent/runtime-api-gaps`(`6309d47`)는 **미머지가 아니다** —
15631615
**PR #190 로 2026-07-25 04:59Z 스쿼시 머지**(머지커밋 `c4665b0`, +33,109/−1,040)됐고
15641616
그래서 브랜치가 upstream 에서 **삭제**됐다. 즉 「삼키는지」는 이제 **upstream/main 에 직접 묻는다**.
@@ -1599,7 +1651,7 @@ green 전건 rc=0 · `cargo test --all` **261 passed / 0 failed / 1 ignored**(S3
15991651
⇒ ★**가드가 «짝이 안 맞는» 것이 핵심이다**: `([CII)`·`(II[C)` 만 막혀 있고 `[B` 계열은 전부 뚫려 있다.
16001652
※**전역 수리는 불가** — `Deref` 는 `Result` 를 못 돌려준다. upstream 방식(진입부 `is_null()` 가드)이 정답이다.
16011653

1602-
### ③다음 회차 발권 후보(우선순위 순)
1654+
### ③~~다음 회차 발권 후보(우선순위 순)~~ → ★★**[2026-09-23] 1·2·3 «전건 해소». 발권 후보 «0» — 사료다.**
16031655

16041656
★★**0번 항목(`rustjava-pr8-claude-md-prune-disposition`)은 «해소됨» — 2026-08-27 S3 회차가 닫았다.**
16051657
구판은 「`reports/rustjava-claude-md-prune.review.md` 가 **없다** ⇒ 게이트②가 아예 돌지 않고 좌초」를
@@ -1672,7 +1724,10 @@ green 전건 rc=0 · `cargo test --all` **261 passed / 0 failed / 1 ignored**(S3
16721724
`LambdaMetafactory.metafactory` 의 인자는 **MethodType·MethodHandle·MethodType** 이라 해석을 강제하면
16731725
★**람다가 든 모든 클래스가 «파싱»에서 죽어 `ClassFormatError: Invalid class file` 로 되돌아간다**
16741726
(= 직전 두 회차가 만든 「파손 ↔ 미지원」 구분을 그대로 잃는다). ⇒ **`test-data/indy/Lambda.class` 가 그 축을 «두 층»에서 문다.**
1675-
★**미착수(= ⒝)**: ★**[2026-09-16 «한 칸» 닫힘 · `rustjava-link-stringconcatfactory-makeconcatwithconstants`] `makeConcatWithConstants` 는 링크됐다**(정의 시점 내려쓰기 · `java.lang.invoke` 0줄) — 남은 것은 `makeConcat` · `LambdaMetafactory` 런타임 · `java.lang.invoke` 패키지 신설.
1727+
~~★**미착수(= ⒝)**: `makeConcatWithConstants` 는 링크됐다 — 남은 것은 `makeConcat` · `LambdaMetafactory` 런타임 · `java.lang.invoke` 패키지 신설.~~
1728+
★★**[2026-09-23 재측] 셋 중 «둘이 닫혔다»** — `makeConcat` = `string_concat.rs` 의 `FACTORY_NAME_NO_RECIPE`(`e94cfe91` 리니지) ·
1729+
`LambdaMetafactory` = `jvm-bytecode/src/lambda.rs` + `Opcode::InvokedynamicLambda`(`8c7b473f`).
1730+
★**남은 것은 `java.lang.invoke` 패키지 «하나»다**(실측: `rustjava-runtime/src/classes/java/lang/` 에 `invoke` 부재) ⇒ ⓪-1 로 옮겼다.
16761731
★★**착수 전 실측 의무 — «그대로 유효»하다**: `verifier.rs` 의 `Opcode::Invokedynamic(_)` 분기를 **언제 뺄지**가 그 회차의 게이트다.
16771732
그것을 빼면 `interpreter.rs:631` 의 `todo!()` 가 **도달 가능해진다** — ★**2026-09-16 에 «두 번» 측정됐다**
16781733
(태그 회차 M4 · 이 회차 M4: 분기 제거 시 `panicked at jvm-bytecode/src/interpreter.rs:631` **호스트 abort** ↔ 현 트리는 게스트 예외).
@@ -1695,12 +1750,23 @@ green 전건 rc=0 · `cargo test --all` **261 passed / 0 failed / 1 ignored**(S3
16951750
(major 50 에서 `ldc of a method handle`/`method type` ↔ 참조 JVM 은 `Class file version does not support constant tag 15/16`).
16961751
⇒ 표 = **15·16·18 ≥ 51 · 17 ≥ 55**(JVMS 4.4). ★**대가 «0»**: OpenJDK 26 jmods **27,902 클래스 중 위반 0**
16971752
(★단 그 corpus 는 전부 major 69·70 이라 ≥51 행을 «시험하지 못한다» — 숨기지 않는다) · 이 repo `test-data` 위반은 **이 회차가 만든 픽스처 1건뿐**.
1753+
★★**[2026-09-23 닫음] 아래 「남는 대역 = «1»」은 «0» 이다** — `d9f45ebf`(`rustjava-bound-bootstrap-method-attr-index`)의
1754+
`validation.rs::bootstrap_method_indices_resolve` 가 **「속성 부재 = 0항목 표」**로 그 칸을 함께 물었다(그 회차 worklog 의 표 ⒞행이 `rejected`).
1755+
★**그 회차가 닫았는데 이 절이 안 지워졌다** — ⓪ 블록의 「세 번 어겼다」와 **같은 계급**이다.
1756+
---- 이하 사료 ----
16981757
★★**남는 대역 = «1»**: **`LdcDynamicNoBSM`**(`bootstrap_method_attr_index` 가 가리키는 `BootstrapMethods` 가 **없다**) —
16991758
참조 JVM 은 `Missing BootstrapMethods attribute` 인데 우리는 **여전히 「미지원」**이다.
17001759
★그 경계 검사는 **속성 파싱이 정말로 필요**하므로 ④-1(PR #45 리니지) 몫이다 — ★**픽스처와 테스트로 «현재 답»을 잠가 뒀으니
17011760
그 회차가 닫으면 그 단언이 «시끄럽게» 진다.**
17021761
★**남긴 것 둘 더**: ⑵★**M5 층 어긋남**: ★**[2026-09-16 닫힘 · `rustjava-cp-tag-switch-passthrough-mutation-detectable`] 이제 `test_class_format` 이 «잡는다»**(픽스처를 «유일한 결함»으로 다시 지었다 — 종전엔 참조되는 Methodref 슬롯을 덮어 «다른 이유»로 통과했다) ⑶서드파티 생성기 corpus **미측정**(이 머신에 jar 0개).
1703-
3. ★InputStreamReader 디코더 — 아래 사료 절 셋째 항목 그대로 **살아 있다**(별건).
1762+
3. ~~★InputStreamReader 디코더 — 아래 사료 절 셋째 항목 그대로 **살아 있다**(별건).~~
1763+
★★**[2026-09-23 닫음] 「그대로 살아 있다」는 절반만 참이었다 — 재 보니 두 축 중 «하나»만 깨져 있었다.**
1764+
사료가 요구한 「① 이후 상태를 다시 재라」를 실제로 했다: 완화책은 **들어왔다**(필드 `endOfInput` 실재 · UTF-8 역주사 실재 ·
1765+
그 축은 `test_input_stream_reader_preserves_split_multibyte_and_buffered_eof` 로 **이미 잠겨 있었다**).
1766+
★**깨져 있던 것은 EUC-KR 축**이고 ★**테스트가 0건이라 아무도 몰랐다**. 근인 = 「마지막 바이트 >= 0x81 이면 보류」인데
1767+
EUC-KR 후행 바이트는 선두 범위와 **겹쳐서** 완성된 쌍도 보류돼 그 선두가 홀로 남고, read 마다 새로 만드는 디코더가 그것을 삼켰다.
1768+
⇒ 전방 주사로 고치고 3형상을 잠갔다(이 회차). ★**「디코더를 read 마다 새로 만든다」는 구조 자체는 그대로다** —
1769+
`encoding_rs::Decoder` 를 자바 필드에 담을 수 없어 «보류 휴리스틱»이 설계다. ★**그래서 다섯째 charset 을 더하면 이 함정이 되살아난다**(⓪ 아래 빚).
17041770

17051771
---- 이하 사료(2026-08-16 기재 · 크레이트 경로·태그 서술은 낡았다) ----
17061772
- ★`jvm_rust/src/interpreter.rs` `Opcode::Invokedynamic(_) => todo!()` 는
@@ -1730,6 +1796,11 @@ green 전건 rc=0 · `cargo test --all` **261 passed / 0 failed / 1 ignored**(S3
17301796

17311797
### ⑤운영 메모 — ★2026-08-27 S3 게이트③ 실측으로 교체(구판 「열린 PR = #13 하나」는 **낡았다**)
17321798

1799+
★★**[2026-09-23 갱신] 아래 표는 «낡았다» — #16 은 머지됐고 지금 열린 PR 은 «#81 하나»다**
1800+
(`gh pr list -R Jun025/RustJava --state open` → `feat/rustjava-sorted-findings` · ★워밍 후 재조회 `mergeable=CONFLICTING`·`DIRTY`).
1801+
★**「열린 PR = 1건」이라는 수만 우연히 맞아서** 이 표가 27일간 안 고쳐졌다 — ★**수가 같다고 내용이 같은 것이 아니다.**
1802+
---- 이하 사료(2026-08-27 실측) ----
1803+
17331804
★**열린 PR = 1건**(`gh pr list -R Jun025/RustJava --state open`):
17341805

17351806
| PR | 브랜치 | 상태 | 원장 |

0 commit comments

Comments
 (0)