From 86e9bd9f1557fe2fcc9f239315a68a1113546532 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Tue, 21 Jul 2026 12:51:36 +0000 Subject: [PATCH] Fix DECFLOAT values with 16-31 decimal places (SignSpecialPlaces mask) TBCD.SignSpecialPlaces keeps the number of decimal places in bits 0..5 (0..63) and the sign in bit 7, so the correct mask for the places field is $3f. SQLDecFloatEncode and SQLDecFloatDecode both masked with $2f, which drops bit 4: any DECFLOAT value with 16..31 decimal places lost exactly 16 places in both directions, i.e. was read back (and sent) multiplied by 10^16. Values with 0..15 or 32..34 places were unaffected, which is why the bug could hide for so long. Reproduced against Firebird 6.0 with round trips at 8, 15, 16, 17, 22, 31 and 33 decimal places: before the fix the 16, 17, 22 and 31 cases came back as e.g. 1.2345678901234567 -> 12345678901234567 on both the getAsBCD path and the SQLParams AsBCD path; after the fix all round trips are exact. --- client/3.0/FB30ClientAPI.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/3.0/FB30ClientAPI.pas b/client/3.0/FB30ClientAPI.pas index bb36988..b6897cb 100644 --- a/client/3.0/FB30ClientAPI.pas +++ b/client/3.0/FB30ClientAPI.pas @@ -710,7 +710,7 @@ procedure TFB30ClientAPI.SQLDecFloatEncode(aValue: tBCD; SQLType: cardinal; begin inherited SQLDecFloatEncode(aValue, SQLType, bufptr); sign := (aValue.SignSpecialPlaces and $80) shr 7; - exp := -(aValue.SignSpecialPlaces and $2f); + exp := -(aValue.SignSpecialPlaces and $3f); case SQLType of SQL_DEC16: @@ -797,7 +797,7 @@ function TFB30ClientAPI.SQLDecFloatDecode(SQLType: cardinal; bufptr: PByte): tBC else IBError(ibxeInvalidDataConversion,[]); end; - Result.SignSpecialPlaces := (-exp and $2f); + Result.SignSpecialPlaces := (-exp and $3f); if sign <> 0 then Result.SignSpecialPlaces := Result.SignSpecialPlaces or $80; end;