[JavaScript engine] spidermonkey Debug 问题集

Removal of global arena cache list (arena_freelist)

https://bugzilla.mozilla.org/show_bug.cgi?id=347645

Currently when allocating a new arena the global list is checked before using malloc. This assumes that allocating from the list is faster than using malloc. But this may not be true for 2 reasons. First, many modern malloc/free implementations use thread-local cache. In such implementation malloc avoids taking any locks in many cases and can bit allocating from the list which allows take the lock. Second, the implementation searches the list for an element with exactly requested size. Since the list is not bounded, this can be arbitrary slow. 

Thus I suggest to remove the global list and always use malloc/free when allocating/releasing arena memory and allow the system to take better use of the memory.

But In case of SpiderMonkey the case is much more stronger for the following reason. The global list is populated only when JS_FreeArenaPool is called, in the rest of cases arena memory is released calling free directly. Now the only place in the browser code that calls JS_FreeArenaPool is js_GetPrinterOutput from js/src/jsopcode.c. 

Since the list is queried for exact allocations, the result of releasing the memory in js_GetPrinterOutput would, in most cases, be only usable when js_NewPrinter is called later. This happens because js_NewPrinter calls JS_InitArenaPool(&jp->pool, name, 256, 1) while in the rest of places JS_InitArenaPool is called with minimal allocation size set to 1K, 8K or the size deduced from the expected buffer size. Thus the global list just imposes useless locking and list searching before calling the malloc.

Here is stats from the browser collected with JS_ARENAMETER defined after the browser startup:

temp allocation statistics:
              number of arenas: 0
         number of allocations: 120748
 number of free arena reclaims: 0
        number of malloc calls: 5012
       number of deallocations: 0
  number of allocation growths: 19
    number of in-place growths: 0
 number of realloc'ing growths: 0
number of released allocations: 4381
       number of fast releases: 3253
         total bytes allocated: 4846989
          mean allocation size: 40.1414
            standard deviation: 186.675
       maximum allocation size: 4096

stack allocation statistics:
              number of arenas: 0
         number of allocations: 420
 number of free arena reclaims: 0
        number of malloc calls: 117
       number of deallocations: 0
  number of allocation growths: 0
    number of in-place growths: 0
 number of realloc'ing growths: 0
number of released allocations: 1012
       number of fast releases: 895
         total bytes allocated: 11584
          mean allocation size: 27.581
            standard deviation: 112.446
       maximum allocation size: 1676

properties allocation statistics:
              number of arenas: 51
         number of allocations: 12898
 number of free arena reclaims: 0
        number of malloc calls: 51
       number of deallocations: 0
  number of allocation growths: 0
    number of in-place growths: 0
 number of realloc'ing growths: 0
number of released allocations: 0
       number of fast releases: 0
         total bytes allocated: 361144
          mean allocation size: 28
            standard deviation: 27.8314
       maximum allocation size: 28

Which tells that there there were 5012 + 117 + 51 useless locking/unlocking calls.



Heap corruption on Out-of-Memory in jsopcode.c

https://bugzilla.mozilla.org/show_bug.cgi?id=393537
The reason for the bug is that SprintEnsureBuffer on failed realloc sets sp->base to null while keeping sp->size at the previous value. Thus the following call to SprintEnsureBuffer would set sp->base to freshly allocated memory of size just nb bytes and then write past malloc boundary.

I think this is exploitable on systems with sufficient memory as one can use huge strings to trigger OOM failure in the decompiler at the right moment.
The reason for the bug is that SprintEnsureBuffer on failed realloc sets sp->base to null while keeping sp->size at the previous value. Thus the following call to SprintEnsureBuffer would set sp->base to freshly allocated memory of size just nb bytes and then write past malloc boundary.

I think this is exploitable on systems with sufficient memory as one can use huge strings to trigger OOM failure in the decompiler at the right moment.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值