#32981 [NoF->Csd]: ReflectionMethod::getStaticVariables() causes apache2.0.54 seg fault
| From: | dmitry@php.net | Date: | Wed, 17 Aug 2005 12:26:58 +0000 |
| Subject: | #32981 [NoF->Csd]: ReflectionMethod::getStaticVariables() causes apache2.0.54 seg fault | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-83688@lists.php.net to get a copy of this message | ||
ID: 32981
Updated by: dmitry@php.net
Reported By: phpbug at swift-web dot com
-Status: No Feedback
+Status: Closed
Bug Type: Reproducible crash
Operating System: Gentoo 2.6.11
PHP Version: 5.0CVS (2005-05-09)
-Assigned To:
+Assigned To: dmitry
New Comment:
Fixed in CVS HEAD (6.0), PHP_5_1 and PHP_5_0.
Previous Comments:
------------------------------------------------------------------------
[2005-07-20 01:00:04] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
------------------------------------------------------------------------
[2005-07-12 20:06:15] tony2001@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves.
A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external
resources such as databases, etc.
If possible, make the script source available online and provide
an URL to it here. Try to avoid embedding huge scripts into the report.
------------------------------------------------------------------------
[2005-07-12 19:07:14] phpbug at swift-web dot com
Sorry for the long delay in getting back to this. Tried using just a
plain php install as suggested (./configure --enable-debug
--with-apxs2=/usr/sbin/apxs2) and I was still getting the seg fault
error consistently on two different test boxes.
I tried looking at my code again and came up with an idea.
if a class has the static variables defined within the class but
outside the methods eg:
class test {
private static $test = true;
public function test_method() {
// do whatever and access the
// static property as: self::$test
}
}
then no seg faults occur when I dump this classes details with my
"dump" class which uses ReflectionMethod::getStaticVariables().
If however the above class is done this way instead (with the static
value only used in the method not in entire class):
class test {
public function test_method() {
static $test = true;
// do whatever and access the
// static property just as $test
}
}
Then using my debug dump class to display information about the class
causes a seg fault. I haven't given you my debug/dump class, maybe
this is what you need to reproduce the seg fault crash. I'll include
the class below.
To use the dump class I simply call it statically
debug::dump($new = new test(),'test class',true,true);
*(replace test() with the name of the class you want information about
obviously but my test about used the name test)
here is the class
////////// start of php code
class debug{
/**
* dump out variables to easy to read html tables
* variable can be array, string, boolean, object or hash mixture
*
* @param mix $data variable to be dumped
* str $label optional top label for table
* boo $show_docs true = show documentation for an object
item
* false (default) = do not show docs for
an object item
* boo $public_only true (default) = when displaying objects
only
* show public items
* false = show everything about the object
*
* returns html output
*/
final public static function
dump($data,$label='',$show_docs=false,$public_only=true) {
// make sure public_only & show_docs is just true or false
$public_only = ($public_only != false) ? true : false;
$show_docs = ($show_docs != false) ? true : false;
// setup styles for html output
$style['key'] = 'font-family: sans-serif; text-align: right;
font-size: 12px; font-weight: bold; background-color: #000; color:
#f0f0f0;';
$style['value'] = 'font-family: sans-serif; font-size: 11px; color:
#009; background-color: #eee'; // monospace
$style['type'] = 'font-family: sans-serif; text-align: center;
font-size: 12px; background-color: #9cc; color: #600;';//#F6F6F6
$output = '<table border="2" bordercolor="#000080"
cellpadding="0"
cellspacing="0"><tr><td style="font-family: sans-serif; font-size:
14px; background-color: #000080; color: white;">'.($label != '' ?
$label : 'variable dump - no variable name
passed').'</td></tr><tr><td
style="font-family: sans-serif; text-align: center; font-size: 12px;
background-color: #9cc; color:
#600;">'.gettype($data).'</td></tr><tr><td>';
return($output.ss_debug::dump_html_table($data,$style,$show_docs,$public_only).'</td></tr></table><br
/>');
}
/**
* used privately by dump method
*/
final private static function
dump_html_table($data,&$style,$show_docs,$public_only) {
if (!is_array($data)) {
if ($data === NULL) {
return('--NULL--');
}
switch (gettype($data)) {
case 'string':
//if ($data === NULL) {
//return('--NULL--');
//}
return ( isset ( $data ) && !empty ( $data ) ) ?
'<pre>'.htmlentities($data)."</pre>" : ' ';
break; // string
case 'boolean':
return($data ? 'true' : 'false');
break; // boolean
case 'object':
// search patterns to replace wasted front whitespace or empty
lines
$doc_search = array('/^(\t| )*\/\*\*/','/^(\t| )*/m','/^(\t|
)*(\*\/)?(\t| )*(\n)?$/m','/^(\w|\*|\r|\n)*$/m');
// convert object to array (so we can find private and protected
properties)
$raw_properties = (array)$data;
// Create an instance of the ReflectionClass class to give us
more detailed info
$class = new ReflectionClass(get_class($data));
$class_name = $class->getName();
// get method info
$methods = $properties = array();
foreach ($class->getMethods() as $method) {
if ($method->isPublic() || $public_only !== true) {
$result = array();
$name = '<font color="grey">';
if ($method->isPublic()) {
$name .= '<i>public</i> ';
} elseif ($method->isPrivate()) {
$name .= '<i>private</i> ';
} elseif ($method->isProtected()) {
$name .= '<i>protected</i> ';
}
if ($method->isStatic()) {
$name .= '<i>static</i> ';
}
if ($method->isAbstract()) {
$name .= '<i>abstract</i> ';
}
if ($method->isFinal()) {
$name .= '<i>final</i> ';
}
$name .= '</font>'.$method->getName();
if ($show_docs === true) {
$result['docs'] = $method->getDocComment();
if ($result['docs'] == false) {
unset($result['docs']);
} else {
$result['docs'] =
preg_replace($doc_search,'',$result['docs']);
}
}
$result['params'] = '';
foreach($method->getParameters() as $parameter) {
$result['params'] .= $parameter->__toString().", \n";
}
if ($result['params'] == false) {
unset($result['params']);
} else {
$result['params'] = substr($result['params'],0,-3);
}
$result['info'] = '';
if ($method->isConstructor()) {
$result['info'] .= 'constructor, ';
}
/* does not appear to work
if ($method->isDestructor()) {
$result['info'] .= 'destructor, ';
}
*/
if ($method->isInternal()) {
$result['info'] .= 'internal (built-into php)';
} else {
$result['info'] .= 'user-defined (lines
'.$method->getStartLine().' - '.$method->getEndline().')';
}
/* TODO: this is commented out because of a bug in the gentoo
php installation, where if the static variables still contain there
* default values then this causes a seg fault error
*/
$result['static vars'] = $method->getStaticVariables();
if ($result['static vars'] == array()) {
unset($result['static vars']);
}
// */
$methods[$name] = $result;
}
}
// get property info
foreach ($class->getProperties() as $prop) {
$prop_name = $prop->getName();
$result = array();
$name = '<font color="grey">';
if ($prop->isDefault()) {
$name .= '<i><default></i> ';
}
if ($prop->isPublic()) {
$name .= '<i>public</i> ';
} elseif ($prop->isPrivate()) {
if ($public_only === true) {
break;
}
$name .= '<i>private</i> ';
} elseif ($prop->isProtected()) {
if ($public_only === true) {
break;
}
$name .= '<i>protected</i> ';
}
if ($prop->isStatic()) {
$name .= '<i>static</i> ';
}
$name .= "</font>$prop_name";
$found = false;
foreach ($raw_properties as $key => $value) {
if (strpos($key,$prop_name,(strlen($key)-strlen($prop_name))))
{
$properties[$name] = $value;
$found = true;
unset($raw_properties[$key]);
break;
}
}
if ($found === false) {
$properties[$name] = NULL;
}
}
// get class info
$keywords = $class->isAbstract() ? 'abstract ' : '';
$keywords .= $class->isFinal() ? 'final ' : '';
$keywords .= $class_name;
$parent = $class->getParentClass();
$parent = (array)$parent;
if (isset($parent['name'])) {
$keywords .= ' extends '.$parent['name'];
}
$obj_data['class'] = $keywords;
$obj_data['declared in'] = $class->getFileName().' (lines
'.$class->getStartLine().' - '.$class->getEndline().')';
if ($show_docs === true) {
$obj_data['docs'] = $class->getDocComment();
if ($obj_data['docs'] == false) {
unset($obj_data['docs']);
} else {
$obj_data['docs'] =
preg_replace($doc_search,'',$obj_data['docs']);
}
}
// removed following line interface (not interfaces) as it seemed
to always be coming up as class (not sure what an interface is)
//$obj_data['interface'] = $class->isInterface() ? 'interface' :
'class';
// removed following line from above as it seemed to display info
I already have elsewhere
//$obj_data['modifiers'] = sprintf('%d
[%s]',$class->getModifiers(),implode(' ',
Reflection::getModifierNames($class->getModifiers())));
$obj_data['interfaces'] = ($class->getInterfaces() == array() &&
count($class->getInterfaces()) > 0) ?
var_export($class->getInterfaces(),1) : 'none';
$obj_data['constants'] = (($class->getConstants() == array() &&
count($class->getConstants()) > 0) ? $class->getConstants() : 'none');
$obj_data['static properties'] = $class->getStaticProperties();
$obj_data['properties'] = $properties;
$obj_data['methods'] = $methods;
// unset empty fields to save space
if ($obj_data['interfaces'] == 'none') {
unset($obj_data['interfaces']);
}
if ($obj_data['constants'] == 'none') {
unset($obj_data['constants']);
}
/* commented it out above so no need to clean it out
if ($obj_data['modifiers']{0} == '0') {
unset($obj_data['modifiers']);
}
*/
if ($obj_data['static properties'] == array()) {
unset($obj_data['static properties']);
}
if ($obj_data['properties'] == array()) {
unset($obj_data['properties']);
}
/* old method used in php4 (did not show extra php5 info like
private, public, etc)
* and it only showed public properties
$object_data = array (
'class' => get_class($data),
'parent_class' => get_parent_class($data),
'methods' => get_class_methods(get_class($data)),
'properties' => get_object_vars($data)
);
// by changing above line to 'properties' => (array)$data
// then we could see private, protected properties but it was a
mess (and still not php5 info)
*/
return
(ss_debug::dump_html_table($obj_data,$style,$public_only,$show_docs));
break;
case 'resource':
return sprintf('%s (%s)',$data,get_resource_type($data));
break;
default:
//if ($data === NULL) {
//return('-NULL-');
//}
return $data;
break;
}
}
$output = '<table border="1" cellpadding="3"
cellspacing="0">';
foreach ($data as $key => $value) {
$type = substr(gettype($data[$key]),0,3);
$output .= sprintf (
"<tr>\n <td style=\"%s\">%s</td>\n <td
style=\"%s\">%s</td>\n
<td style=\"%s\">%s</td>\n</tr>\n",
$style['key'], $key,
$style['type'], $type,
$style['value'],
ss_debug::dump_html_table($value,$style,$public_only,$show_docs)
);
}
$output .= '</table>';
return($output);
}
// end of ss_debug class
}
///////////////////////////// end of script
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
http://bugs.php.net/32981
--
Edit this bug report at http://bugs.php.net/?id=32981&edit=1