ソースを参照

* fixed big endian bugs in variant dispatching
* fixed size calculation of vardatetime arguments on 32 bit systems with
variant dispatching

git-svn-id: trunk@29319 -

Jonas Maebe 10 年 前
コミット
476e3fabb7
2 ファイル変更133 行追加28 行削除
  1. 41 15
      packages/rtl-objpas/src/inc/variants.pp
  2. 92 13
      tests/webtbs/tw26773.pp

+ 41 - 15
packages/rtl-objpas/src/inc/variants.pp

@@ -4004,6 +4004,8 @@ var
   arg_ptr: pointer;
   arg_data: PVarData;
   dummy_data: TVarData;
+  arg_advanced: boolean;
+
 const
   argtype_mask = $7F;
   argref_mask = $80;
@@ -4032,22 +4034,46 @@ begin
         Inc(arg_ptr,sizeof(Pointer));
       end
       else
-        case arg_type of
-          varError:
-            arg_data^.vError:=VAR_PARAMNOTFOUND;
-          varVariant:
-            begin
+        begin
+          arg_advanced:=false;
+          case arg_type of
+            varError:
+              begin
+                arg_data^.vError:=VAR_PARAMNOTFOUND;
+                arg_advanced := true;
+              end;
+            varVariant:
               arg_data^ := PVarData(PPointer(arg_ptr)^)^;
-              Inc(arg_ptr,sizeof(Pointer));
-            end;
-          varDouble, varCurrency, varInt64, varQWord:
-            begin
-              arg_data^.vQWord := PQWord(arg_ptr)^; // 64bit on all platforms
-              inc(arg_ptr,sizeof(qword))
-            end
-        else
-          arg_data^.vAny := PPointer(arg_ptr)^; // 32 or 64bit
-          inc(arg_ptr,sizeof(pointer))
+            varDouble, varCurrency, varDate, varInt64, varQWord:
+              begin
+                arg_data^.vQWord := PQWord(arg_ptr)^; // 64bit on all platforms
+                inc(arg_ptr,sizeof(QWord));
+                arg_advanced := true;
+              end;
+            { values potentially smaller than sizeof(pointer) must be handled
+              explicitly to guarantee endian safety and to prevent copying/
+              skipping data (they are always copied into a 4 byte element
+              by the compiler, although it will still skip sizeof(pointer)
+              bytes afterwards) }
+            varSingle:
+              arg_data^.vSingle := PSingle(arg_ptr)^;
+            varSmallint:
+              arg_data^.vSmallInt := PLongint(arg_ptr)^;
+            varInteger:
+              arg_data^.vInteger := PLongint(arg_ptr)^;
+            varBoolean:
+              arg_data^.vBoolean := WordBool(PLongint(arg_ptr)^);
+            varShortInt:
+              arg_data^.vShortInt := PLongint(arg_ptr)^;
+            varByte:
+              arg_data^.vByte := PLongint(arg_ptr)^;
+            varWord:
+              arg_data^.vWord := PLongint(arg_ptr)^;
+            else
+              arg_data^.vAny := PPointer(arg_ptr)^; // 32 or 64bit
+          end;
+          if not arg_advanced then
+            inc(arg_ptr,sizeof(pointer));
         end;
     end;
   end;

+ 92 - 13
tests/webtbs/tw26773.pp

@@ -49,10 +49,22 @@ function TSampleVariant.GetProperty(var Dest: TVarData; const V: TVarData;
   const Name: string): Boolean;
 begin
   assert(V.VType=varType);
-  if Name='AnyField' then begin
-    variant(Dest) := V.VInt64;
-    result := true;
-  end else
+  if Name='IntField' then
+    begin
+      variant(Dest) := V.VInt64;
+      result := true;
+    end
+  else if Name='FloatField' then
+    begin
+      variant(Dest) := V.VDouble;
+      result := true;
+    end
+  else if Name='BoolField' then
+    begin
+      variant(Dest) := V.VBoolean;
+      result := true;
+    end
+  else
     result := false;
 end;
 
@@ -60,23 +72,90 @@ function TSampleVariant.SetProperty(var V: TVarData; const Name: string;
   const Value: TVarData): Boolean;
 begin
   assert(V.VType=varType);
-  if Name='AnyField' then begin
-    PVarData(@V)^.VInt64 := variant(Value);
-    result := true;
-  end else
+  if Name='IntField' then
+    begin
+      PVarData(@V)^.VInt64 := variant(Value);
+      result := true;
+    end
+  else if Name='FloatField' then
+    begin
+      PVarData(@V)^.VDouble := variant(Value);
+      result := true;
+    end
+  else if Name='BoolField' then
+    begin
+      PVarData(@V)^.VBoolean := variant(Value);
+      result := true;
+    end
+  else
     result := false;
 end;
 
 var
   SampleVariant: TSampleVariant;
   v: Variant;
+
+  GB1 : Byte;
+  GS1 : Shortint;
+  GW : Word;
+  GL : longint;
+  gsi : single;
+  gd : double;
+  gi64 : int64;
+  gdate: tdatetime;
+  gb: boolean;
 begin
   SampleVariant:=TSampleVariant.Create;
   v := null;
   TVarData(v).VType:=SampleVariant.VarType;
-  v.AnyField := 100;
-  if v.AnyField=100 then
-    Halt(0) 
-  else
+  v.IntField := 100;
+  if v.IntField<>100 then
     halt(1);
-end.
+
+  gb1:=128;
+  gs1:=127;
+  gw:=32768;
+  gl:=longint($b100dbad);
+  gsi:=12345789.5;
+  gd:=999991234889879.5;
+  gi64:=$813245678901234;
+  gdate:=now;
+  gb:=false;
+
+  v.IntField:=gb1;
+  if v.IntField<>gb1 then
+    halt(2);
+
+  v.IntField:=gs1;
+  if v.IntField<>gs1 then
+    halt(3);
+
+  v.IntField:=gw;
+  if v.IntField<>gw then
+    halt(4);
+
+  v.IntField:=gl;
+  if v.IntField<>gl then
+    halt(5);
+
+  v.FloatField:=gsi;
+  if v.FloatField<>gsi then
+    halt(6);
+
+  v.FloatField:=gd;
+  if v.FloatField<>gd then
+    halt(7);
+
+  v.IntField:=gi64;
+  if v.IntField<>gi64 then
+    halt(8);
+
+  v.FloatField:=gdate;
+  if v.FloatField<>gdate then
+    halt(9);
+
+  v.BoolField:=gb;
+  if boolean(v.BoolField)<>gb then
+    halt(10);
+
+end.