diff --git a/rtl/inc/sstrings.inc b/rtl/inc/sstrings.inc index 010bd6a730..fe934bb296 100644 --- a/rtl/inc/sstrings.inc +++ b/rtl/inc/sstrings.inc @@ -1154,33 +1154,41 @@ end; Function fpc_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; compilerproc; var - temp, prev, maxPrevValue, maxNewValue: ValUInt; + temp, prev, maxPrevValue: ValUInt; base,u : byte; - negative, RolledOver: boolean; - SignedLower, SignedUpper: Int64; - UnsignedUpper: UInt64; - RolledOverAt: integer; - RollOverPoint: ValUInt; + negative: boolean; + UnsignedUpperLimit: ValUInt; const - ValueArray : array['0'..'f'] of byte = (0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,10,11,12,13,14,15, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + ValueArray : array['0'..'f'] of byte = (0,1,2,3,4,5,6,7,8,9,$FF,$FF,$FF,$FF,$FF,$FF,$FF,10,11,12,13,14,15, + $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF, 10,11,12,13,14,15); begin fpc_Val_SInt_ShortStr := 0; Temp:=0; Code:=InitVal(s,negative,base); - case DestSize of - 1: begin SignedLower:=Low(ShortInt); SignedUpper:=(High(ShortInt)); UnSignedUpper:=High(Byte) end; - 2: begin SignedLower:=Low(SmallInt); SignedUpper:=(High(SmallInt)); UnSignedUpper:=High(Word) end; - 4: begin SignedLower:=Low(LongInt); SignedUpper:=(High(LongInt)); UnSignedUpper:=High(DWord) end; - 8: begin SignedLower:=Low(Int64); SignedUpper:=(High(Int64)); UnSignedUpper:=High(QWord) end; - end; - RolledOver:=False; - if negative then - RollOverPoint:=-SignedLower + if (base=10) or negative then + begin //always limit to either Low(DestType) or High(DestType) + case DestSize of + 1: UnsignedUpperLimit := ValUInt(High(ShortInt))+Ord(negative); + 2: UnsignedUpperLimit := ValUInt(High(SmallInt))+Ord(negative); + 4: UnsignedUpperLimit := ValUInt(High(LongInt))+Ord(negative); + {$ifdef CPU64} + 8: UnsignedUpperLimit := ValUInt(High(Int64))+Ord(negative); + {$endif CPU64} + end; + end else - RollOverPoint:=SignedUpper; + begin //not decimal and not negative + case DestSize of + 1: UnsignedUpperLimit := High(Byte); + 2: UnsignedUpperLimit := High(Word); + 4: UnsignedUpperLimit := High(DWord); + {$ifdef CPU64} + 8: UnsignedUpperLimit := High(UInt64); + {$endif CPU64} + end; + end; if Code>length(s) then exit; @@ -1190,11 +1198,8 @@ begin Code:=0; exit; end; + maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base); - if (base = 10) then - maxNewValue := MaxSIntValue + ord(negative) - else - maxNewValue := MaxUIntValue; while Code<=Length(s) do begin @@ -1208,19 +1213,14 @@ begin Prev := Temp; Temp := Temp*ValUInt(base); + If (u >= base) or - (ValUInt(maxNewValue-u) < Temp) or - (prev > maxPrevValue) or - ((Temp+u)>UnsignedUpper) Then + (prev > maxPrevValue) + or ((Temp)>(UnsignedUpperLimit-u)) Then Begin fpc_Val_SInt_ShortStr := 0; Exit End; - if (not RolledOver) and ((Temp+u)>RollOverPoint) then - begin - RolledOver := True; - RolledOverAt := Code; - end; Temp:=Temp+u; inc(code); end; @@ -1230,13 +1230,6 @@ begin If Negative Then fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr; - if RolledOver and ((base=10) or ((base<>10) and (negative))) {and (not negative)} then - begin - fpc_Val_SInt_ShortStr:=0; - Code := RolledOverAt; - exit; - end; - If Not(Negative) and (base <> 10) Then {sign extend the result to allow proper range checking} Case DestSize of