Skip to content

fix(serializer): OLE Storage BinData 4-byte size prefix 복원#954

Closed
civilian7 wants to merge 1 commit into
edwardkim:develfrom
civilian7:fix/ole-storage-bindata-size-prefix
Closed

fix(serializer): OLE Storage BinData 4-byte size prefix 복원#954
civilian7 wants to merge 1 commit into
edwardkim:develfrom
civilian7:fix/ole-storage-bindata-size-prefix

Conversation

@civilian7

Copy link
Copy Markdown

문제

OLE 임베디드 개체를 포함한 HWP 문서를 rhwp 로 파싱한 뒤 다시 직렬화(serialize_hwp)하면, 결과 파일을 한컴 오피스에서 열 때 "메모리 부족" 오류가 발생하며 문서가 열리지 않습니다. (rhwp 자체 파서로는 정상 재열림)

원인

HWP 의 OLE Storage BinData 스트림은 [4-byte LE size][CFB 컨테이너] 형식입니다.

  • 파서 load_bin_data_content 는 내부 CFB(D0CF11E0…)를 바로 노출하기 위해 이 4-byte size prefix 를 제거합니다 (decompressed.drain(..4), Task 차트/OLE 개체 렌더링 지원 #195).
  • 그러나 직렬화기 cfb_writer::write_hwp_cfb 는 BinData 를 그대로 다시 쓰며 prefix 를 복원하지 않습니다.

→ 재저장된 파일의 OLE BinData 는 prefix 없이 곧바로 CFB 매직으로 시작합니다. 한컴은 첫 4바이트 D0 CF 11 E0 를 OLE 개체 크기로 해석 → LE 0xE011CFD03.75 GB 할당 시도 → "메모리 부족".

실제 문서 비교에서, 재직렬화 파일의 모든 CFB 스트림(DocInfo · BodyText · 이미지 BinData 등)은 원본과 바이트 단위로 동일했고 OLE BinData 만 정확히 4바이트 짧았습니다.

수정

write_hwp_cfb 의 BinData 직렬화 루프에서, BinData 가 OLE Storage 타입이고 내용이 CFB 매직으로 시작하면 4-byte LE size prefix 를 복원합니다. 파서의 strip 조건(is_storage && data[..8] != magic && data[4..12] == magic)을 그대로 미러링하므로, prefix 가 없던 입력에는 영향을 주지 않습니다.

검증

  • 회귀 테스트 test_ole_storage_size_prefix_restored 추가
  • cargo test serializer::cfb_writer — 16개 전부 통과
  • OLE 개체를 포함한 실제 문서 재직렬화 후 전 CFB 스트림이 원본과 바이트 일치 확인, 한컴 오피스에서 "메모리 부족" 없이 정상 열림 확인

HWP 의 OLE 임베디드 개체 BinData 스트림은 `[4-byte LE size][CFB 컨테이너]`
형식이다. 파서(`load_bin_data_content`)는 내부 CFB 를 바로 노출하려고 이
prefix 를 제거(`drain(..4)`)하지만, 직렬화기(`cfb_writer`)가 이를 복원하지
않아 round-trip 시 prefix 가 누락됐다.

그 결과 한컴 오피스가 재저장된 문서의 OLE 개체를 열 때 CFB 매직(D0CF11E0)을
개체 크기(~3.75GB)로 오인하여 "메모리 부족" 오류로 문서 열기에 실패했다.

`write_hwp_cfb` 의 BinData 직렬화에서 OLE Storage 타입이면 파서의 strip
조건을 그대로 미러링하여 4-byte LE size prefix 를 복원한다. 회귀 테스트
`test_ole_storage_size_prefix_restored` 추가.
@edwardkim edwardkim self-requested a review May 17, 2026 08:48
@edwardkim edwardkim added the bug Something isn't working label May 17, 2026
@edwardkim edwardkim added this to the v1.0.0 milestone May 17, 2026
edwardkim pushed a commit that referenced this pull request May 17, 2026
…ck PR #954)

파서(load_bin_data_content)가 내부 CFB 노출을 위해 제거한
[4-byte LE size] prefix 를 직렬화 시 복원. 미복원 시 한컴이
CFB 매직(D0CF11E0)을 OLE 개체 크기(~3.75GB)로 오인 →
"메모리 부족" 오류로 문서 열기 실패.

회귀 테스트 test_ole_storage_size_prefix_restored 추가.

Original-Author: civilian7
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
edwardkim pushed a commit that referenced this pull request May 17, 2026
@edwardkim

Copy link
Copy Markdown
Owner

rhwp에 보내주신 첫 PR 진심으로 환영하고 감사드립니다! 🎉

OLE 임베디드 개체 round-trip 시 한컴 "메모리 부족" 오류의 원인을 정확히 짚어주셨습니다. 파서의 drain(..4)(Task #195)과 직렬화기 간의 비대칭을 size prefix 복원으로 해결하고, 파서 strip 조건을 미러링한 점, 그리고 회귀 테스트(test_ole_storage_size_prefix_restored)까지 함께 주신 점이 인상적이었습니다.

검증 완료:

  • cargo test serializer::cfb_writer — 16개 전부 통과 (신규 테스트 포함)
  • 전체 테스트 통과, clippy 경고 없음, WASM 빌드 정상

cherry-pick으로 devel에 반영했습니다 (원작자 표기 보존). 앞으로의 기여도 기대하겠습니다. 감사합니다!

@edwardkim edwardkim closed this May 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants