使用高级别合成方法

此主题说明如何使用高级别合成方法的某些重要特性。有关完整详细信息,请参阅 Framework for Frameworks API 类和方法 Javadoc 文档。

创建高级别合成方法

要创建高级别合成方法并将其添加到 F4FActions 对象 actions,请使用如下代码:

HighLevelSyntheticMethod m = HighLevelSyntheticMethod.make();
actions.addHighLevelSyntheticMethod(m);

您可以通过将 VDB 方法特征符传递到 HighLevelSyntheticMethod.make() 来指定合成方法的名称、参数类型和返回类型。

创建局部变量

可以通过以下方式来创建高级别合成方法 m 的新局部变量:

Local l = m.newLocal("java.lang.String");

构造方法不需要在合成方法中调用。考虑到以上代码,在向合成方法中添加更多语句时,我们可以假设 l 是指非空 String 对象。

添加调用

高级别合成方法中的大部分语句将为方法调用(通过 addCall() 方法添加)。addCall() 的参数表示要调用的方法、调用的文件位置信息以及在调用时要传递的参数。以下示例用于添加对 setter 方法 sample.BeanType.setName() 的调用(假定存在 F4FApp 对象 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());

处理 MVC 体系结构中的客户机表单提交的步骤 2-5(如高级别合成方法中所概述)可以在某种程度上进行建模,方法是按照上述方式向合成方法中添加相应调用。

某个调用的参数由 Param 类型的对象来表示,这可以是以下任何一种:

  • Local对象,表示局部变量
  • Taint对象,表示不可信或受感染数据。
  • EnclosingFormal 对象,表示高级别合成方法的形参。例如,如果您具有一个包含特征符 synthMethod(int):void 的合成方法,那么 EnclosingFormal.FIRST 是指方法的 int 参数。
  • 代表全局变量的 Global 对象(已在全局变量中讨论)。
注: 对于非静态实例方法,要以 this 传递的值必须提供给 addCall()。在上述示例中,l 中的值将作为 this 传递到 setName()

添加返回值

合成方法可通过使用 setReturnedValue() 方法返回值。返回值对于生成标记方法来对复杂框架验证建模比较有用。例如,如果要在将已感染 HTTP 请求值传递到模型对象的 setter 方法之前使用对该值执行复杂验证的框架,那么可通过使用以下代码在 AppScan® Source 发现的跟踪上暴露验证:

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

合成方法 Synth.validatorModel() 仅返回作为参数传递到其自身的 String。然后,在另一个合成方法中添加对 Synth.validatorModel() 的调用,将已感染值作为自变量传递。该调用的结果存储在 validated 中,可在后续调用中将该结果传递到 setter 方法(如添加调用中的示例所示)。涉及该查找和关闭数据的跟踪将包括对 Synth.validatorModel() 的调用,如果认为验证已足够,那么 AppScan® Source 用户可选择过滤跟踪。

全局变量

全局变量是一项用于揭示应用程序不同部分之间的流的高级功能。例如,全局变量可以用于针对从控制器到视图的数据流进行建模(通过请求或会话属性)。用于创建和访问全局变量的关键操作为:

  • 要创建表示全局变量的 Global 对象,请使用 F4FActions.createGlobal()
  • 要写入全局变量,请使用 HighLevelSyntheticMethod.addGlobalWrite()
  • 要从全局变量中读取,请将 Global 对象作为调用中的 Param 参数传递到 HighLevelSyntheticMethod.addCall() - 或通过 HighLevelSyntheticMethod.setReturnedValue() 将其返回合成方法。

示例:控制器类将用户的名字写入到请求属性 firstName,然后视图读取此请求属性并将值呈现给响应。在高级别上,用户可以按如下所示将此流进行建模:

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);

通过将某个写入添加到控制器合成方法中的 firstNameGlobal,然后将 firstNameGlobal 传递到 view 合成方法中的 Response.write(),将揭示从控制器到视图的数据流。

注: 该示例进行了大幅度的简化。其中一点是,完整版本将需要揭示数据到 firstNameLocal 的正确流。