Skip to content

Fix isc_put_slice storing unaligned VARCHAR array elements without character set conversion - #9181

Open
madorin wants to merge 1 commit into
FirebirdSQL:masterfrom
madorin:fix-slice-varying-charset
Open

madorin wants to merge 1 commit into
FirebirdSQL:masterfrom
madorin:fix-slice-varying-charset

Conversation

@madorin

@madorin madorin commented Oct 2, 2026

Copy link
Copy Markdown

Fixes #9180.

An element of a VARCHAR(n) array with an odd element size (n + 2 bytes for single-byte
character sets, 3 * n + 2 for UNICODE_FSS) can start at an odd address. slice_callback writes
such elements with MOV_make_string, which converts through CVT_move and CommonCallbacks,
whose transliterate() does nothing. So when the slice character set differs from the column
one, every second element is stored without conversion (or rejected with "string right
truncation" when the unconverted bytes don't fit), and UNICODE_FSS columns can get malformed
strings.

The fix moves the value with MOV_move (engine callbacks, as for aligned elements) into an
aligned temporary that has the element's descriptor, then copies the length and the text to the
element's address. The reading direction already uses MOV_move for unaligned elements and is
correct.

Tested on debug builds of master and v5.0-release with the reproducer from the issue and with an
extended test: VARCHAR(1), (2), (3), (5) in WIN1251 / ISO8859_1 written from UTF8, a value that
fits only after conversion, 2-dimensional arrays, blr_varying, UNICODE_FSS VARCHAR(1)/(3)
written from WIN1251 and ISO8859_1, UTF8, same character set and NONE columns. The stored bytes
of every element are checked with cast(COL[i] as varchar(64) character set octets) and with
isc_get_slice in both character sets.

Please consider a backport to v5.0 (and older branches if applicable): the code is the same
there, and the bug reproduces on 5.0.4, 3.0.14 and 2.5.9. A branch for v5.0-release is ready:
madorin:fix-slice-varying-charset-5.0.

…aracter set conversion

An array element of an odd-size VARCHAR (e.g. VARCHAR(3) in a single-byte
character set) can start at an odd address. slice_callback wrote such elements
with MOV_make_string, which converts through CVT_move and CommonCallbacks, so
the slice was copied without transliteration. Move the value with MOV_move into
an aligned temporary instead, as for aligned elements, and copy it.
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.

isc_put_slice stores every second VARCHAR array element without character set conversion

1 participant