Skip to content

model/page: 페이지 영역 여백 산술 오버플로 하드닝 — batch 퍼징 실측 DoS (#4833) - #4834

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

model/page: 페이지 영역 여백 산술 오버플로 하드닝 — batch 퍼징 실측 DoS (#4833)#4834
kevin9327 wants to merge 1 commit into
edwardkim:develfrom
kevin9327:gym_batch_path_hardening

Conversation

@kevin9327

Copy link
Copy Markdown
Contributor

무엇을

batch 경로 퍼징이 드러낸 src/model/page.rs 의 페이지 영역 여백 산술 오버플로
패닉(DoS)을 잠근다. 손상 hwp3 문서에서 margin_footer > page_height 이면
page_height - margin_footer 뺄셈이 u32 언더플로해 패닉했다.

Fixes #4833

  • 단건 명령(rhwp info <file>)에는 catch_unwind 가드가 없어, 손상 파일 한 개로
    프로세스가 exit 101 로 크래시
    한다(DoS). 재현: samples/hwp3-pagedef-1915.hwp
    헤더 2바이트(offset 51→0x5d, 56→0xd1)만 뒤집으면 panicked at src\model\page.rs:271:21: attempt to subtract with overflow.
  • batch 는 행별 catch_unwind 로 격리하므로 프로세스는 죽지 않지만, 정상 처리
    가능한 문서가 "내부 오류(panic)" error 레코드로 잘못 보고된다.

어떻게

PageAreas::from_page_def_for_page 는 이미 대부분의 여백 산술을 saturating_*
처리한다(예: content_right, content_bottom). 빠져 있던 세 자리를 같은 규약으로
맞춘다:

  • footer 아래 경계: page_height - margin_footersaturating_sub
  • 본문 시작: margin_header + margin_topsaturating_add
  • 좌측 여백: margin_left + margin_guttersaturating_add (양쪽 제본 분기 모두)

정상 문서(margin_footer <= page_height, 여백 합이 u32 이내)에서는 결과가 동일
하다. 극값에서만 포화되고, 기존의 "본문 소멸 시 용지 5% 기본 여백" 폴백이 이를
정상 경로로 흡수한다.

중복 아님

검증

  • 재현자: 수정 전 rhwp info corrupt.hwp → exit 101 패닉. 수정 후 → 정상 봉투, exit 0.
  • 단위 테스트 src/model/page.rs::test_page_areas_extreme_margins_do_not_overflow:
    margin_footer = u32::MAX(뺄셈)·margin_header/top/left/gutter = u32::MAX(덧셈,
    단면/양면 제본 모두) 에서 패닉 없이 양수 본문 영역으로 폴백. (수정 전엔 패닉으로 실패)
  • 통합 테스트 tests/batch_axes_contract.rs::batch_isolates_corrupt_page_def_without_panic:
    [유효·손상(page.rs 트리거)·쓰레기·유효] 배치가 패닉 없이 완주하고, 입력 N=출력 N,
    순서 보존, 진짜 실패 행(쓰레기)만 격리해 exit 1, 손상 페이지 정의 행은 성공 레코드.
  • cargo test --lib 회귀 없음. rustfmt --edition 2021 --check 통과(변경 두 파일).
  • 정상 배치(유효 hwp3/hwpx/hwp5 4건)는 여전히 올바른 NDJSON 산출, exit 0.

손상 hwp3 문서에서 margin_footer > page_height 이면 PageAreas::
from_page_def_for_page 의 footer 아래 경계 `page_height - margin_footer` 가
u32 언더플로해 패닉했다. 단건 `rhwp info` 는 catch_unwind 가드가 없어 손상 파일
한 개로 exit 101 크래시(DoS), batch 는 격리하지만 정상 문서를 실패로 보고했다.

같은 함수가 이미 대부분 saturating_* 를 쓰는 규약대로 남은 세 자리를 맞춘다:
footer 뺄셈은 saturating_sub, margin_header+margin_top·margin_left+margin_gutter
덧셈은 saturating_add. 정상 문서에서는 결과가 동일하고, 극값만 포화 후 기존의
본문 소멸 폴백이 흡수한다.

- 단위 테스트: model::page::test_page_areas_extreme_margins_do_not_overflow
- 통합 테스트: batch_axes_contract::batch_isolates_corrupt_page_def_without_panic
- edwardkim#4818(렌더러)·edwardkim#4821(파서)과 다른 파일·다른 자리 (중복 아님)

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.

@kevin9327

Copy link
Copy Markdown
Contributor Author

중복 정리: 이 PR의 page.rs:271 u32 언더플로 수정은 병렬로 진행된 #4832 에 포함됩니다(#4832 는 page.rs 4개 사이트 saturating + 별개의 WMF graphics_object.rs OOB 까지 함께 고쳐 더 완전합니다). 두 PR이 page.rs 를 동시에 건드려 충돌하므로 이쪽을 닫습니다. 다만 여기 추가한 batch 격리 통합 테스트(batch_isolates_corrupt_page_def_without_panic)는 유용하니 #4832 또는 별도 후속으로 살리겠습니다. batch 러너 자체는 견고함을 실측 확인(8 서브명령·40k 경로·퇴화 입력 전부 무크래시).

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