Skip to content

Fix non-BMP characters in JNI strings (#10) + regression test, CI on develop - #11

Merged
titusz merged 10 commits into
developfrom
verify/pr10-non-bmp
Oct 9, 2026
Merged

titusz merged 10 commits into
developfrom
verify/pr10-non-bmp

Conversation

@titusz

@titusz titusz commented Oct 8, 2026

Copy link
Copy Markdown
Member

Summary

Brings @CHISANW's non-BMP JNI decoding fix onto develop for the next release, with a regression test and CI for develop.

Merging this pull request includes their commit (198e4a1, "Decode Java strings as modified UTF-8"), so GitHub will show #10 as merged.

Changes from #10

  • iscc-tika-core/src/tika/jni_utils.rs: decode Java strings with the jni crate's modified UTF-8 conversion (String::from(JavaStr)) instead of plain to_string_lossy().
  • CHANGELOG.md: note under Unreleased.

Regression test

  • iscc-tika-core/tests/non_bmp_tests.rs
  • Fixtures: test_files/documents/non-bmp.txt, non-bmp.html, non-bmp.docx
  • Checks that 😀 (U+1F600), 𠀋 (U+2000B), and 𝄞 (U+1D11E) round-trip in extracted text and in dc:title (HTML and DOCX, including metadata-only extraction). Fails on main / current develop without the JNI fix.

CI

.github/workflows/ci.yml already ran on pushes to develop. Pull requests that target develop now run the same workflow as pull requests that target main.

Not merged here.

Open in Web Open in Cursor 

titusz and others added 10 commits July 23, 2026 21:57
`GetStringUTFChars` returns modified UTF-8, which encodes characters
outside the BMP as a CESU-8 surrogate pair. Decoding that buffer as
plain UTF-8 replaced every such character with U+FFFD, so emoji and
CJK extension ideographs were lost from extracted text and metadata.
Characters outside the BMP were decoded as plain UTF-8 on the way out of
JNI, so extracted text and metadata came back as U+FFFD. Cover a UTF-8
text file, an HTML title, and a DOCX body plus dc:title.

Co-authored-by: Titusz <tp@py7.de>
Pushes to develop already ran this workflow. Pull requests against
develop now use the same jobs as pull requests against main.

Co-authored-by: Titusz <tp@py7.de>
cargo test for iscc-tika-core runs in its own job, in parallel with the
wheel build. Cargo already puts the native library directory on
LD_LIBRARY_PATH. The Graal image is produced by setup_tika_native.py, the
same path local builds use, and cached so the next run can reuse it.

Co-authored-by: Titusz <tp@py7.de>
Co-authored-by: Titusz <tp@py7.de>
Modified UTF-8 from GetStringUTFChars cannot be decoded at all once a
string holds an unpaired surrogate, so the jni crate fell back to lossy
decoding of the whole string and garbled every supplementary character
in it. Reading UTF-16 units replaces only the unpaired surrogate.

Metadata values are looked up with the original Java key instead of a
re-encoded copy of the decoded key, which did not round-trip for keys
holding an unpaired surrogate.
The 500,000 default cut off the text of most books. Text cut off at the
limit is now flagged with Tika's X-TIKA:EXCEPTION:write_limit_reached
metadata key (exported as WRITE_LIMIT_REACHED), and a cut that splits a
surrogate pair drops the dangling high surrogate. Any negative limit
disables truncation; Tika itself only accepts -1.
File hygiene hooks no longer rewrite test_files/, whose BOM and missing
final newline are part of the fixtures. The Rust CI job saves the native
library cache before running tests, so a failing test keeps the build,
and moves to actions/cache v6.
@titusz
titusz merged commit 5745c54 into develop Oct 9, 2026
6 checks passed
@titusz
titusz deleted the verify/pr10-non-bmp branch October 9, 2026 08:13
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.

3 participants