示例1
在以下C ++代码中实现Widget类是代码的一个示例,并非被设计为重新进入。如果一种小部件方法的调用无意间产生了小部件方法的第二个嵌套调用,则数据成员背景图可能会在执行外呼叫时出乎意料地改变。
类小部件
{
私人的:
图像*背景图像;
民众:
void click()
{
if(背景图像)
{
背景图像 - > click();
}
}
void ChanchbackgroundImage(图像* newimage)
{
if(背景图像)
{
删除背景图像;
}
背景图= newImage;
}
}
类图像
{
民众:
void click()
{
ScriptEngine-> fironimageclick();
/ *使用“此”指针执行一些操作 */
}
}
仔细观察此示例,widget :: click()调用backgroundImage-> click(),它依次呼叫scriptEngine-> firononimageclick()。Fireonimageclick()中的代码调用了由文档渲染的文档定义的适当脚本处理程序例程。在这种情况下,此脚本例程由对手提供,此恶意脚本呼叫widget :: ChandlackgroundImage(),从而删除了由背景图指向的映像对象。当控件返回到Image ::单击时,函数的背景图像“此”指针(这是背景图的前值)是一个悬空的指针。这种弱点的根源是,虽然窗口小部件上的一个操作(click)在执行中,但可以调用小部件对象上的第二个操作(在这种情况下,第二个调用是对不同方法的调用,即换回了backbackgroundImage)这修改了非本地变量。
示例2
这是C ++代码的另一个示例,并非被设计为重新进入。
类请求
{
私人的:
std :: string uri;
/ * ... */
民众:
void设置(scriptObject* _uri)
{
this-> uri = scriptEngine-> coercetostring(_uri);
/ * ... */
}
void send(scriptObject* _data)
{
凭证凭证= getCredentials(uri);
std :: string data = scriptEngine-> coercetostring(_data);
dosend(URI,凭据,数据);
}
}
预期的操作顺序是呼叫请求:: setup(),然后打电话给请求:: send()。请求:: send()调用scriptEngine-> coercetostring(_data)将脚本提供的参数胁到字符串。此操作可能会产生脚本执行。例如,如果脚本语言是eCmascript,则如果_data是具有自定义toString方法的对手支持的ecmascript对象,则可能会导致任意脚本执行。如果对手的脚本对请求::设置进行了新的调用,则当控件返回请求::发送时,URI和本地变量凭据将不再与彼此保持一致。结果,一个资源的凭据将与其他资源不正确。这种弱点的根源是,尽管按要求进行一次操作(发送)在执行中,但可以调用第二个操作(设置)。