Delphi 10.4 WordBool change affects Bin2 streaming

It appears that Delphi 10.4 includes a change to how WordBool types are handled that can impact streaming from a TDAMemDataTable to the Bin2 format. I don’t know if this issue affects any of the Delphi-based drivers, but depending on how they are implemented it’s possible that it could.

Method TBooleanField.SetAsBoolean in Data.DB.pas has the following line:

if Value then Word(B) := 1 else Word(B) := 0;

where B is a local variable of type WordBool. In Delphi 10.3 and earlier, the “true” assignment gets compiled to:

mov dx,$0001

but in Delphi 10.4, it gets compiled to:

or edx,-$01

In other words, 10.3 sets the value of the WordBool to $0001, while 10.4 appears to be restricting the range of allowed values and setting it to $ffff. TDAMemDataset just copies this value into its own buffer, which isn’t a problem if you’re only using it locally. However, I will sometimes manually create and fill a TDAMemDataTable on the server and then stream its contents to the client as if it were a database table, and that’s where I’m running into issues. The fast streaming from TDAMemDataTable to the Bin2 format copies the least-significant byte of the WordBool from the record buffer to the data stream, so 10.3 writes a Boolean “true” value as $01, while 10.4 writes it as $ff (if it was assigned using SetAsBoolean or SetValue). Then when the stream is deserialized on the client, it hits this line in method TDADBSupport.BufferToBoolean in uDADBSupport.pas:

Result := BufferToByte(Buffer, Offset) = 1;

which is expecting a value of $01 if the field value is “true”. When the value read from the stream is $ff, the field value on the client is set to “false” despite having been “true” on the server.

I’ve only tried this with the Win32 compiler, so I don’t know whether or not it happens with any of the other Delphi 10.4 compilers, but I expect that they would have changed the WordBool behavior for all of them. I’ve tried to describe the problem as best I can, but if necessary I can put together a simple project to demonstrate it.

Hi,

pls change TDADBSupport.BufferToBoolean method in uDADBSupport.pas as

class function TDADBSupport.BufferToBoolean(const Buffer: TBytes;
  Offset: Integer): WordBool;
begin
  Result := BufferToByte(Buffer, Offset) <> 0;
end;

Thanks, logged as bugs://84514

bugs://84514 got closed with status fixed.

Thanks for the quick response. The fix as posted solves the problem for Delphi clients, but it still leaves the possibility of a $ff value appearing in the Bin2 stream where a $01 is expected. Could this still cause problems for non-Delphi clients?

Hi,

no, other non-Delphi clients already check for 0