Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
opencc (1.1.9+ds1-1deepin1) unstable; urgency=medium

* Fix CVE-2025-15536: heap buffer overflow in UTF-8 processing

-- deepin-ci-robot <[email protected]> Wed, 29 Apr 2026 19:47:21 +0800

opencc (1.1.9+ds1-1deepin0) unstable; urgency=medium

* No source change upload against GCC 12.
Expand Down
85 changes: 85 additions & 0 deletions debian/patches/0006-CVE-2025-15536.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
Description: Fix heap buffer overflow in UTF-8 processing
Two out-of-bounds read issues were identified in OpenCC's UTF-8
processing logic when handling malformed or truncated UTF-8 sequences.
.
1) MaxMatchSegmentation:
NextCharLength() could return a value larger than the remaining input size.
The previous logic subtracted this value from a size_t length counter,
potentially causing underflow and subsequent out-of-bounds reads.
.
2) Conversion:
Similar length handling could allow reads past the end of the input buffer
during dictionary matching.
.
This patch fixes both issues by:
- Explicitly tracking the end of the input buffer
- Recomputing remaining length on each iteration
- Clamping matched character and key lengths to the remaining buffer size
- Preventing reads past the null terminator
Origin: upstream, https://github.com/BYVoid/OpenCC/commit/345c9a50ab07018f1b4439776bad78a0d40778ec
Bug: https://github.com/BYVoid/OpenCC/issues/997
Bug-Debian: https://bugs.debian.org/1126286
Forwarded: not-needed
Last-Update: 2026-04-29

--- opencc-1.1.9+ds1.orig/src/Conversion.cpp
+++ opencc-1.1.9+ds1/src/Conversion.cpp
@@ -25,14 +25,30 @@ using namespace opencc;

std::string Conversion::Convert(const char* phrase) const {
std::ostringstream buffer;
+ // Calculate string end to prevent reading beyond null terminator
+ const char* phraseEnd = phrase;
+ while (*phraseEnd != '\0') {
+ phraseEnd++;
+ }
+
for (const char* pstr = phrase; *pstr != '\0';) {
- Optional<const DictEntry*> matched = dict->MatchPrefix(pstr);
+ size_t remainingLength = phraseEnd - pstr;
+ Optional<const DictEntry*> matched = dict->MatchPrefix(pstr, remainingLength);
size_t matchedLength;
if (matched.IsNull()) {
matchedLength = UTF8Util::NextCharLength(pstr);
+ // Ensure we don't read beyond the null terminator
+ if (matchedLength > remainingLength) {
+ matchedLength = remainingLength;
+ }
buffer << UTF8Util::FromSubstr(pstr, matchedLength);
} else {
matchedLength = matched.Get()->KeyLength();
+ // Defensive: ensure dictionary key length does not exceed remaining input
+ // (MatchPrefix should already guarantee this, but defense in depth)
+ if (matchedLength > remainingLength) {
+ matchedLength = remainingLength;
+ }
buffer << matched.Get()->GetDefault();
}
pstr += matchedLength;
--- opencc-1.1.9+ds1.orig/src/MaxMatchSegmentation.cpp
+++ opencc-1.1.9+ds1/src/MaxMatchSegmentation.cpp
@@ -26,12 +26,16 @@ SegmentsPtr MaxMatchSegmentation::Segmen
};
size_t length = text.length();
for (const char* pstr = text.c_str(); *pstr != '\0';) {
+ // Recompute remaining length each iteration to avoid underflow
+ size_t remainingLength = text.c_str() + text.length() - pstr;
const Optional<const DictEntry*>& matched = dict->MatchPrefix(pstr, length);
size_t matchedLength;
if (matched.IsNull()) {
matchedLength = UTF8Util::NextCharLength(pstr);
+ // Clamp matchedLength to remaining buffer size
+ if (matchedLength > remainingLength) matchedLength = remainingLength;
segLength += matchedLength;
} else {
clearBuffer();
matchedLength = matched.Get()->KeyLength();
segments->AddSegment(matched.Get()->Key());
segStart = pstr + matchedLength;
}
pstr += matchedLength;
- length -= matchedLength;
+ // No need to track length, we recompute remainingLength each iteration
}
clearBuffer();
return segments;
1 change: 1 addition & 0 deletions debian/patches/series
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
0003-no-remote-images-when-reading-docs-on-disk.patch
0004-Use-system-googletest.patch
0005-Disable-build-in-setup.py.patch
0006-CVE-2025-15536.patch
Loading