* Rewrote fpc_dynarray_copy to trim out-of-range arguments instead of raising range error. Makes behavior Delphi-compatible and resolves #21396.

* Changed copying the entire array to use range 0..high(sizeint) instead of -1..-2.

git-svn-id: trunk@20468 -
This commit is contained in:
sergei 2012-03-04 04:41:52 +00:00
parent a417e9d0b6
commit 92f927976e
3 changed files with 35 additions and 35 deletions

View File

@ -2505,6 +2505,7 @@ begin
def_system_macro('FPC_HAS_CONSTREF');
def_system_macro('FPC_STATICRIPFIXED');
def_system_macro('FPC_VARIANTCOPY_FIXED');
def_system_macro('FPC_DYNARRAYCOPY_FIXED');
{$if defined(x86) or defined(powerpc) or defined(powerpc64)}
def_system_macro('FPC_HAS_INTERNAL_ABS_LONG');
{$endif}

View File

@ -749,9 +749,9 @@ implementation
end
else
begin
{ use special -1,-1 argument to copy the whole array }
highppn:=cordconstnode.create(int64(-1),s32inttype,false);
lowppn:=cordconstnode.create(int64(-1),s32inttype,false);
{ copy the whole array using [0..high(sizeint)] range }
highppn:=cordconstnode.create(torddef(sinttype).high,sinttype,false);
lowppn:=cordconstnode.create(0,sinttype,false);
end;
{ create call to fpc_dynarray_copy }

View File

@ -248,56 +248,55 @@ function int_dynarray_copy(psrc : pointer;ti : pointer;
function fpc_dynarray_copy(psrc : pointer;ti : pointer;
lowidx,count:tdynarrayindex) : pointer;[Public,Alias:'FPC_DYNARR_COPY'];compilerproc;
var
realpdest,
realpsrc : pdynarray;
cnt,
i,size : longint;
highidx : tdynarrayindex;
i,size : sizeint;
elesize : sizeint;
eletype : pointer;
pdest : pointer;
begin
highidx:=lowidx+count-1;
pdest:=nil;
result:=pdest;
result:=nil;
if psrc=nil then
exit;
{$ifndef FPC_DYNARRAYCOPY_FIXED}
if (lowidx=-1) and (count=-1) then
begin
lowidx:=0;
count:=high(tdynarrayindex);
end;
{$endif FPC_DYNARRAYCOPY_FIXED}
realpsrc:=pdynarray(psrc-sizeof(tdynarray));
if (lowidx<0) then
begin
{ Decrease count if index is negative, this is different from how copy()
works on strings. Checked against D7. }
if count<=0 then
exit; { may overflow when adding lowidx }
count:=count+lowidx;
lowidx:=0;
end;
if (count>realpsrc^.high-lowidx+1) then
count:=realpsrc^.high-lowidx+1;
if count<=0 then
exit;
{ skip kind and name }
ti:=aligntoptr(ti+2+PByte(ti)[1]);
elesize:=pdynarraytypedata(ti)^.elSize;
eletype:=pdynarraytypedata(ti)^.elType2;
{ -1, -1 (highidx=lowidx-1-1=-3) is used to copy the whole array like a:=copy(b);, so
update the lowidx and highidx with the values from psrc }
if (lowidx=-1) and (highidx=-3) then
begin
lowidx:=0;
highidx:=realpsrc^.high;
end;
{ get number of elements and check for invalid values }
if (lowidx<0) or (highidx<0) or (lowidx > realpsrc^.high) then
HandleErrorFrame(201,get_frame);
cnt:=highidx-lowidx+1;
if (cnt > realpsrc^.high - lowidx + 1) then
cnt := realpsrc^.high - lowidx + 1;
{ create new array }
size:=elesize*cnt;
getmem(realpdest,size+sizeof(tdynarray));
pdest:=pointer(realpdest)+sizeof(tdynarray);
size:=elesize*count;
getmem(result,size+sizeof(tdynarray));
pdynarray(result)^.refcount:=1;
pdynarray(result)^.high:=count-1;
inc(result,sizeof(tdynarray));
{ copy data }
move(pointer(psrc+elesize*lowidx)^,pdest^,size);
{ fill new refcount }
realpdest^.refcount:=1;
realpdest^.high:=cnt-1;
move(pointer(psrc+elesize*lowidx)^,result^,size);
{ increment ref. count of members? }
if PByte(eletype)^ in tkManagedTypes then
for i:= 0 to cnt-1 do
int_addref(pointer(pdest+elesize*i),eletype);
result:=pdest;
for i:=0 to count-1 do
int_addref(pointer(result+elesize*i),eletype);
end;