Skip to content

fix(gym): convert·export-hwpx·export-markdown 손상 입력 DoS 패닉 2건 하드닝 (page u32 오버플로, WMF 색인 OOB) - #4832

Closed
kevin9327 wants to merge 1 commit into
edwardkim:develfrom
kevin9327:gym_writer_path_overflow
Closed

fix(gym): convert·export-hwpx·export-markdown 손상 입력 DoS 패닉 2건 하드닝 (page u32 오버플로, WMF 색인 OOB)#4832
kevin9327 wants to merge 1 commit into
edwardkim:develfrom
kevin9327:gym_writer_path_overflow

Conversation

@kevin9327

Copy link
Copy Markdown
Contributor

배경

convert·export-hwpx·export-markdown (writer/변환 경로)는 이전 퍼징 캠페인이 다루지 않은 명령 표면입니다. 이 세 명령을 손상된 HWP 입력으로 퍼징해 렌더러 하드닝(#4818)·파서 vpos 하드닝(#4821)이 놓친 DoS 패닉 2건을 찾아 고칩니다.

Fixes #4831

무엇을 고쳤나

1. src/model/page.rs — 페이지 영역 계산 정수 오버플로

PageAreas::from_page_def_for_page 의 raw 산술 4곳을 주변 코드와 동일하게 saturating 으로 통일:

  • bottom: (page_height - page_def.margin_footer) as i32 -> saturating_sub (재현된 언더플로 패닉; margin_footer > page_height)
  • margin_left + margin_gutter (2곳), margin_header + margin_top -> saturating_add (동일 클래스의 덧셈 오버플로 방어)

바로 위 content_bottom 이 이미 saturating_sub 를 쓰는데 271행만 raw 뺄셈이었습니다. 정상 문서는 여백이 용지를 넘지 않으므로 동작 불변, 손상 입력에서만 패닉 대신 포화합니다.

2. src/wmf/converter/graphics_object.rs — WMF 개체표 색인 OOB

GraphicsObjects::delete 가 범위 검사 없이 self.0[i] 직접 색인 -> 손상 WMF 의 DELETEOBJECT 가 범위 밖 object_index 를 주면 패닉. 형제 get 과 같은 관용 규약(get_mut + 범위 밖 무시)으로 변경. 유효 인덱스는 동일 동작.

재현과 검증

재현자 수정 전 수정 후
HWP3 footer_length=0xFFFF (오프셋 50~51) -> convert/export-hwpx/export-markdown page.rs:271:21 패닉(101) 우아하게 종료(비-101)
WMF 손상 문서 -> export-markdown graphics_object.rs:22:15 패닉(101) 우아하게 종료(비-101)
  • 수정 전/후 대조(stash): 위 두 재현자가 수정 전 종료 101 -> 수정 후 비-101. 결정적 재현.
  • 퍼징(수정 후): 디버그 빌드(오버플로 체크 on)로 HWP3 샘플 × (바이트플립·0xFFFF 채움·절단) 변형에 세 명령 실행. 수정 전 패닉하던 샘플(SO-SUEOP·hwp3-pagedef-1915·hwp3-sample) 2193 실행에서 패닉 0건.
  • 정상 데이터 불변: HWP3/HWP5 정상 샘플의 convert/export-hwpx/export-markdown 모두 종료 0·산출물 정상.
  • 회귀 테스트: tests/cli_exit_codes.rs::corrupt_page_margin_does_not_panic_in_writer 추가 — 손상 footer_length 로 세 명령이 101 이 아님을 단언.
  • cargo test --test cli_exit_codes 11 통과, cargo clippy --lib --tests -- -D warnings clean, 변경 파일 rustfmt --edition 2021 적용.

convert·export-hwpx·export-markdown 를 손상 HWP 로 퍼징해 렌더러(edwardkim#4818)·
파서 vpos(edwardkim#4821) 하드닝이 놓친 새 DoS 패닉 2건을 고친다.

- src/model/page.rs: PageAreas::from_page_def_for_page 의 raw 산술 4곳을
  주변과 동일하게 saturating 화. bottom = page_height - margin_footer 의
  u32 언더플로가 세 명령 모두에서 재현되던 패닉(page.rs:271). 덧셈 3곳도
  동일 클래스. 정상 데이터 동작 불변.
- src/wmf/converter/graphics_object.rs: GraphicsObjects::delete 가 손상 WMF
  DELETEOBJECT 의 범위 밖 object_index 로 직접 색인해 패닉. get 과 같은
  관용 색인(get_mut)으로 범위 밖 삭제 무시.
- tests/cli_exit_codes.rs: 손상 footer_length 회귀 테스트 추가.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@jangster77
jangster77 self-requested a review August 15, 2026 13:29
jangster77 pushed a commit that referenced this pull request Aug 15, 2026
손상된 임베디드 WMF/EMF 메타파일 바이트가 산술 오버플로 패닉(디버그 빌드)과
무한 할당(릴리스 OOM)으로 번지는 DoS 5개 지점을 하드닝한다. 파서/컨버터를
퍼징해 재현·수정한 뒤 회귀 테스트를 추가했다.

- bitmap16.rs calc_length: DDB 비트 길이 `(((W*Bpp+15)>>4)<<1)*H` i16 오버플로
  → i64 포화 산술 + 음수 클램프(음수 i16 → 거대 usize 사인확장도 차단)
- bitmap_info_header size(): Core(u16) `:82`, Info/V4/V5(u32) `:113` 치수 곱
  오버플로 → 공용 `dib_image_size`(u64 포화)로 통일
- wmf converter svg placeable header `:577`: 경계 `right-left`/`bottom-top`
  i16 뺄셈 오버플로 → `saturating_sub`
- emf converter player open_root_group `:62-63`: `bounds.right-left`/`bottom-top`
  i32 뺄셈 오버플로 → `saturating_sub`
- read_variable: 신뢰 불가 `len` 선할당(`vec![0u8; len]`) 제거, 실제 도착
  바이트만큼만 증분(64KiB 청크) 할당하여 거대 크기 선언 시 OOM abort 차단

유효 메타파일의 변환 결과는 동일하다(유효 치수는 오버플로하지 않아 동일 값).
`cargo test --lib` 무회귀(3707 pass), 단위·통합 회귀 테스트 추가.

#4832(`graphics_object.rs:22` 색인 OOB)와는 별개 지점이다.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jangster77

Copy link
Copy Markdown
Collaborator

통합 PR #4883(4412546)로 병합 완료했습니다.

원 head와 CI를 다시 확인해 누적 반영했고, 상세 검토·메인터너 보정·검증 근거는 archive 검토 기록에 남겼습니다.

중복 병합을 막기 위해 이 원 PR을 닫습니다. 감사합니다.

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.

2 participants