在开发处理符合性数据和变体数据的 RPC 接口和方法时,请考虑使用以下特定于 IDL 的技术来提高安全性和性能。 本主题中引用的属性是在处理符合性数据的方法参数(例如[size_is] 和 [max_is] 属性)或变体数据(例如[length_is] 和 [字符串] 属性)上设置的 IDL 属性。
使用具有符合性数据参数的 [range] 属性
[范围] 属性指示 RPC 运行时在数据取消划分过程中执行其他大小验证。 具体而言,它验证作为关联参数传递的数据的提供大小是否在指定范围内。
[范围] 属性不会影响线路格式。
如果线路上的值超出允许的范围,RPC 将引发RPC_X_INVALID_BOUND或RPC_X_BAD_STUB_DATA异常。 这提供了额外的数据验证级别,有助于防止常见的安全错误,例如缓冲区溢出。 同样,使用 [范围] 可以提高应用程序性能,因为标有它的符合性数据具有明确的约束可供 RPC 服务考虑。
RPC 服务器存根内存管理规则
为启用了 RPC 的应用程序创建 IDL 文件时,请务必了解 RPC 服务器存根内存管理规则。 应用程序可以通过将 [范围] 与上述符合性数据结合使用来提高服务器资源利用率,并故意避免将可变长度的数据 IDL 属性(如 [length_is])应用于符合性数据。
不建议将 [length_is] 应用于 IDL 文件中定义的数据结构字段。
可变长度数据参数的最佳做法
以下是为可变大小数据结构、方法参数和字段定义 IDL 属性时要考虑的几个最佳做法。
使用早期关联。 通常,最好定义可变大小参数或字段,使其在控制整型类型之后立即发生。
例如
earlyCorr ( [in, range(MIN_COUNT, MAX_COUNT)] long size, [in,size_is(size)] char *pv );
比
lateCorr ( [in,size_is(size)] char *pv, [in, range(MIN_COUNT, MAX_COUNT)] long size) );
其中,earlyCorr 在可变长度数据参数之前声明大小参数,lateCorr 声明大小参数之后。 使用早期通信可提高整体性能,尤其是在频繁调用该方法的情况下。
对于用 [out、size_is] 属性元组标记的参数,以及客户端上已知数据长度或客户端具有合理上限的参数,方法定义应与以下方法定义在参数属性和序列方面类似:
outKnownSize ( [in,range(MIN_COUNT, MAX_COUNT)] long lSize, [out,size_is(lSize)] UserDataType * pArr );
在这种情况下,客户端为 pArr提供固定大小缓冲区,使服务器端 RPC 服务能够分配一个大小合理的缓冲区,并提供良好的保证。 请注意,在示例中,从服务器([输出])接收数据。 定义类似于传递给服务器的数据([]中的)。
对于 RPC 应用程序的服务器端组件决定数据长度的情况,方法定义应如下所示:
typedef [range(MIN_COUNT,MAX_COUNT)] long RANGED_LONG; outUnknownSize ( [out] RANGED_LONG *pSize, [out,size_is(,*pSize)] UserDataType **ppArr );
RANGED_LONG 是为客户端和服务器存根定义的类型,并且客户端可以正确预测的指定大小。 在此示例中,客户端将 ppArr 作为 NULL传递,RPC 服务器应用程序组件分配正确的内存量。 返回后,客户端上的 RPC 服务将为返回的数据分配内存。
如果客户端想要将大型符合性数组的子集发送到服务器,则应用程序可以指定子集的大小,如以下示例所示:
inConformantVaryingArray ( [in,range(MIN_COUNT,MAX_COUNT)] long lSize, [in] long lLength, [in,size_is(lSize), length_is(lLength)] UserDataType *pArr );
这样,RPC 将只传输 lLength 线路中数组的元素。 但是,此定义强制 RPC 服务在服务器端 lSize 分配大小内存。
如果客户端应用程序组件确定服务器可以返回的数组的最大大小,但允许服务器传输该数组的子集,则应用程序可以通过定义类似于以下示例的 IDL 来指定此类行为:
inMaxSizeOutLength ( [in, range(MIN_COUNT, MAX_COUNT)] long lSize, [out] long *pLength, [out,size_is(lSize), length_is(*pLength)] UserDataType *pArr );
客户端应用程序组件指定数组的最大大小,服务器指定它传回客户端的元素数。
如果服务器应用程序组件需要将字符串返回到客户端应用程序组件,并且客户端知道要从服务器返回的最大大小,则应用程序可以使用一致字符串类型,如以下示例所示:
outStringKnownSize ( [in,range(MIN_COUNT, MAX_STRING)] long lSize, [out,size_is(lSize),string] wchar_t *pString );
如果客户端应用程序组件不应控制字符串的大小,RPC 服务可以专门分配内存,如以下示例所示:
outStringUnknownSize ( [out] LPWSTR *ppStr );
客户端应用程序组件必须在调用 RPC 方法时将 ppStr 设置为 NULL。