You are not logged in.
Hello,
I have discovered a bug in the function Base64JSONStringToBytes that is located in the unit SynCrossPlatformJSON compiling with Delphi 10.1 Berlin update 2 and a recently installation of mormot of November 2016 and the project targeting and Android device.
The problem is that in the function Base64JSONStringToBytes the string named JSONString is accesed using 1-based indexing and in mobile compilers in Delphi this strings should be converted to access them using the rule of 0-based indexing ( you can see it in this page : http://docwiki.embarcadero.com/RADStudi … om_Desktop ). The best solution is to use the TStringHelper.Chars property that is 0-based indexing independent of the compiler, so changing the access of JSONString[x] by JSONString.Chars[x-1] the program run well targeting Win32/64 or Android/ios ( mobile devices ).
You can see the corrected function here :
function Base64JSONStringToBytes(const JSONString: string;
var Bytes: TByteDynArray; withBase64Magic: boolean): boolean;
var i,bits,value,x,magiclen,len: cardinal;
begin
result := JSONString='';
if result then
exit;
if withBase64Magic then
if comparemem(pointer(JSONString),@JSON_BASE64_MAGIC,sizeof(JSON_BASE64_MAGIC)) then
magiclen := JSON_BASE64_MAGIC_LEN else
{$ifndef UNICODE}
//if JSONString[1]='?' then // handle UTF-8 decoding error on ANSI Delphi
if JSONString.Chars[0]='?' then // <----- NEW CODE
magiclen := 1 else
{$endif}
exit else
magiclen := 0; // withBase64Magic=false
x := length(JSONString);
len := x-magiclen;
if len and 3<>0 then
exit;
if len=0 then
Bytes := nil else begin
if BASE64DECODE=nil then begin
SetLength(BASE64DECODE,128);
for i := 0 to 127 do
BASE64DECODE[i] := -1;
for i := 0 to high(BASE64) do
BASE64DECODE[ord(BASE64[i])] := i;
end;
len := (len shr 2)*3;
//if Base64One(JSONString[x])<0 then begin
if Base64One(JSONString.Chars[x-1])<0 then begin // <----- NEW CODE
dec(len);
//if Base64One(JSONString[x-1])<0 then
if Base64One(JSONString.Chars[x-2])<0 then // <----- NEW CODE
dec(len);
end;
SetLength(Bytes,len);
bits := 0;
value := 0;
len := 0;
for i := magiclen+1 to Length(JSONString) do begin
//x := ord(JSONString[i]); // inlined Base64One(JSONString[i])
x := ord(JSONString.Chars[i-1]); // <----- NEW CODE
if x>127 then
break;
x := cardinal(BASE64DECODE[x]);
if integer(x)<0 then
break;
value := value*64+x;
bits := bits+6;
if bits>=8 then begin
bits := bits-8;
x := value shr bits;
value := value and ((1 shl bits)-1);
Bytes[len] := x;
inc(len);
end;
end;
end;
result := len=cardinal(length(Bytes));
end;
I suppose that the complementary function BytesToBase64JSONString can have the same problem.
I saw the problem downloading a bitmap content as Base64 from a interface based service server. When I compiled the program targeting Win32 or Win64 the bitmap was decoded using Base64JSONStringToBytes and had a size X. But if I compiled the project targeting Android, the same bitmap had a size of X - 1. Once that I corrected the Base64JSONStringToBytes function to use the Chars property of TStringHelper class the problem solved.
Can anyone confirm me this bug please?. I am in the doubt if I am wrong.
Thank you and best regards.
Offline