mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 15:09:20 +02:00
pastojs: range check of proc argument integer
git-svn-id: trunk@38016 -
This commit is contained in:
parent
1a301b5cce
commit
b4d8ea7477
@ -269,12 +269,21 @@ Works:
|
|||||||
- Assert(bool[,string])
|
- Assert(bool[,string])
|
||||||
- without sysutils: if(bool) throw string
|
- without sysutils: if(bool) throw string
|
||||||
- with sysutils: if(bool) throw pas.sysutils.EAssertionFailed.$create("Create",[string])
|
- with sysutils: if(bool) throw pas.sysutils.EAssertionFailed.$create("Create",[string])
|
||||||
- $Objectchecks:
|
- Object checks:
|
||||||
- Method call EInvalidCast, rtl.checkMethodCall
|
- Method call EInvalidCast, rtl.checkMethodCall
|
||||||
- type cast to class-type and class-of-type, rtl.asExt, EInvalidCast
|
- type cast to class-type and class-of-type, rtl.asExt, EInvalidCast
|
||||||
-
|
- Range checks:
|
||||||
|
- assign int:=, int+=
|
||||||
|
- procedure argument int
|
||||||
|
|
||||||
ToDos:
|
ToDos:
|
||||||
|
- range checks:
|
||||||
|
- proc args
|
||||||
|
- assign enum:=, enum+=
|
||||||
|
- prop:=
|
||||||
|
- string[index]
|
||||||
|
- array[index]
|
||||||
|
- prop[index]
|
||||||
- typecast longint(highprecint) -> value & $ffffffff
|
- typecast longint(highprecint) -> value & $ffffffff
|
||||||
- static arrays
|
- static arrays
|
||||||
- a[] of record
|
- a[] of record
|
||||||
@ -1257,6 +1266,8 @@ type
|
|||||||
AContext: TConvertContext): TJSElement; virtual;
|
AContext: TConvertContext): TJSElement; virtual;
|
||||||
Function CreateProcCallArgRef(El: TPasExpr; ResolvedEl: TPasResolverResult;
|
Function CreateProcCallArgRef(El: TPasExpr; ResolvedEl: TPasResolverResult;
|
||||||
TargetArg: TPasArgument; AContext: TConvertContext): TJSElement; virtual;
|
TargetArg: TPasArgument; AContext: TConvertContext): TJSElement; virtual;
|
||||||
|
Function CreateArgumentAccess(Arg: TPasArgument; AContext: TConvertContext;
|
||||||
|
PosEl: TPasElement): TJSElement; virtual;
|
||||||
Function CreateUnary(Members: array of string; E: TJSElement): TJSUnary;
|
Function CreateUnary(Members: array of string; E: TJSElement): TJSUnary;
|
||||||
Function CreateMemberExpression(Members: array of string): TJSDotMemberExpression;
|
Function CreateMemberExpression(Members: array of string): TJSDotMemberExpression;
|
||||||
Function CreateCallExpression(El: TPasElement): TJSCallExpression;
|
Function CreateCallExpression(El: TPasElement): TJSCallExpression;
|
||||||
@ -4809,8 +4820,6 @@ var
|
|||||||
Prop: TPasProperty;
|
Prop: TPasProperty;
|
||||||
ImplicitCall: Boolean;
|
ImplicitCall: Boolean;
|
||||||
AssignContext: TAssignContext;
|
AssignContext: TAssignContext;
|
||||||
Arg: TPasArgument;
|
|
||||||
ParamContext: TParamContext;
|
|
||||||
ResolvedEl: TPasResolverResult;
|
ResolvedEl: TPasResolverResult;
|
||||||
ProcType, TargetProcType: TPasProcedureType;
|
ProcType, TargetProcType: TPasProcedureType;
|
||||||
ArrLit: TJSArrayLiteral;
|
ArrLit: TJSArrayLiteral;
|
||||||
@ -4917,49 +4926,8 @@ begin
|
|||||||
end
|
end
|
||||||
else if Decl.ClassType=TPasArgument then
|
else if Decl.ClassType=TPasArgument then
|
||||||
begin
|
begin
|
||||||
Arg:=TPasArgument(Decl);
|
Result:=CreateArgumentAccess(TPasArgument(Decl),AContext,El);
|
||||||
if Arg.Access in [argVar,argOut] then
|
exit;
|
||||||
begin
|
|
||||||
// Arg is a reference object
|
|
||||||
case AContext.Access of
|
|
||||||
caRead:
|
|
||||||
begin
|
|
||||||
// create arg.get()
|
|
||||||
Call:=CreateCallExpression(El);
|
|
||||||
Call.Expr:=CreateDotExpression(El,
|
|
||||||
CreateIdentifierExpr(Arg.Name,Arg,AContext),
|
|
||||||
CreatePrimitiveDotExpr(TempRefObjGetterName,El));
|
|
||||||
Result:=Call;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
caAssign:
|
|
||||||
begin
|
|
||||||
// create arg.set(RHS)
|
|
||||||
AssignContext:=AContext.AccessContext as TAssignContext;
|
|
||||||
if AssignContext.Call<>nil then
|
|
||||||
RaiseNotSupported(El,AContext,20170214120606);
|
|
||||||
Call:=CreateCallExpression(El);
|
|
||||||
AssignContext.Call:=Call;
|
|
||||||
Call.Expr:=CreateDotExpression(El,
|
|
||||||
CreateIdentifierExpr(Arg.Name,Arg,AContext),
|
|
||||||
CreatePrimitiveDotExpr(TempRefObjSetterName,El));
|
|
||||||
Call.AddArg(AssignContext.RightSide);
|
|
||||||
AssignContext.RightSide:=nil;
|
|
||||||
Result:=Call;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
caByReference:
|
|
||||||
begin
|
|
||||||
// simply pass the reference
|
|
||||||
ParamContext:=AContext.AccessContext as TParamContext;
|
|
||||||
ParamContext.ReusingReference:=true;
|
|
||||||
Result:=CreateIdentifierExpr(Arg.Name,Arg,AContext);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
RaiseNotSupported(El,AContext,20170214120739);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end
|
end
|
||||||
else if Decl.ClassType=TPasResString then
|
else if Decl.ClassType=TPasResString then
|
||||||
begin
|
begin
|
||||||
@ -9207,7 +9175,7 @@ var
|
|||||||
Var
|
Var
|
||||||
FS : TJSFunctionDeclarationStatement;
|
FS : TJSFunctionDeclarationStatement;
|
||||||
FD : TJSFuncDef;
|
FD : TJSFuncDef;
|
||||||
n:Integer;
|
n, i:Integer;
|
||||||
AssignSt: TJSSimpleAssignStatement;
|
AssignSt: TJSSimpleAssignStatement;
|
||||||
FuncContext: TFunctionContext;
|
FuncContext: TFunctionContext;
|
||||||
ProcScope, ImplProcScope: TPasProcedureScope;
|
ProcScope, ImplProcScope: TPasProcedureScope;
|
||||||
@ -9218,6 +9186,8 @@ Var
|
|||||||
PosEl: TPasElement;
|
PosEl: TPasElement;
|
||||||
Call: TJSCallExpression;
|
Call: TJSCallExpression;
|
||||||
ClassPath: String;
|
ClassPath: String;
|
||||||
|
ArgResolved: TPasResolverResult;
|
||||||
|
MinVal, MaxVal: MaxPrecInt;
|
||||||
begin
|
begin
|
||||||
Result:=nil;
|
Result:=nil;
|
||||||
|
|
||||||
@ -9262,7 +9232,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
BodyPas:=ImplProc.Body;
|
BodyPas:=ImplProc.Body;
|
||||||
if (BodyPas<>nil) or (bsObjectChecks in ImplProcScope.ScannerBoolSwitches) then
|
if BodyPas<>nil then
|
||||||
begin
|
begin
|
||||||
PosEl:=BodyPas;
|
PosEl:=BodyPas;
|
||||||
if PosEl=nil then
|
if PosEl=nil then
|
||||||
@ -9273,6 +9243,31 @@ begin
|
|||||||
FuncContext.ScannerBoolSwitches:=ImplProcScope.ScannerBoolSwitches;
|
FuncContext.ScannerBoolSwitches:=ImplProcScope.ScannerBoolSwitches;
|
||||||
FirstSt:=nil;
|
FirstSt:=nil;
|
||||||
LastSt:=nil;
|
LastSt:=nil;
|
||||||
|
|
||||||
|
if (bsRangeChecks in ImplProcScope.ScannerBoolSwitches)
|
||||||
|
and (AContext.Resolver<>nil) then
|
||||||
|
for i:=0 to El.ProcType.Args.Count-1 do
|
||||||
|
begin
|
||||||
|
Arg:=TPasArgument(El.ProcType.Args[i]);
|
||||||
|
if Arg.ArgType=nil then continue;
|
||||||
|
AContext.Resolver.ComputeElement(Arg,ArgResolved,[rcType]);
|
||||||
|
if ArgResolved.BaseType in btAllJSInteger then
|
||||||
|
begin
|
||||||
|
if AContext.Resolver.ResolveAliasType(ArgResolved.TypeEl) is TPasUnresolvedSymbolRef then
|
||||||
|
begin
|
||||||
|
if not AContext.Resolver.GetIntegerRange(ArgResolved.BaseType,MinVal,MaxVal) then
|
||||||
|
RaiseNotSupported(Arg,AContext,20180119192608);
|
||||||
|
// use Arg as PosEl, so that user knows which Arg is out of range
|
||||||
|
Call:=CreateCallExpression(Arg);
|
||||||
|
Call.Expr:=CreatePrimitiveDotExpr(FBuiltInNames[pbivnRTL]+'.'+FBuiltInNames[pbifnRangeCheckInt],El);
|
||||||
|
AddBodyStatement(Call,Arg);
|
||||||
|
Call.AddArg(CreateArgumentAccess(Arg,AContext,Arg));
|
||||||
|
Call.AddArg(CreateLiteralNumber(Arg,MinVal));
|
||||||
|
Call.AddArg(CreateLiteralNumber(Arg,MaxVal));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
if ProcScope.ClassScope<>nil then
|
if ProcScope.ClassScope<>nil then
|
||||||
begin
|
begin
|
||||||
// method or class method
|
// method or class method
|
||||||
@ -10872,7 +10867,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if AssignContext.LeftResolved.BaseType in btAllJSInteger then
|
if AssignContext.LeftResolved.BaseType in btAllJSInteger then
|
||||||
begin
|
begin
|
||||||
if AssignContext.LeftResolved.TypeEl is TPasUnresolvedSymbolRef then
|
if AContext.Resolver.ResolveAliasType(AssignContext.LeftResolved.TypeEl) is TPasUnresolvedSymbolRef then
|
||||||
begin
|
begin
|
||||||
if not AContext.Resolver.GetIntegerRange(AssignContext.LeftResolved.BaseType,MinVal,MaxVal) then
|
if not AContext.Resolver.GetIntegerRange(AssignContext.LeftResolved.BaseType,MinVal,MaxVal) then
|
||||||
RaiseNotSupported(El.left,AContext,20180119154120);
|
RaiseNotSupported(El.left,AContext,20180119154120);
|
||||||
@ -13115,6 +13110,62 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasToJSConverter.CreateArgumentAccess(Arg: TPasArgument;
|
||||||
|
AContext: TConvertContext; PosEl: TPasElement): TJSElement;
|
||||||
|
var
|
||||||
|
Call: TJSCallExpression;
|
||||||
|
AssignContext: TAssignContext;
|
||||||
|
ParamContext: TParamContext;
|
||||||
|
Name: String;
|
||||||
|
begin
|
||||||
|
if Arg.Access in [argVar,argOut] then
|
||||||
|
begin
|
||||||
|
// Arg is a reference object
|
||||||
|
case AContext.Access of
|
||||||
|
caRead:
|
||||||
|
begin
|
||||||
|
// create arg.get()
|
||||||
|
Call:=CreateCallExpression(PosEl);
|
||||||
|
Call.Expr:=CreateDotExpression(PosEl,
|
||||||
|
CreateIdentifierExpr(Arg.Name,PosEl,AContext),
|
||||||
|
CreatePrimitiveDotExpr(TempRefObjGetterName,PosEl));
|
||||||
|
Result:=Call;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
caAssign:
|
||||||
|
begin
|
||||||
|
// create arg.set(RHS)
|
||||||
|
AssignContext:=AContext.AccessContext as TAssignContext;
|
||||||
|
if AssignContext.Call<>nil then
|
||||||
|
RaiseNotSupported(Arg,AContext,20170214120606);
|
||||||
|
Call:=CreateCallExpression(PosEl);
|
||||||
|
AssignContext.Call:=Call;
|
||||||
|
Call.Expr:=CreateDotExpression(PosEl,
|
||||||
|
CreateIdentifierExpr(Arg.Name,PosEl,AContext),
|
||||||
|
CreatePrimitiveDotExpr(TempRefObjSetterName,PosEl));
|
||||||
|
Call.AddArg(AssignContext.RightSide);
|
||||||
|
AssignContext.RightSide:=nil;
|
||||||
|
Result:=Call;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
caByReference:
|
||||||
|
begin
|
||||||
|
// simply pass the reference
|
||||||
|
ParamContext:=AContext.AccessContext as TParamContext;
|
||||||
|
ParamContext.ReusingReference:=true;
|
||||||
|
Result:=CreateIdentifierExpr(Arg.Name,PosEl,AContext);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
RaiseNotSupported(Arg,AContext,20170214120739);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Name:=Arg.Name;
|
||||||
|
if (CompareText(Name,'Self')=0) and (AContext.GetSelfContext<>nil) then
|
||||||
|
Name:=AContext.GetLocalName(Arg);
|
||||||
|
Result:=CreatePrimitiveDotExpr(Name,PosEl);
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasToJSConverter.ConvertExceptOn(El: TPasImplExceptOn;
|
function TPasToJSConverter.ConvertExceptOn(El: TPasImplExceptOn;
|
||||||
AContext: TConvertContext): TJSElement;
|
AContext: TConvertContext): TJSElement;
|
||||||
// convert "on T do ;" to "if(T.isPrototypeOf(exceptObject)){}"
|
// convert "on T do ;" to "if(T.isPrototypeOf(exceptObject)){}"
|
||||||
|
@ -15980,14 +15980,14 @@ begin
|
|||||||
'var',
|
'var',
|
||||||
' b: byte;',
|
' b: byte;',
|
||||||
' w: word;',
|
' w: word;',
|
||||||
'procedure DoIt;',
|
'procedure DoIt(p: byte);',
|
||||||
'begin',
|
'begin',
|
||||||
' b:=w;',
|
' b:=w;',
|
||||||
' b+=w;',
|
' b+=w;',
|
||||||
'end;',
|
'end;',
|
||||||
'{$R-}',
|
'{$R-}',
|
||||||
'begin',
|
'begin',
|
||||||
' DoIt;',
|
' DoIt(w);',
|
||||||
' b:=w;',
|
' b:=w;',
|
||||||
'{$R+}',
|
'{$R+}',
|
||||||
'']);
|
'']);
|
||||||
@ -15996,13 +15996,14 @@ begin
|
|||||||
LinesToStr([ // statements
|
LinesToStr([ // statements
|
||||||
'this.b = 0;',
|
'this.b = 0;',
|
||||||
'this.w = 0;',
|
'this.w = 0;',
|
||||||
'this.DoIt = function () {',
|
'this.DoIt = function (p) {',
|
||||||
|
' rtl.rc(p, 0, 255);',
|
||||||
' $mod.b = rtl.rc($mod.w,0,255);',
|
' $mod.b = rtl.rc($mod.w,0,255);',
|
||||||
' rtl.rc($mod.b += $mod.w, 0, 255);',
|
' rtl.rc($mod.b += $mod.w, 0, 255);',
|
||||||
'};',
|
'};',
|
||||||
'']),
|
'']),
|
||||||
LinesToStr([ // $mod.$main
|
LinesToStr([ // $mod.$main
|
||||||
'$mod.DoIt();',
|
'$mod.DoIt($mod.w);',
|
||||||
'$mod.b = rtl.rc($mod.w,0,255);',
|
'$mod.b = rtl.rc($mod.w,0,255);',
|
||||||
'']));
|
'']));
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user