Conversation
글머리표(bullet_char/check_bullet_char), 각주/미주 모양(user_char/prefix_char/ suffix_char), 자동번호(user_symbol/prefix_char/suffix_char), 쪽번호 위치 (user_symbol/prefix_char/suffix_char/dash_char) 필드는 모델에서 `char` (전체 유니코드 스칼라)로 정의되어 있고 HWPX 파서는 `s.chars().next()`로 BMP 제한 없이 값을 채운다. 하지만 HWP5 직렬화 시 `as u16`으로 그대로 캐스팅해 U+FFFF를 넘는 문자(예: 이모지 🔶 U+1F536)의 상위 비트가 잘려 0xF536 같은 완전히 다른 문자로 조용히 손상된 채 저장됐다. byte_writer.rs에 char_to_wchar() 헬퍼를 추가해 BMP 밖 문자를 U+FFFD로 치환하도록 doc_info.rs·control.rs의 4개 함수(bullet, footnote_shape, auto_number, page_num_pos) 10곳을 통일했다. byte_writer.rs의 `write_hwp_string` 오버플로 수정(u16::MAX 초과 문자열 길이 wraparound)과 같은 종류의 결함이었으나 char 타입 필드들에는 적용되지 않고 남아있었다. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
cargo fmt --all -- --check 가 src/serializer/doc_info.rs:621 에서 실패했다. w.write_u16(char_to_wchar(..)).unwrap() 체인을 rustfmt 가 요구하는 형태로 줄바꿈한다. 동작 변화 없음. 포맷만 수정. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 1, 2026
이 PR 의 변경과 무관하게 CI 가 계속 빨갛다. devel(cc38291) 자체가 edwardkim#3742 머지 이후 tests/batch_axes_contract.rs 의 stdin 헬퍼 때문에 깨져 있고, 그 커밋을 기반으로 하는 모든 PR 이 같은 지점에서 막힌다. thread 'batch_global_auth_options_are_rejected_before_consuming_path_stdin' panicked at tests/batch_axes_contract.rs:34:10: stdin 쓰기 실패: Os { code: 32, kind: BrokenPipe, message: "Broken pipe" } 재실행으로는 빠져나가지 못한다 — 이 PR 도 재실행했지만 같은 지점에서 다시 실패했다. 이 브랜치의 CI 를 읽을 수 있게 하려고 edwardkim#3766 의 테스트 하네스 수정을 그대로 싣는다. 근인: 이 헬퍼를 쓰는 테스트들의 계약이 "자식이 stdin 을 읽기 전에 거부하고 종료한다" 이다. 자식이 인자 검증에서 즉시 죽으면 파이프의 읽기 끝이 닫히고 부모의 write_all 이 EPIPE 를 받는다. 기능이 의도대로 일찍 거부할수록 더 잘 깨진다. EPIPE 는 오류가 아니라 검증 대상 동작의 정상적인 부산물이므로 ErrorKind::BrokenPipe 만 넘어가고 그 밖의 오류는 그대로 패닉한다. 제품 코드 변경 없음. 테스트 하네스만 고친다. edwardkim#3766 이 먼저 머지되면 이 커밋은 빈 diff 가 되므로 리베이스 때 떨어져 나간다. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
jangster77
self-requested a review
August 2, 2026 10:48
Collaborator
|
통합 검토 PR #3801이 이 PR의 contributor 기능 commit은 원 PR별 검토 기록과 적용 SHA는 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
문제
HWP5 직렬화 코드에서
char타입 필드를 HWP5의 16비트 WCHAR 슬롯에 쓸 때as u16으로 직접 캐스팅하는 패턴이 4개 함수, 10개 필드에 걸쳐 반복돼 있었다.char는 U+0000~U+10FFFF 전체 유니코드 스칼라 값을 담을 수 있지만, HWPX파서는 이 필드들을
s.chars().next()로 BMP 제한 없이 채운다(글머리표기호, 각주/미주 접두/접미 문자, 자동번호 사용자 기호 등은 실제로 이모지 같은
비BMP 문자를 담을 수 있다). 이런 문자를 그대로
as u16캐스팅하면 상위비트가 잘려 완전히 다른 문자로 조용히 손상된다. 예:
'🔶'(U+1F536)as u16==
0xF536(전혀 다른 글자) — 에러도, 패닉도 없이 잘못된 값이 저장된다.같은 클래스의 결함이
byte_writer.rs의write_hwp_string(문자열 길이u16::MAX 초과 시 wraparound)에서는 이미 한 번 고쳐졌지만
(
test_write_hwp_string_overlong_truncates_instead_of_wrapping),char타입 필드들에는 같은 수정이 적용되지 않고 남아 있었다.
수정 대상 (4곳, 10개 필드)
src/serializer/doc_info.rs—serialize_bullet:bullet_char,check_bullet_charsrc/serializer/control.rs—serialize_footnote_shape:user_char,prefix_char,suffix_charsrc/serializer/control.rs—serialize_auto_number(추정 함수명):user_symbol,prefix_char,suffix_charsrc/serializer/control.rs—serialize_page_num_pos:user_symbol,prefix_char,suffix_char,dash_char수정 방식
src/serializer/byte_writer.rs에 공용 헬퍼char_to_wchar()를 추가:BMP(U+0000~U+FFFF) 안이면 그대로
as u16, 밖이면 대체 문자U+FFFD(REPLACEMENT CHARACTER)로 치환한다. 4개 함수의 10개 캐스팅 지점을
모두 이 헬퍼 호출로 교체했다.
검증
cargo test --lib serializer::— 488 passed, 0 failed(신규 테스트
test_char_to_wchar_bmp_passthrough,test_char_to_wchar_astral_replaces_instead_of_truncating포함)cargo test --lib serializer::byte_writer::tests— 18 passed, 0 failedcargo test --lib필터만 실행했고 풀cargo build/cargo test --tests는실행하지 않았다. 컴파일은
cargo test --lib과정에서 전체 크레이트를포함해 성공적으로 완료됐다.
Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
📌 추가 커밋 안내 — #3763 플레이키 수정을 함께 실었습니다
이 PR 의 변경과 무관하게 CI 가 계속 빨갰습니다.
devel(cc38291) 자체가 #3742 머지 이후tests/batch_axes_contract.rs의 stdin 헬퍼 때문에 깨져 있고, 그 커밋을 기반으로 하는 모든 PR 이같은 지점에서 막힙니다.
재실행으로는 빠져나가지 못했습니다 — 이 PR 도 재실행했지만 같은 지점에서 다시 실패했습니다.
그래서 이 브랜치의 CI 를 읽을 수 있게 하려고 #3766 의 테스트 하네스 수정
(
tests/3개 파일, 제품 코드 무변경)을 그대로 실었습니다.원인 분석은 #3763 에 있습니다. #3766 이 먼저 머지되면 이 커밋은 빈 diff 가 되어 리베이스 때
자연히 떨어져 나갑니다. 리뷰 시 마지막 커밋
test(cli): stdin 계약 테스트의 BrokenPipe 플레이키를 함께 싣는다 (#3763)는 이 PR 의 본 주제가아니니 분리해서 보시면 됩니다.