Skip to content

Fix double-free/UAF in AppendLinePolygon for RTL PAGE XML output - #4647

Open
stweil wants to merge 1 commit into
tesseract-ocr:mainfrom
stweil:ghsa-vf7v-pagerenderer
Open

stweil wants to merge 1 commit into
tesseract-ocr:mainfrom
stweil:ghsa-vf7v-pagerenderer

Conversation

@stweil

@stweil stweil commented Oct 10, 2026 •

Copy link
Copy Markdown
Member

AppendLinePolygon freed a Pta it did not own. The right-to-left accumulator was passed by value as Pta *, so ptaDestroy released the allocation and nulls only the callee's local copy; the caller's line_top_rtl_pts / line_bottom_rtl_pts (created once before the page loop and never reassigned) were left dangling. That branch is entered once per recognised word whose writing direction is right-to-left, so on any page containing at least two such words the dangling pointer was read (ptaGetCount/ptaJoin) and freed again, and the stale coordinates
were joined into the line polygon - which can trigger a heap-buffer-overflow in RecalcPolygonline.

This uses the fix suggested in the GHSA-vf7v-2h4f-6f4j advisory: take the RTL accumulator by pointer-to-pointer so the function can hand the replacement back. This also repairs two further defects in the same
function: the RTL branch discarded its result (right-to-left word polygons were never accumulated) and leaked the ptsd copy.

Add a PAGEXMLRightToLeftPolygon regression test that renders hebrew.png (already in the test data) through GetPAGEText at word level with polygons enabled. Under AddressSanitizer it crashes on the unfixed code and is clean on the fixed code.

The regression test exposed a pre-existing leak in RecalcPolygonline: the num_pts == 2 early return skipped the numaDestroy of bin_line, which had been created before the check. Each call with a 2-point polygon leaked one NUMA. LeakSanitizer (running in the Linux ASan CI jobs) flagged this, so destroy bin_line in the early-return branch as well.

Fixes GHSA-vf7v-2h4f-6f4j

Suggested-by: Jipa Alexandru-Ionut jipaionut@gmail.com
Assisted-by: OpenCode / qwen3.8-27b-thinking (Alibaba Cloud)
Signed-off-by: Stefan Weil sw@weilnetz.de

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 5 complexity · 0 duplication

Metric Results
Complexity 5
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@stweil
stweil force-pushed the ghsa-vf7v-pagerenderer branch from 0e86d38 to 547ac18 Compare October 18, 2026 18:49
@stweil

stweil commented Oct 18, 2026

Copy link
Copy Markdown
Member Author

@router0mail, please review.

@stweil
stweil requested a balanced review from Copilot October 18, 2026 18:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The regression test leaks its source image on a skip path, potentially failing LeakSanitizer runs.

1 open issue

Review effort: Balanced

Comment thread unittest/baseapi_test.cc
@stweil
stweil force-pushed the ghsa-vf7v-pagerenderer branch from 547ac18 to 88e423c Compare October 18, 2026 19:28
@stweil
stweil force-pushed the main branch 2 times, most recently from 47b149e to f87ce60 Compare October 19, 2026 07:16
AppendLinePolygon freed a Pta it did not own. The right-to-left
accumulator was passed by value as Pta *, so ptaDestroy released the
allocation and nulls only the callee's local copy; the caller's
line_top_rtl_pts / line_bottom_rtl_pts (created once before the page
loop and never reassigned) were left dangling. That branch is entered
once per recognised word whose writing direction is right-to-left, so on
any page containing at least two such words the dangling pointer was
read (ptaGetCount/ptaJoin) and freed again, and the stale coordinates
were joined into the line polygon - which can trigger a
heap-buffer-overflow in RecalcPolygonline.

This uses the fix suggested in the GHSA-vf7v-2h4f-6f4j advisory: take
the RTL accumulator by pointer-to-pointer so the function can hand the
replacement back. This also repairs two further defects in the same
function: the RTL branch discarded its result (right-to-left word
polygons were never accumulated) and leaked the ptsd copy.

Add a PAGEXMLRightToLeftPolygon regression test that renders hebrew.png
(already in the test data) through GetPAGEText at word level with
polygons enabled. Under AddressSanitizer it crashes on the unfixed code
and is clean on the fixed code.

The regression test exposed a pre-existing leak in RecalcPolygonline:
the num_pts == 2 early return skipped the numaDestroy of bin_line,
which had been created before the check. Each call with a 2-point
polygon leaked one NUMA. LeakSanitizer (running in the Linux ASan CI
jobs) flagged this, so destroy bin_line in the early-return branch as
well.

Also release the test's source image right after SetImage: the API
clones the image, so the local copy is not needed any longer, and
destroying it early keeps every early-return path (GTEST_SKIP,
ASSERT_TRUE) from leaking it under LeakSanitizer.

Fixes GHSA-vf7v-2h4f-6f4j

Suggested-by: Jipa Alexandru-Ionut <jipaionut@gmail.com>
Assisted-by: OpenCode / qwen3.8-27b-thinking (Alibaba Cloud)
Signed-off-by: Stefan Weil <sw@weilnetz.de>
@stweil
stweil force-pushed the ghsa-vf7v-pagerenderer branch from 88e423c to bc29121 Compare October 19, 2026 07:29
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