I think the problem starts with Firebird itself - when the connection charset is UTF8, it always allocates the maximum possibly needed memory for a field, which is 4 bytes per character, and as a result, the buffer for a CHAR(3) field is 12 bytes, and its length is given as 12. No information is provided about the length of the buffer as number of characters, this is only available in the field metadata. (That description may not be entirely correct, if anyone can provide a better explanation - would be nice)
As a result of this many (or at least some) clients will return such CHAR(3) field as up to 12 UTF characters (depending on how many of them as ASCII), padded right with spaces. The PHP interbase driver does so, and FPC's IBConnection does so, and IBX for Lazarus too.
There is however a difference - when you create the TField object for such a firebird field, TIBConnection will create it with Size and DisplayWidth of 12. IBX for lazarus, on the other hand, will create the field with the correct Size and DisplayWidth of 3. And then, both of them will actually return the data in the AsString property as up to 12, padded with spaces to the length of 12 bytes.
There is a kind of workaround for this with TIBConnection - you can set the TField.Size to the correct value, and it will work - as long as your content is only ASCII. I couldn't find similar one for IBX.
Now the questions are - would it be possible to fix this on the level of data access components, and how. If not, why exactly? Do you know how this works on current Delphi versions? What about other db components supporting Firebird?