Copying an empty multi-dimensional variant array may raise an exception
Original Reporter info from Mantis: Dr.Sigmund
-
Reporter name: Vadim Yakovlev
Original Reporter info from Mantis: Dr.Sigmund
- Reporter name: Vadim Yakovlev
Description:
A multi-dimensional variant array is empty if at least one of its dimensions has element count equal to zero. Other dimensions may have more that 0 element counts, array is still empty. If first dimension has element count > 0, some other dimension has element count = 0 and array element type is Variant then copying of such array fails.
Steps to reproduce:
-----------Single dimension array, this code works fine---------------
var
Bounds: Array [0..0] of TVarArrayBound; V1, V2: Variant;
begin
Bounds[0].lowbound := 0;
Bounds[0].elementcount := 0;
V1 := VarArrayCreate(@Bounds, 1, varVariant);
V2 := V1;
end;
-----------Multi dimension array, first dimension has elementcount=0, this code works, too---------------
var
Bounds: Array [0..1] of TVarArrayBound; V1, V2: Variant;
begin
Bounds[0].lowbound := 0;
Bounds[0].elementcount := 0;
Bounds[1].lowbound := 0;
Bounds[1].elementcount := 0;
V1 := VarArrayCreate(@Bounds, 2, varVariant);
V2 := V1;
end;
-----------Empty multi dimension array, first dimension has elementcount>0, this code fails---------------
var
Bounds: Array [0..1] of TVarArrayBound; V1, V2: Variant;
begin
Bounds[0].lowbound := 0;
Bounds[0].elementcount := 1;
Bounds[1].lowbound := 0;
Bounds[1].elementcount := 0;
V1 := VarArrayCreate(@Bounds, 2, varVariant);
V2 := V1; // <- Exception EVariantBadIndexError!!!!!
end;
Additional information:
The problem is in method TVariantArrayIterator.AtEnd. RTL procedure DoVarCopyArray calls this method first before iterating arrays:
procedure DoVarCopyArray(...);
...
Iterator.Init(Dims, @Bounds);
try
if not(Iterator.AtEnd) then
...
For empty array in last example, function AtEnd returns False after checking just first dimension, so DoVarCopyArray starts iterating over an empty array.
function TVariantArrayIterator.AtEnd: Boolean;
var
i : sizeint;
begin
result:=true;
for i:=0 to Pred(Dims) do
if Coords^[i] < Bounds^[i].LowBound + Bounds^[i].ElementCount then
begin
result:=false;
exit;
end;
end;
Mantis conversion info:
- Mantis ID: 26370
- OS: Windows
- OS Build: 7
- Version: 2.6.4
- Fixed in version: 3.0.0
- Fixed in revision: 29324 (#ba61a9f9)