Skip to content

fix: resolve Unicode Bug in nodeSv2C (GH #229) - #288

Draft
toddr-bot wants to merge 1 commit into
mainfrom
koan.toddr.bot/fix-unicode-bug-nodeSv2C
Draft

toddr-bot wants to merge 1 commit into
mainfrom
koan.toddr.bot/fix-unicode-bug-nodeSv2C

Conversation

@toddr-bot

@toddr-bot toddr-bot commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

What

Fix the Perl Unicode Bug in nodeSv2C so that appendText, setAttribute, and all
other node string setters behave identically regardless of whether a Perl string is
internally upgraded (UTF-8 flagged) or downgraded (Latin-1 bytes).

Why

Reported by ikegami in RT #115190
(2016), migrated to GH #229. Non-UTF8-flagged Perl SVs store characters 0x80–0xFF as
single Latin-1 bytes. When the document encoding is UTF-8, PmmFastEncodeString received
XML_CHAR_ENCODING_UTF8 as the source charset, causing a no-op xmlStrdup — the raw
Latin-1 bytes were passed to libxml2 as if they were valid UTF-8. This produced different
(and invalid) XML depending on Perl's internal string representation, which should be
invisible to XS code.

How

  • When !DO_UTF8(scalar) and the document encoding is UTF-8, pass
    XML_CHAR_ENCODING_8859_1 as the source encoding to PmmFastEncodeString so the
    Latin-1→UTF-8 conversion actually runs.
  • For non-UTF-8 document encodings (UTF-16, etc.), preserve the old behavior — callers
    may legitimately pass bytes in the document's encoding.
  • Also fix the fallback path (no document / no document encoding) where Sv2C(scalar, NULL)
    would pass Latin-1 bytes through unchanged.

Testing

  • New test t/49unicode_bug_rt115190.t based on ikegami's reproducer: round-trips
    upgraded vs downgraded Latin-1 strings through text nodes, attributes, and a document
    without explicit encoding.
  • Full test suite passes (2692 subtests, 89 test files).
  • Verified that t/03doc.t UTF-16 getAttribute tests still pass (the fix is scoped to
    UTF-8 documents only).

Closes #229


Quality Report

Changes: 2 files changed, 128 insertions(+), 5 deletions(-)

Code scan: clean

Tests: passed (OK)

Branch hygiene: clean

Generated by Kōan

Non-UTF8-flagged Perl SVs store characters as Latin-1 bytes internally.
When the document encoding is UTF-8, PmmFastEncodeString received
XML_CHAR_ENCODING_UTF8 as the source charset, causing it to treat the
Latin-1 bytes as already-valid UTF-8 and copy them unchanged. This meant
upgraded and downgraded SVs with the same logical content produced
different (and invalid) output — the classic Perl "Unicode Bug".

Fix: when the document encoding is UTF-8 and the SV lacks the UTF-8
flag, use XML_CHAR_ENCODING_8859_1 as the source encoding so
PmmFastEncodeString correctly converts Latin-1 bytes to UTF-8. For
non-UTF-8 document encodings (e.g. UTF-16), the old behavior is
preserved since the caller may legitimately pass encoded bytes.

Also handle the fallback path (no document or no document encoding)
where Sv2C(scalar, NULL) would pass Latin-1 bytes through unchanged.
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.

RT #115190: ->appendText suffers from The Unicode Bug

1 participant