LuciferYang opened a new pull request, #56585:
URL: https://github.com/apache/spark/pull/56585

   ### What changes were proposed in this pull request?
   
   `UTF8String.codePointFrom` decodes a code point by reading 
`numBytesForFirstByte(leader)` continuation bytes, and `copyUTF8String` copies 
`end - start + 1` bytes. Neither bounds the read by the bytes that actually 
remain, so when a string ends in a truncated multi-byte sequence (a leader byte 
whose declared width exceeds the remaining bytes), both read past the end of 
the backing memory. `trimLeft`/`trimRight` build their search character through 
`copyUTF8String`, so they over-read too.
   
   This PR:
   - `codePointFrom` reads continuation bytes through a small 
`continuationByte` helper that returns 0 once the index passes the end of the 
string.
   - `copyUTF8String` clamps the copy length to `numBytes - start`.
   - Once `copyUTF8String` stops over-reading, `trimRight` needs a matching 
accounting fix: it advanced `trimEnd` by the leader's declared width, which 
overshoots a truncated trailing character, so it now uses the actual (clamped) 
byte count, as `trimLeft` already does.
   
   ### Why are the changes needed?
   
   `UTF8String` can hold malformed UTF-8 (for example, bytes from binary 
coercion or truncated input). For a string ending in an incomplete multi-byte 
sequence, these methods read out of bounds and produced wrong results: 
`codePointFrom` assembled a code point from adjacent memory, and `trimRight` 
could drop valid leading characters. Well-formed UTF-8 is unaffected, since a 
complete sequence never exceeds the remaining bytes.
   
   This is a follow-up to SPARK-57507, which fixed the same kind of over-read 
in `reverse()`.
   
   ### Does this PR introduce _any_ user-facing change?
   
   Yes, it fixes incorrect results on malformed input. String operations that 
reach these methods (such as trimming or code-point access) no longer read past 
the end of a value that ends in a truncated multi-byte sequence; only 
previously-incorrect results change. Well-formed strings behave exactly as 
before.
   
   ### How was this patch tested?
   
   Added cases to `UTF8StringSuite`:
   - `testCodePointFrom`: truncated trailing 2-, 3-, and 4-byte leaders, 
including a 4-byte leader with only the last continuation byte missing.
   - `copyUTF8StringClampsToRemainingBytes`: an `end` one past the last byte, 
with a non-zero start so the clamp must use `numBytes - start`.
   - `trimTruncatedTrailingSequence`: trimming a truncated trailing leader 
keeps the valid preceding character.
   
   Each uses a sliced backing array with a trailing sentinel byte, so the 
previous over-read produces a deterministically wrong value; the cases fail on 
the old code and pass with the fix. `build/sbt 'unsafe/testOnly 
*UTF8StringSuite'` passes (51 tests).
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (Claude Opus 4.8)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to