php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #59741 apc_bin_dump[file]() generates invalid output on certain files
Submitted: 2011-05-02 01:17 UTC Modified: 2011-07-28 02:19 UTC
From: drupal at samboyer dot org Assigned:
Status: Closed Package: APC (PECL)
PHP Version: 5.3.5 OS: ubuntu lucid64
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: drupal at samboyer dot org
New email:
PHP Version: OS:

 

 [2011-05-02 01:17 UTC] drupal at samboyer dot org
Description:
------------
Some drupal folks have been attempting to make APC actually useful in cli mode by taking advantage of the dump/load functions; we dump onto /dev/shm, then reload from the same spot later.

We've run into some problems, though - they manifest in two ways, but look to be the same basic problem: apc_bin_dump[file] writes invalid data when attempting to dump certain files, then segfaults on attempts to load that file in subsequent processes.

To be clear, there seem to be three cases - some files dump out fine, and others terminate the dump process with an error, and still others appear to dump fine but cause a segfault when a subsequent run tries to load the dump. At least, that was the case when I was testing with 5.3.2-1ubuntu4.7; when I compiled a debug 5.3.6, the second case disappeared. The two files that caused segfaults at that revision were commands/core/cache.drush.inc and includes/table.inc. I haven't tried dumping them individually to see if they cause the same errors.

Reproduce code:
---------------
1. Download the latest version of drush from http://drupal.org/project/drush. Preferably use git; I did my tests against 7c582a0.
2. Apply http://drupal.org/files/issues/drush_apc_testing.patch
3. Run the drush sh script contained therein with no arguments, or with APCCACHE set to the location where the dumpfile should be place. Defaults to /dev/shm/drush.apc
4. Run drush again with the same APCCACHE value

(Optional 5. Tweak the array_slice()/unset controlling which files are dumped to see how omitting certain files allows it to function normally)

Expected result:
----------------
drush to run normally, but much quicker since it takes advantage of the already-generated apc dump. with no arguments, drush should spew a bunch of helptext.

Actual result:
--------------
When running with --enable-debug and attempting to dump one of those files, here's the error:

php: /tmp/pear/temp/APC/apc_bin.c:469: apc_swizzle_zval: Assertion `0' failed.

Program received signal SIGABRT, Aborted.
0x00007ffff50cfa75 in raise () from /lib/libc.so.6

and the gdb backtrace:
#0  0x00007ffff50cfa75 in raise () from /lib/libc.so.6
#1  0x00007ffff50d35c0 in abort () from /lib/libc.so.6
#2  0x00007ffff50c8941 in __assert_fail () from /lib/libc.so.6
#3  0x00007ffff2d69fe3 in apc_swizzle_zval (bd=0x17df330, ll=0x7fffffffbf50, zv=0x18b6524) at /tmp/pear/temp/APC/apc_bin.c:469
#4  0x00007ffff2d69238 in apc_swizzle_op_array (bd=0x17df330, ll=0x7fffffffbf50, op_array=0x18b6183) at /tmp/pear/temp/APC/apc_bin.c:205
#5  0x00007ffff2d6b779 in apc_bin_dump (files=0x1584c70, user_vars=0x15d2608) at /tmp/pear/temp/APC/apc_bin.c:780
#6  0x00007ffff2d567ff in zif_apc_bin_dumpfile (ht=3, return_value=0x1796ac0, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0) at /tmp/pear/temp/APC/php_apc.c:1408
#7  0x00000000008e40f3 in zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7e8abf8) at /home/vagrant/src/php-5.3.6/Zend/zend_vm_execute.h:316
#8  0x00000000008e86e0 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (execute_data=0x7ffff7e8abf8) at /home/vagrant/src/php-5.3.6/Zend/zend_vm_execute.h:1606
#9  0x00000000008e35e7 in execute (op_array=0x13bffc0) at /home/vagrant/src/php-5.3.6/Zend/zend_vm_execute.h:107
#10 0x00000000008b0038 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/vagrant/src/php-5.3.6/Zend/zend.c:1194
#11 0x0000000000838de4 in php_execute_script (primary_file=0x7fffffffe790) at /home/vagrant/src/php-5.3.6/main/main.c:2268
#12 0x0000000000999330 in main (argc=2, argv=0x7fffffffea28) at /home/vagrant/src/php-5.3.6/sapi/cli/php_cli.c:1193


Then, on a subsequent run that attempted to read in the bogus dumpfile that would ultimately segfault, this is the backtrace:
#0  0x00007ffff5122cf0 in memcpy () from /lib/libc.so.6
#1  0x00007ffff2d668f3 in apc_pmemcpy (p=0x7f06306e37af, n=16, pool=0x7ffff0b98df0) at /tmp/pear/temp/APC/apc_pool.c:493
#2  0x00007ffff2d5b92a in apc_string_pmemcpy (str=0x7f06306e37af <Address 0x7f06306e37af out of bounds>, len=16, pool=0x7ffff0b98df0) at /tmp/pear/temp/APC/apc_compile.c:288
#3  0x00007ffff2d5bbca in my_copy_zval (dst=0x7ffff0ba14a8, src=0x7ffff7e4d4fe, ctxt=0x7fffffffbf80) at /tmp/pear/temp/APC/apc_compile.c:337
#4  0x00007ffff2d5be20 in my_copy_znode (dst=0x7ffff0ba14a0, src=0x7ffff7e4d4f6, ctxt=0x7fffffffbf80) at /tmp/pear/temp/APC/apc_compile.c:427
#5  0x00007ffff2d5bf2e in my_copy_zend_op (dst=0x7ffff0ba1458, src=0x7ffff7e4d4ae, ctxt=0x7fffffffbf80) at /tmp/pear/temp/APC/apc_compile.c:446
#6  0x00007ffff2d5dc86 in apc_copy_op_array (dst=0x7ffff0ba11c0, src=0x7ffff7e4d15d, ctxt=0x7fffffffbf80) at /tmp/pear/temp/APC/apc_compile.c:1222
#7  0x00007ffff2d6c051 in apc_bin_load (bd=0x7ffff7e09070, flags=3) at /tmp/pear/temp/APC/apc_bin.c:900
#8  0x00007ffff2d56ea5 in zif_apc_bin_loadfile (ht=3, return_value=0x1370520, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0) at /tmp/pear/temp/APC/php_apc.c:1526
#9  0x00000000008e40f3 in zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7e8a090) at /home/vagrant/src/php-5.3.6/Zend/zend_vm_execute.h:316
#10 0x00000000008e86e0 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (execute_data=0x7ffff7e8a090) at /home/vagrant/src/php-5.3.6/Zend/zend_vm_execute.h:1606
#11 0x00000000008e35e7 in execute (op_array=0x134c288) at /home/vagrant/src/php-5.3.6/Zend/zend_vm_execute.h:107
#12 0x00000000008b0038 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/vagrant/src/php-5.3.6/Zend/zend.c:1194
#13 0x0000000000838de4 in php_execute_script (primary_file=0x7fffffffe790) at /home/vagrant/src/php-5.3.6/main/main.c:2268
#14 0x0000000000999330 in main (argc=2, argv=0x7fffffffea28) at /home/vagrant/src/php-5.3.6/sapi/cli/php_cli.c:1193


Note that in that case on 5.3.2, where I'd get that error that didn't seem to prevent the dump from happening, and didn't generate a bogus dump, this was the error:

PHP Fatal error:  apc_bin_dumpfile(): Exceeded bounds check in apc_bd_alloc_ex by 14 bytes.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-05-02 06:08 UTC] gopalv@php.net
No work has gone into the bin_dump for a while ... it remains a sort of abandoned part of code written by the Facebook folks (pre-hiphop).

I'm on the verge of making a 3.1.8 stable release, so I'm not going to rock the boat to fix this right now.

But I'll get back to this bug in about a week or so. Please find me on IRC if I don't.
 [2011-05-02 15:38 UTC] grugnog at yahoo dot com
I have gone through the files that were producing segfaults (when running from loaded cache code) and produced a simplified test case, pasted below:

<?php

// This is a testcase for http://pecl.php.net/bugs/bug.php?id=22679
// see also http://drupal.org/node/1051748
// Repeat runs using a command like:
// rm /dev/shm/drush.apc && php apc-segfault.php && php apc-segfault.php
// If working it should output "It ran!" twice.

// Load the stored APC opcode cache, if available.
define('APC_CACHE', '/dev/shm/drush.apc');
if (function_exists('apc_bin_loadfile') && is_readable(APC_CACHE)) {
  apc_bin_loadfile(APC_CACHE, NULL, APC_BIN_VERIFY_CRC32 | APC_BIN_VERIFY_MD5);
}

// Test case 1: undefined constant in function defaults
// If this block is active, php segfaults when running from code loaded from the cache.
function generates_segfault($var = UNDEFINED_CONSTANT) {
  return;
}

// Test case 2: defined constant used in a class
// If this block is active, php segfaults when running from code loaded from the cache.
define('DEFINED_CONSTANT', 1);
class MiscClass {
  var $var = DEFINED_CONSTANT;
}

// Store the APC opcode cache.
if (function_exists('apc_bin_dumpfile') && (is_writable(APC_CACHE) || is_writable(dirname(APC_CACHE)))) {
  apc_bin_dumpfile(NULL, NULL, APC_CACHE);
}

print "It ran!\n";
 [2011-05-02 15:40 UTC] grugnog at yahoo dot com
You can get the non-wrapped test case from http://drupal.org/files/issues/apc-segfault-php.txt
 [2011-05-04 15:24 UTC] HappySoft at mail dot ru
Too early version 3.1.8 called stable...
E.g. after building APC (by executing "pecl install apc") on Debian Squeeze with php5 (5.3.3-7+squeeze1) & apache2 (2.2.16-6+squeeze1) we got segfaults in /var/log/apache2/error.log:
[Wed May 04 20:32:16 2011] [notice] child pid 24106 exit signal Segmentation fault (11)
[Wed May 04 20:32:22 2011] [notice] child pid 24107 exit signal Illegal instruction (4)
[Wed May 04 20:32:23 2011] [notice] child pid 24108 exit signal Illegal instruction (4)
[Wed May 04 20:32:24 2011] [notice] child pid 24109 exit signal Segmentation fault (11)

I haven't might to investigate this problem, but APC 3.1.6 compiled on same machine works fine!
 [2011-05-25 17:27 UTC] drupal at samboyer dot org
Any other information we can provide to help along work on this issue?
 [2011-07-28 02:19 UTC] gopalv@php.net
Fixed in svn, please confirm

http://news.php.net/php.pecl.cvs/16099

I will add this as a test-case tomorrow.
 [2012-08-22 14:04 UTC] paul at fryer dot org dot uk
Did this fix go in to 3.1.9 as I get the same error in Debian Wheezy (and every other OS I've tried).

Using the test case example here for a double check:

user@box /usr/share/nginx/www/development $ php apc.php
It ran!
user@box /usr/share/nginx/www/development $ php apc.php
Segmentation fault

From PHPInfo
APC Support => enabled
Version => 3.1.9
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sat Jul 12 05:01:33 2025 UTC