Using high-level synthetic methods
This topic illustrates how to use some of the key features of high-level synthetic methods. For full details, see the Framework for Frameworks API classes and methods Javadoc™ documentation.
Creating a high-level synthetic method
To create a high-level synthetic method and add it
to the F4FActions
object actions
,
use code such as:
HighLevelSyntheticMethod m = HighLevelSyntheticMethod.make();
actions.addHighLevelSyntheticMethod(m);
You can specify
the name, parameter types, and return type of the synthetic method
by passing a VDB method signature to HighLevelSyntheticMethod.make()
.
Creating locals
A new
local variable for a high-level synthetic method m
can
be created in this manner:
Local l = m.newLocal("java.lang.String");
Constructors
need not be invoked in synthetic methods. Given the above code, one
can assume that l
refers to a non-null String
object
when adding further statements to the synthetic method.
Adding calls
Most statements
in high-level synthetic methods will be method calls, added via the addCall()
method.
The parameters to addCall()
represent the method
to be invoked, file position information for the invocation, and parameters
to be passed at the invocation. This is an example for adding a call
to a setter method sample.BeanType.setName()
, assuming
an F4FApp
object app
:
Collection<IMethod> setterMethods =
app.getClassMethods("sample.BeanType", "setName");
// assume there is exactly one "setName" method in BeanType
IMethod setter = setterMethods.iterator().next();
HighLevelSyntheticMethod m = HighLevelSyntheticMethod.make();
Local l = m.newLocal("sample.BeanType");
m.addCall(setter, null, l, Taint.taint());
Steps 2-5 of handling client form submission in an MVC architecture (as outlined in High-level synthetic methods) can all be modelled to some degree by adding appropriate calls to a synthetic method in the manner shown above.
The parameters for a call
are represented by objects of type Param
, which can
be any one of:
- A
Local
object, representing a local - A
Taint
object, representing untrusted or tainted data. - An
EnclosingFormal
object, representing a formal parameter of the high-level synthetic method. For example, if you have a synthetic method with signaturesynthMethod(int):void
,EnclosingFormal.FIRST
refers to theint
parameter of the method. - A
Global
object representing a global (discussed in Globals).
this
must be provided to addCall()
.
In the above example, the value in l
will be passed
as this
to setName()
.Adding a return value
A
synthetic method can return a value by using the setReturnedValue()
method.
Return values can be useful for generating marker methods to model
complex framework validation. For example, if you are using a framework
that performs complex validation of a tainted HTTP request value before
passing it to the setter method of a model object, you can expose
the validation on traces discovered by AppScan®
Source by
using code such as this:
String validatorSig =
"Synth.validatorModel(java.lang.String):
java.lang.String";
HighLevelSyntheticMethod validator =
HighLevelSyntheticMethod.make(validatorSig);
// just return the parameter passed in
validator.setReturnedValue(EnclosingFormal.FIRST);
HighLevelSyntheticMethod m = ...;
Local validated = m.addCall(validatorSig, null, Taint.taint());
// now, validated can be passed to a setter
The synthetic
method Synth.validatorModel()
simply returns the String
that
is passed to it as a parameter. Then, a call to Synth.validatorModel()
is
added in another synthetic method, passing a tainted value as an argument.
The result of this call is stored in validated
, which
can be passed in a subsequent call to a setter method (as illustrated
by example in Adding calls).
Traces involving this tainted data will include the call to Synth.validatorModel()
,
and an AppScan®
Source user
can choose to filter the traces if the validation is deemed sufficient.
Globals
Globals are an advanced feature that can be used to expose flow between disparate parts of an application. For example, globals can be used to model the flow of data from a controller to a view via request or session attributes. The key operations for creating and accessing globals are:
- To create a
Global
object representing a global, useF4FActions.createGlobal()
. - To write to a global, use
HighLevelSyntheticMethod.addGlobalWrite()
. - To read from a global, pass the
Global
object as aParam
parameter in a call toHighLevelSyntheticMethod.addCall()
- or have it returned from a synthetic method viaHighLevelSyntheticMethod.setReturnedValue()
.
Example: A controller class writes a user's first name
to the request attribute firstName
, and then the
view reads this request attribute and renders the value to the response.
At a high level, one could model this flow as:
Global firstNameGlobal = actions.createGlobal
("firstName", "java.lang.String", true);
HighLevelSyntheticMethod controller = ...;
Local firstNameLocal = controller.newLocal("java.lang.String");
controller.addGlobalWrite(firstNameGlobal, firstNameLocal, null);
HighLevelSyntheticMethod view = ...;
view.addCall("Response.write(java.lang.String):void",
null, firstNameGlobal);
By adding a write to firstNameGlobal
in
the controller synthetic method and then passing firstNameGlobal
to Response.write()
in
the view
synthetic method, the data flow from controller
to the view is exposed.
firstNameLocal
.