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
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
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-2024 The PHP Group
All rights reserved.
Last updated: Thu Oct 31 23:01:28 2024 UTC