php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #43128 Very long class name causes segfault
Submitted: 2007-10-29 17:25 UTC Modified: 2008-02-15 07:45 UTC
From: felipensp at gmail dot com Assigned: dmitry (profile)
Status: Closed Package: Reproducible crash
PHP Version: 5.3CVS-2007-10-29 (snap) OS: Linux
Private report: No CVE-ID: None
 [2007-10-29 17:25 UTC] felipensp at gmail dot com
Description:
------------
Long names cause segmentation fault in 'instanceof' and 'new' operators.

Reproduce code:
---------------
<?php

$a = str_repeat("a", 10000000);

# call_user_func($a); // Warning
# $a->$a();           // Fatal error

if ($a instanceof $a); // Segmentation fault
new $a;                // Segmentation fault


Expected result:
----------------
Warning / Fatal error

Actual result:
--------------
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1214703296 (LWP 4538)]
zend_lookup_class_ex (name=0xb6f4d018 'a' <repeats 200 times>..., 
    name_length=10000000, use_autoload=0, ce=0xbf9644d8)
    at /home/felipe/php5.3-200710261430/Zend/zend_execute_API.c:1078
1078    in /home/felipe/php5.3-200710261430/Zend/zend_execute_API.c



Backtrace:
----------------------------------------------

#0  zend_lookup_class_ex (name=0xb6ece018 'a' <repeats 200 times>..., 
    name_length=10000000, use_autoload=0, ce=0xbfb896f8)
    at /home/felipe/php5.3-200710261430/Zend/zend_execute_API.c:1078
#1  0x08277d9f in zend_fetch_class (
    class_name=0xb6ece018 'a' <repeats 200 times>..., class_name_len=10000000, 
    fetch_type=132) at /home/felipe/php5.3-200710261430/Zend/zend_execute_API.c:1548
#2  0x082c26c9 in ZEND_FETCH_CLASS_SPEC_CV_HANDLER (execute_data=0xbfb8982c)
    at /home/felipe/php5.3-200710261430/Zend/zend_vm_execute.h:1065
#3  0x0829ef1b in execute (op_array=0x84a6900)
    at /home/felipe/php5.3-200710261430/Zend/zend_vm_execute.h:87
#4  0x08281952 in zend_execute_scripts (type=8, retval=<value optimized out>, 
    file_count=3) at /home/felipe/php5.3-200710261430/Zend/zend.c:1137
#5  0x0823d841 in php_execute_script (primary_file=0xbfb8bbcc)
    at /home/felipe/php5.3-200710261430/main/main.c:2007
#6  0x08301c65 in main (argc=2, argv=0xbfb8bce4)
    at /home/felipe/php5.3-200710261430/sapi/cli/php_cli.c:1140


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-10-29 22:24 UTC] iliaa@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows (zip):
 
  http://snaps.php.net/win32/php5.2-win32-latest.zip

For Windows (installer):

  http://snaps.php.net/win32/php5.2-win32-installer-latest.msi

I've tried both PHP 5.2 and 5.3 and cannot reproduce the crash.
 [2007-10-29 23:46 UTC] felipensp at gmail dot com
PHP 5.2.5RC2-dev (cli) (built: Oct 29 2007 21:22:10):

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1211684448 (LWP 31245)]
zend_lookup_class_ex (name=0xb722e018 'a' <repeats 200 times>..., 
    name_length=10000000, use_autoload=0, ce=0xbfa0c498)
    at /home/felipe/php5.2-200710292130/Zend/zend_execute_API.c:1046
1046            zend_str_tolower_copy(lc_name, name, name_length);
 [2007-10-30 00:14 UTC] crrodriguez at suse dot de
Always reproducible on linux64 bit hosts.
 [2007-10-30 08:21 UTC] derick@php.net
Segfaults for me too, looks like a stack smash with valgrind:


==7344== Warning: client switching stacks?  SP change: 0x7FEFFD9A0 --> 0x7FE674310
==7344==          to suppress, use: --max-stackframe=10000016 or greater
==7344== Invalid write of size 8
==7344==    at 0x85D4D3: zend_lookup_class_ex (zend_execute_API.c:1046)
==7344==  Address 0x7FE674308 is on thread 1's stack
==7344== 
==7344== Process terminating with default action of signal 11 (SIGSEGV)
==7344==  Access not within mapped region at address 0x7FE674308
==7344==    at 0x85D4D3: zend_lookup_class_ex (zend_execute_API.c:1046)
==7344== 
==7344== Invalid write of size 8
==7344==    at 0x4A1E310: _vgnU_freeres (vg_preloaded.c:56)
==7344==  Address 0x7FE674300 is on thread 1's stack
==7344== 
==7344== Process terminating with default action of signal 11 (SIGSEGV)
==7344==  Access not within mapped region at address 0x7FE674300

Which makes sense, as lc_name in 
zend_lookup_class_ex() is allocated on line 1045 with:

    lc_name = do_alloca(name_length + 1);
    zend_str_tolower_copy(lc_name, name, name_length);

SPL and Reflection have the same problem in the files:

ext/spl/php_spl.c
ext/reflection/php_reflection.c

A possible fix would be to set an arbitrary limit on the name of classes here...

 [2007-10-30 10:37 UTC] crrodriguez at suse dot de
Index: Zend/zend_execute_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute_API.c,v
retrieving revision 1.331.2.20.2.24.2.8
diff -u -p -r1.331.2.20.2.24.2.8 zend_execute_API.c
--- Zend/zend_execute_API.c     7 Oct 2007 05:22:03 -0000       1.331.2.20.2.24.2.8
+++ Zend/zend_execute_API.c     30 Oct 2007 10:14:29 -0000
@@ -1073,6 +1073,10 @@ ZEND_API int zend_lookup_class_ex(const
        if (name == NULL || !name_length) {
                return FAILURE;
        }
+
+       if(name_length >= ZEND_MAX_CLASSNAME_LEN) {
+               zend_error(E_ERROR, "Class name cannot be longer than %d", ZEND_MAX_CLASSNAME_LEN);
+       }

        lc_free = lc_name = do_alloca(name_length + 1);
        zend_str_tolower_copy(lc_name, name, name_length);
Index: Zend/zend.h
===================================================================
RCS file: /repository/ZendEngine2/zend.h,v
retrieving revision 1.293.2.11.2.9.2.7
diff -u -p -r1.293.2.11.2.9.2.7 zend.h
--- Zend/zend.h 7 Oct 2007 05:22:02 -0000       1.293.2.11.2.9.2.7
+++ Zend/zend.h 30 Oct 2007 10:14:29 -0000
@@ -712,7 +712,7 @@ END_EXTERN_C()


 #define ZEND_MAX_RESERVED_RESOURCES    4
-
+#define ZEND_MAX_CLASSNAME_LEN                 65535
 #include "zend_operators.h"
 #include "zend_variables.h"


ZEND_MAX_CLASSNAME_LEN being the same as java, not to mention that I dont see any reason why such insane long naming will be useful :-)

HTH.
 [2007-10-30 10:48 UTC] derick@php.net
That would already allocate 64kb on the stack, I doubt that will work on all systems. I would suggest a somewhat smaller limit, say 1024?
 [2007-10-30 11:42 UTC] crrodriguez at suse dot de
Yes, an smaller limit like 1024 looks OK and is still high enough to avoid annoying insane coders ;-)
 [2007-11-13 09:59 UTC] dmitry@php.net
The suggested patch is going to fix only one place, however the same stack overflow may be reached using several other places which use do_alloca(). I'll try to think about general solution.
 [2007-11-14 23:34 UTC] jani@php.net
See also bug #43298

 [2007-11-22 13:34 UTC] dmitry@php.net
Fixed in CVS HEAD and PHP_5_3.
 [2008-02-15 07:45 UTC] dmitry@php.net
Fixed in PHP_5_2 too.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 11:01:29 2024 UTC