<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jun 8, 2015, at 2:15 PM, Christopher Ferris <<a href="mailto:cferris@google.com" class="">cferris@google.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Recently, it appears that there was a bug introduced in chunk allocation. The bug is exposed by this small snippet of code:<div class=""><br class=""></div><div class=""><font face="monospace, monospace" class="">  void* mem = malloc(128*1024*1024);</font></div><div class=""><font face="monospace, monospace" class="">  printf("mem address %p\n", mem);</font></div><div class=""><font face="monospace, monospace" class="">  free(mem);</font></div><div class=""><font face="monospace, monospace" class="">  void* large_alloc = malloc(0x80000081UL);</font></div><div class=""><span style="font-family:monospace,monospace" class="">  printf("large mem %p\n", large_alloc);</span><br class=""></div><div class=""><font face="monospace, monospace" class="">  free(large_alloc);</font></div><div class=""><br class=""></div><div class="">It looks like the bug is in the chunk_recycle code, in this piece of code:<br class=""></div><div class=""><br class=""></div><div class=""><div class=""><font face="monospace, monospace" class="">        if (new_addr != NULL) {</font></div><div class=""><font face="monospace, monospace" class="">                extent_node_t key;</font></div><div class=""><font face="monospace, monospace" class="">                extent_node_init(&key, arena, new_addr, alloc_size, false);</font></div><div class=""><font face="monospace, monospace" class="">                node = extent_tree_ad_search(chunks_ad, &key);</font></div><div class=""><font face="monospace, monospace" class="">        } else {</font></div><div class=""><font face="monospace, monospace" class="">                node = chunk_first_fit(arena, chunks_szad, chunks_ad,</font></div><div class=""><font face="monospace, monospace" class="">                    alloc_size);</font></div><div class=""><font face="monospace, monospace" class="">        }</font></div><div class=""><font face="monospace, monospace" class="">        if (node == NULL || (new_addr != NULL && extent_node_size_get(node) <</font></div><div class=""><font face="monospace, monospace" class="">            size)) {</font></div><div class=""><font face="monospace, monospace" class="">                malloc_mutex_unlock(&arena->chunks_mtx);</font></div><div class=""><font face="monospace, monospace" class="">                return (NULL);</font></div><div class=""><font face="monospace, monospace" class="">        }</font></div></div><div class=""><br class=""></div><div class="">The problem is that new_addr == NULL, so the size check is not performed. In my testing, removing the new_addr != NULL check fixes the problem, but I don't know if that's the correct change.</div><div class=""><br class=""></div><div class="">The first allocation after the free shows the problem, if you try and use the whole memory allocation it might segfault, or let you scribble all over someone else's memory.</div></div></div></blockquote></div><br class=""><div class="">This was caused by integer overflow in size class computation, and is fixed now:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">      </span><a href="https://github.com/jemalloc/jemalloc/commit/dde067264db6b801f7ffae9616a35dba5d2d9ad4" class="">https://github.com/jemalloc/jemalloc/commit/dde067264db6b801f7ffae9616a35dba5d2d9ad4</a></div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Jason</div></body></html>