通过用户脚本防止堆栈溢出

时间:2015-04-06 04:59:01

标签: c++ security scripting stack-overflow

C ++具有有限的堆栈空间,但是没有办法让函数检查是否有足够的空间让它们运行。在编写脚本绑定时,我不知道该怎么做。

例如:

class Container : Widget {
  void addChild(WidgetPtr child) { ... }

  void draw(Canvas& canvas) {
    for (auto child : m_children) {
      child.draw();
    }
  }
};

恶意脚本可以执行此操作以使程序崩溃:

var a = new Container()
for (i = 0; i < 10000000; i++) {
  var b = new Container()
  a.addChild(b)
  a = b
}

a.draw() // 10000000 nested calls ---> stack overflow

还有回调问题:

void doSomething(std::function<void()> callback) {
  callback();
}

如果用这样的东西包裹:

ScriptValue doSomething_Wrapper(ScriptArgs args) {
  doSomething([&]() { args[0].callAsFunction(); });
}

崩溃使用:

function badCallback() { doSomething(badCallback) }
doSomething(badCallback)

...
doSomething_Wrapper
doSomething
ScriptValue::callAsFunction
...
doSomething_Wrapper
doSomething
ScriptValue::callAsFunction
...
BOOM!

以最不便的方式来防御这种最惯用的方式是什么?

用C ++(Firefox,Chrome)编写的浏览器有什么作用?

我不能偶然引入这样的漏洞吗?

1 个答案:

答案 0 :(得分:4)

虽然“恶意”脚本可能会导致堆栈溢出(如您所述),但它不会对程序造成损害而不会导致崩溃(至少在实际检查堆栈限制的现代操作系统上,因此它安全地防止覆盖其他重要数据)。

如果程序一直在运行至关重要,则另一个进程必须对其进行监视(并在必要时重新启动它。不仅因为堆栈溢出,还有更多潜在问题。)。
除此之外,如果使用OS堆栈,则无法做很多事情。为堆栈中的单个指针动态分配大内存块并在此块中手动执行整个内存管理是可能的,但可能不切实际。

关于eg。 FIrefox:至少部分程序正在使用自己的内存管理(但我不确定它是否与插件,脚本等相关)。此外,还有一个单独的进程plugin-container.exe(至少在Windows上),并且kill不会杀死Firefox(只有Flash等插件部分不再工作,用户会收到有关插件崩溃的消息) 。