Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:89030 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 51373 invoked from network); 2 Nov 2015 08:35:41 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 2 Nov 2015 08:35:41 -0000 Authentication-Results: pb1.pair.com header.from=aurelien.dudouit@corp.ovh.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=Aurelien.Dudouit@corp.ovh.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain corp.ovh.com designates 46.105.52.207 as permitted sender) X-PHP-List-Original-Sender: Aurelien.Dudouit@corp.ovh.com X-Host-Fingerprint: 46.105.52.207 8.mo175.mail-out.ovh.net Received: from [46.105.52.207] ([46.105.52.207:46598] helo=8.mo175.mail-out.ovh.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 5C/50-42726-75027365 for ; Mon, 02 Nov 2015 03:35:41 -0500 Received: from EX3.OVH.local (corp.ovh.com [5.196.251.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mo175.mail-out.ovh.net (Postfix) with ESMTPS id 54C7BFF8268 for ; Mon, 2 Nov 2015 09:35:31 +0100 (CET) Received: from [10.42.108.97] (109.190.254.34) by EX3.OVH.local (172.16.7.3) with Microsoft SMTP Server (TLS) id 15.1.225.42; Mon, 2 Nov 2015 09:35:31 +0100 To: Message-ID: <56372052.2000204@corp.ovh.com> Date: Mon, 2 Nov 2015 09:35:30 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8"; format=flowed Content-Transfer-Encoding: 8bit X-Originating-IP: [109.190.254.34] X-ClientProxiedBy: cas02.OVH.local (172.16.1.2) To EX3.OVH.local (172.16.7.3) X-Ovh-Tracer-Id: 2329205433269362122 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: 0 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfeekhedrvdegucetufdoteggodftvfcurfhrohhfihhlvgemucfqggfjnecuuegrihhlohhuthemuceftddtnecu Subject: Zend memory manager possible left overflow in heap initialization From: aurelien.dudouit@corp.ovh.com (=?UTF-8?Q?Aur=c3=a9lien_Dudouit?=) Hi, I'm into the process of reviewing the Zend memory manager, and I noticed something in the allocation of the heap. I'm working on PHP 5.6.14, but nothing that could affect it has changed in 5.6.15; I'm building on Debian squeeze, 32 bits. I'm referring to Zend/zend_alloc.c:zend_mm_init() The heap struct (zend_mm_heap) should be like this: ... ------------------------- | internal | ------------------------- | cached | ------------------------- | cache[n] | ------------------------- ... n times... ------------------------- | free_buckets[2n] | ------------------------- ... 2*n times... ------------------------- | large_free_buckets[n] | ------------------------- ... n stands for ZEND_MM_NUM_BUCKETS ZEND_MM_CACHE is set to 1, so cache and cached exist ZEND_DEBUG is set to 0 cache and free_buckets (and large_free_buckets, but this doesn't matter) are arrays containing the same type: pointers to zend_mm_free_block This line troubles me: p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0); The corresponding macro is: #define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \ (zend_mm_free_block*) ((char*)&heap->free_buckets[index * 2] + \ sizeof(zend_mm_free_block*) * 2 - \ sizeof(zend_mm_small_free_block)) sizeof(zend_mm_free_block*) is 4 bytes sizeof(zend_mm_small_free_block) is sizeof(zend_mm_block_info) + 2*sizeof(zend_mm_free_block*), i.e. 16 bytes Which means that the pointer returned by this macro is 2 behind the beginning of free_buckets (index=0), and pointing to the nearly end of the cache array (which is located before, hence "left" overflow). As it contains the same type, it doesn't break immediately, it will run smoothly, but it may lead to memory corruption later, when the last elements of the cache array will be accessed. Am I wrong? If I'm mistaking, and so this is the right behaviour, could anyone explain why does the pointer is shifted using the size of a structure, which does not contain only pointers but integers too? It could have made sense for me if it was containing only pointers, but it doesn't. En apparté, I haven't found where do the zend_mm_free_blocks are allocated. The heap is malloc-ated in the previous calling function (zend_mm_startup_ex), but there isn't any space for those, and right after the problematic macro, members are accessed: for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) { p->next_free_block = p; Does anyone have some hints to spare? It would be greatly appreciated. Thanks, Aurélien