mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-13 11:49:30 +02:00
* fixed val(s,int64) (it accepted values in the range
high(int64+1)..high(qword) if written in decimal notation) + test * fixed range checking of qword constants parsed by the compiler (they always gave a range error if > high(int64), because the compiler internally stores them as int64) * turn off range checking flag of rdconstnodes created by the parser from _INTCONST, because those are already range checked by the way they are parsed using val() git-svn-id: trunk@6814 -
This commit is contained in:
parent
d79d29ccda
commit
69cf42c4f7
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -6264,6 +6264,7 @@ tests/tbs/tb0528.pp svneol=native#text/x-pascal
|
|||||||
tests/tbs/tb0530.pp svneol=native#text/plain
|
tests/tbs/tb0530.pp svneol=native#text/plain
|
||||||
tests/tbs/tb0531.pp svneol=native#text/plain
|
tests/tbs/tb0531.pp svneol=native#text/plain
|
||||||
tests/tbs/tb0532.pp svneol=native#text/x-pascal
|
tests/tbs/tb0532.pp svneol=native#text/x-pascal
|
||||||
|
tests/tbs/tb0533.pp svneol=native#text/plain
|
||||||
tests/tbs/ub0060.pp svneol=native#text/plain
|
tests/tbs/ub0060.pp svneol=native#text/plain
|
||||||
tests/tbs/ub0069.pp svneol=native#text/plain
|
tests/tbs/ub0069.pp svneol=native#text/plain
|
||||||
tests/tbs/ub0119.pp svneol=native#text/plain
|
tests/tbs/ub0119.pp svneol=native#text/plain
|
||||||
|
@ -198,10 +198,10 @@ interface
|
|||||||
{# Returns true, if def is a 64 bit type }
|
{# Returns true, if def is a 64 bit type }
|
||||||
function is_64bit(def : tdef) : boolean;
|
function is_64bit(def : tdef) : boolean;
|
||||||
|
|
||||||
{# If @var(l) isn't in the range of def a range check error (if not explicit) is generated and
|
{# If @var(l) isn't in the range of todef a range check error (if not explicit) is generated and
|
||||||
the value is placed within the range
|
the value is placed within the range
|
||||||
}
|
}
|
||||||
procedure testrange(def : tdef;var l : tconstexprint;explicit:boolean);
|
procedure testrange(fromdef, todef : tdef;var l : tconstexprint;explicit:boolean);
|
||||||
|
|
||||||
{# Returns the range of def, where @var(l) is the low-range and @var(h) is
|
{# Returns the range of def, where @var(l) is the low-range and @var(h) is
|
||||||
the high-range.
|
the high-range.
|
||||||
@ -693,9 +693,9 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ if l isn't in the range of def a range check error (if not explicit) is generated and
|
{ if l isn't in the range of todef a range check error (if not explicit) is generated and
|
||||||
the value is placed within the range }
|
the value is placed within the range }
|
||||||
procedure testrange(def : tdef;var l : tconstexprint;explicit:boolean);
|
procedure testrange(fromdef, todef : tdef;var l : tconstexprint;explicit:boolean);
|
||||||
var
|
var
|
||||||
lv,hv: TConstExprInt;
|
lv,hv: TConstExprInt;
|
||||||
error: boolean;
|
error: boolean;
|
||||||
@ -703,9 +703,14 @@ implementation
|
|||||||
error := false;
|
error := false;
|
||||||
{ for 64 bit types we need only to check if it is less than }
|
{ for 64 bit types we need only to check if it is less than }
|
||||||
{ zero, if def is a qword node }
|
{ zero, if def is a qword node }
|
||||||
if is_64bitint(def) then
|
if is_64bitint(todef) then
|
||||||
begin
|
begin
|
||||||
if (l<0) and (torddef(def).ordtype=u64bit) then
|
if (l<0) and
|
||||||
|
(torddef(todef).ordtype=u64bit) and
|
||||||
|
{ since tconstexprint is an int64, values > high(int64) will }
|
||||||
|
{ always be stored as negative numbers }
|
||||||
|
(not is_64bitint(fromdef) or
|
||||||
|
(torddef(fromdef).ordtype<>u64bit)) then
|
||||||
begin
|
begin
|
||||||
{ don't zero the result, because it may come from hex notation
|
{ don't zero the result, because it may come from hex notation
|
||||||
like $ffffffffffffffff! (JM)
|
like $ffffffffffffffff! (JM)
|
||||||
@ -722,12 +727,12 @@ implementation
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
getrange(def,lv,hv);
|
getrange(todef,lv,hv);
|
||||||
if (l<lv) or (l>hv) then
|
if (l<lv) or (l>hv) then
|
||||||
begin
|
begin
|
||||||
if not explicit then
|
if not explicit then
|
||||||
begin
|
begin
|
||||||
if ((def.typ=enumdef) and
|
if ((todef.typ=enumdef) and
|
||||||
{ delphi allows range check errors in
|
{ delphi allows range check errors in
|
||||||
enumeration type casts FK }
|
enumeration type casts FK }
|
||||||
not(m_delphi in current_settings.modeswitches)) or
|
not(m_delphi in current_settings.modeswitches)) or
|
||||||
@ -742,16 +747,16 @@ implementation
|
|||||||
if error then
|
if error then
|
||||||
begin
|
begin
|
||||||
{ Fix the value to fit in the allocated space for this type of variable }
|
{ Fix the value to fit in the allocated space for this type of variable }
|
||||||
case longint(def.size) of
|
case longint(todef.size) of
|
||||||
1: l := l and $ff;
|
1: l := l and $ff;
|
||||||
2: l := l and $ffff;
|
2: l := l and $ffff;
|
||||||
{ work around sign extension bug (to be fixed) (JM) }
|
{ work around sign extension bug (to be fixed) (JM) }
|
||||||
4: l := l and (int64($fffffff) shl 4 + $f);
|
4: l := l and (int64($fffffff) shl 4 + $f);
|
||||||
end;
|
end;
|
||||||
{ do sign extension if necessary (JM) }
|
{ do sign extension if necessary (JM) }
|
||||||
if is_signed(def) then
|
if is_signed(todef) then
|
||||||
begin
|
begin
|
||||||
case longint(def.size) of
|
case longint(todef.size) of
|
||||||
1: l := shortint(l);
|
1: l := shortint(l);
|
||||||
2: l := smallint(l);
|
2: l := smallint(l);
|
||||||
4: l := longint(l);
|
4: l := longint(l);
|
||||||
|
@ -1830,10 +1830,10 @@ implementation
|
|||||||
not(convtype=tc_char_2_char) then
|
not(convtype=tc_char_2_char) then
|
||||||
begin
|
begin
|
||||||
{ replace the resultdef and recheck the range }
|
{ replace the resultdef and recheck the range }
|
||||||
left.resultdef:=resultdef;
|
|
||||||
if ([nf_explicit,nf_internal] * flags <> []) then
|
if ([nf_explicit,nf_internal] * flags <> []) then
|
||||||
include(left.flags, nf_explicit);
|
include(left.flags, nf_explicit);
|
||||||
testrange(left.resultdef,tordconstnode(left).value,(nf_explicit in flags));
|
testrange(left.resultdef,resultdef,tordconstnode(left).value,(nf_explicit in flags));
|
||||||
|
left.resultdef:=resultdef;
|
||||||
result:=left;
|
result:=left;
|
||||||
left:=nil;
|
left:=nil;
|
||||||
exit;
|
exit;
|
||||||
|
@ -623,7 +623,7 @@ implementation
|
|||||||
resultdef:=typedef;
|
resultdef:=typedef;
|
||||||
{ only do range checking when explicitly asked for it }
|
{ only do range checking when explicitly asked for it }
|
||||||
if rangecheck then
|
if rangecheck then
|
||||||
testrange(resultdef,value,false);
|
testrange(resultdef,resultdef,value,false);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function tordconstnode.pass_1 : tnode;
|
function tordconstnode.pass_1 : tnode;
|
||||||
|
@ -1419,9 +1419,9 @@ implementation
|
|||||||
(index.left.nodetype = ordconstn) and
|
(index.left.nodetype = ordconstn) and
|
||||||
not is_special_array(unpackedarraydef) then
|
not is_special_array(unpackedarraydef) then
|
||||||
begin
|
begin
|
||||||
testrange(unpackedarraydef,tordconstnode(index.left).value,false);
|
testrange(index.left.resultdef,unpackedarraydef,tordconstnode(index.left).value,false);
|
||||||
tempindex := tordconstnode(index.left).value + packedarraydef.highrange-packedarraydef.lowrange;
|
tempindex := tordconstnode(index.left).value + packedarraydef.highrange-packedarraydef.lowrange;
|
||||||
testrange(unpackedarraydef,tempindex,false);
|
testrange(index.left.resultdef,unpackedarraydef,tempindex,false);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -2459,7 +2459,10 @@ implementation
|
|||||||
consume(_INTCONST);
|
consume(_INTCONST);
|
||||||
p1:=crealconstnode.create(d,pbestrealtype^);
|
p1:=crealconstnode.create(d,pbestrealtype^);
|
||||||
end;
|
end;
|
||||||
end;
|
end
|
||||||
|
else
|
||||||
|
{ the necessary range checking has already been done by val }
|
||||||
|
tordconstnode(p1).rangecheck:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
_REALNUMBER :
|
_REALNUMBER :
|
||||||
|
@ -183,8 +183,8 @@ implementation
|
|||||||
CGMessage(parser_e_case_lower_less_than_upper_bound);
|
CGMessage(parser_e_case_lower_less_than_upper_bound);
|
||||||
if not casedeferror then
|
if not casedeferror then
|
||||||
begin
|
begin
|
||||||
testrange(casedef,hl1,false);
|
testrange(casedef,casedef,hl1,false);
|
||||||
testrange(casedef,hl2,false);
|
testrange(casedef,casedef,hl2,false);
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -198,7 +198,7 @@ implementation
|
|||||||
CGMessage(parser_e_case_mismatch);
|
CGMessage(parser_e_case_mismatch);
|
||||||
hl1:=get_ordinal_value(p);
|
hl1:=get_ordinal_value(p);
|
||||||
if not casedeferror then
|
if not casedeferror then
|
||||||
testrange(casedef,hl1,false);
|
testrange(casedef,casedef,hl1,false);
|
||||||
casenode.addlabel(blockid,hl1,hl1);
|
casenode.addlabel(blockid,hl1,hl1);
|
||||||
end;
|
end;
|
||||||
p.free;
|
p.free;
|
||||||
|
@ -233,7 +233,7 @@ implementation
|
|||||||
begin
|
begin
|
||||||
if is_constintnode(n) then
|
if is_constintnode(n) then
|
||||||
begin
|
begin
|
||||||
testrange(def,tordconstnode(n).value,false);
|
testrange(n.resultdef,def,tordconstnode(n).value,false);
|
||||||
case def.size of
|
case def.size of
|
||||||
1 :
|
1 :
|
||||||
list.concat(Tai_const.Create_8bit(byte(tordconstnode(n).value)));
|
list.concat(Tai_const.Create_8bit(byte(tordconstnode(n).value)));
|
||||||
|
@ -879,7 +879,7 @@ end;
|
|||||||
|
|
||||||
Function fpc_val_int64_shortstr(Const S: ShortString; out Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR']; compilerproc;
|
Function fpc_val_int64_shortstr(Const S: ShortString; out Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR']; compilerproc;
|
||||||
|
|
||||||
var u, temp, prev : qword;
|
var u, temp, prev, maxprevvalue, maxnewvalue : qword;
|
||||||
base : byte;
|
base : byte;
|
||||||
negative : boolean;
|
negative : boolean;
|
||||||
|
|
||||||
@ -892,6 +892,11 @@ end;
|
|||||||
Code:=InitVal(s,negative,base);
|
Code:=InitVal(s,negative,base);
|
||||||
if Code>length(s) then
|
if Code>length(s) then
|
||||||
exit;
|
exit;
|
||||||
|
maxprevvalue := maxqword div base;
|
||||||
|
if (base = 10) then
|
||||||
|
maxnewvalue := maxint64 + ord(negative)
|
||||||
|
else
|
||||||
|
maxnewvalue := maxqword;
|
||||||
|
|
||||||
while Code<=Length(s) do
|
while Code<=Length(s) do
|
||||||
begin
|
begin
|
||||||
@ -904,13 +909,10 @@ end;
|
|||||||
u:=16;
|
u:=16;
|
||||||
end;
|
end;
|
||||||
Prev:=Temp;
|
Prev:=Temp;
|
||||||
Temp:=Temp*Int64(base);
|
Temp:=Temp*qword(base);
|
||||||
If (u >= base) or
|
If (u >= base) or
|
||||||
((base = 10) and
|
(qword(maxnewvalue-u) < temp) or
|
||||||
(maxint64-temp+ord(negative) < u)) or
|
(prev > maxprevvalue) Then
|
||||||
((base <> 10) and
|
|
||||||
(qword(maxqword-temp) < u)) or
|
|
||||||
(prev > maxqword div qword(base)) Then
|
|
||||||
Begin
|
Begin
|
||||||
fpc_val_int64_shortstr := 0;
|
fpc_val_int64_shortstr := 0;
|
||||||
Exit
|
Exit
|
||||||
|
25
tests/tbs/tb0533.pp
Normal file
25
tests/tbs/tb0533.pp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{$r+}
|
||||||
|
|
||||||
|
const
|
||||||
|
q: qword = 18446744073709551615;
|
||||||
|
|
||||||
|
var
|
||||||
|
i: int64;
|
||||||
|
code: longint;
|
||||||
|
begin
|
||||||
|
val('18446744073709551615',i,code);
|
||||||
|
if (code = 0) then
|
||||||
|
halt(1);
|
||||||
|
val('-9223372036854775808',i,code);
|
||||||
|
if (code <> 0) or
|
||||||
|
(i <> low(int64)) then
|
||||||
|
halt(2);
|
||||||
|
val('9223372036854775807',i,code);
|
||||||
|
if (code <> 0) or
|
||||||
|
(i <> high(int64)) then
|
||||||
|
halt(3);
|
||||||
|
val('$8000000000000000',i,code);
|
||||||
|
if (code <> 0) or
|
||||||
|
(i <> low(int64)) then
|
||||||
|
halt(4);
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user