Skip to content

bound utf-8 reader to the terminating nul in extension-functions - #1454

Open
dxbjavid wants to merge 1 commit into
xerial:masterfrom
dxbjavid:utf8-reader-nul-bound
Open

bound utf-8 reader to the terminating nul in extension-functions#1454
dxbjavid wants to merge 1 commit into
xerial:masterfrom
dxbjavid:utf8-reader-nul-bound

Conversation

@dxbjavid

Copy link
Copy Markdown
Contributor

out-of-bounds read on a truncated utf-8 sequence in extension-functions

the multibyte reader behind reverse/proper/charindex/leftstr/rightstr/strfilter/difference reads the trailing bytes a lead byte announces without checking for the string's terminating nul, so a value ending in a truncated sequence such as reverse(cast(x'f0' as text)) makes it walk a few bytes past the allocation, a heap over-read reachable from ordinary sql. this stops the read as soon as the next byte is not a continuation byte, so a truncated character resolves to U+FFFD and well-formed utf-8 decodes exactly as before.

@gotson

gotson commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

The extension functions come from the Sqlite repo, would you happen to know if that issue is also present there, or whether it has been fixed and this fix is the port of theirs ?

@gotson gotson added impacts:JNI Has impact on JNI C code and removed impacts:JNI Has impact on JNI C code labels Aug 20, 2026
@dxbjavid

Copy link
Copy Markdown
Contributor Author

good question. this isn't part of the core sqlite amalgamation. it's the contributed extension-functions.c (the LMH one from sqlite.org's contrib page), and the reader here was copied out of sqlite 3.3.13's internal utf8 handling, as the comment just above the tables notes.

core sqlite reworked that reader a long time ago. their version now takes an end pointer and stops on the first non-continuation byte, so the over-read isn't present upstream. the contrib file was never kept in sync, so the old unbounded copy is what still ships here. there's no upstream patch to this file to port, so this is a local fix, but it deliberately follows the same continuation-byte approach current sqlite uses.

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