昨天遇到一个amfext会core的问题,一开始以为是自己的php代码写的有问题,后来仔细看了一下core的地点,结果发现
似乎是amfext的一个bug,它在MAKE_STD_ZVAL之后没有对zval的type进行初始化,而接下来的操作中立即使用了这个
type,如果type=5则调用HASH_OF,一般情况下这句是不会有错的,因为它实际上是从某个数组中取数据出来,并且
这个结果也不会修改(不知道这里为什么要这么写,估计是半成品,为某个目的预留的),因此即使错了也问题不大。
但是在特殊情况下,比如昨天core的情况下,数组的index实在太大了,应该有10亿左右,这个时候可能访问到了某个
保护内在地址,因此才会直接segement fault了。并且在我的机器上运行那段代码是不会core的,只有在同事的机器上会,
并且只要对代码进行任意修改,比如加日志都不会core了,可能就是因为修改了内存加载的地址,导致加载了那个很大的index。
附:针对php5.3的patch
-------------------------------------------------------------------------begin------------------------------------------------------
diff -uprN amfext-0.9.2/amf.c amfext/amf.c
--- amfext-0.9.2/amf.c 2008-07-18 18:28:36.000000000 +0800
+++ amfext/amf.c 2011-10-12 12:08:51.000000000 +0800
@@ -844,7 +844,7 @@ static inline void amf_write_zstring(amf
buf->last_chunk->size = 1; /* zval chun */
buf->last_chunk->zv = zstr;
- ZVAL_ADDREF(zstr);
+ Z_ADDREF_P(zstr);
buf->chunks++;
buf->left_in_part -= sizeof(amf_string_chunk);
@@ -1185,7 +1185,7 @@ static void amf3_serialize_object(amf_se
int resultType = AMFC_TYPEDOBJECT;
int resultValueLength = 0;
zval** resultValue = struc;
- int deallocResult = (*struc)->refcount;
+ int deallocResult = Z_REFCOUNT_PP(struc);
resultType = amf_perform_serialize_callback(struc, &className,&classNameLen,&resultValue,var_hash TSRMLS_CC);
@@ -2670,7 +2670,7 @@ static int amf3_read_string(zval **rval,
}
else
{
- newval->refcount--;
+ Z_DELREF_P(newval);
}
*rval = newval;
}
@@ -2772,6 +2772,7 @@ static int amf_read_objectdata(zval **rv
break;
}
MAKE_STD_ZVAL(zValue);
+ zValue->type = 0;
if(amf_var_unserialize(&zValue,p, max, var_hash TSRMLS_CC) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "amf cannot unserialize key <%s>",Z_STRVAL_P(zName));
@@ -2824,7 +2825,7 @@ static int amf_read_objectdata(zval **rv
{
if(zClassname != NULL)
{
- ZVAL_ADDREF(zClassname);
+ Z_ADDREF_P(zClassname);
add_assoc_zval(*rval, "_explicitType",zClassname);
}
}
@@ -2906,8 +2907,8 @@ static int amf3_unserialize_var(zval **r
{
int iIndex;
int maxIndex = handle >> 1;
- HashTable * htOutput = HASH_OF(*rval);
amf_array_init(*rval, maxIndex TSRMLS_CC);
+ HashTable * htOutput = HASH_OF(*rval);
/* zval_add_ref(rval) */
amf_put_in_cache(&(var_hash->objects),*rval);
@@ -2927,6 +2928,7 @@ static int amf3_unserialize_var(zval **r
break;
}
MAKE_STD_ZVAL(zValue);
+ zValue->type = 0;
if(amf3_unserialize_var(&zValue,p,max, var_hash TSRMLS_CC) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "amf cannot unserialize key %s",Z_STRVAL_P(zKey));
@@ -2967,6 +2969,7 @@ static int amf3_unserialize_var(zval **r
{
zval * zValue;
MAKE_STD_ZVAL(zValue)
+ zValue->type = 0;
if(amf3_unserialize_var(&zValue,p,max,var_hash TSRMLS_CC) == FAILURE)
{
zval_ptr_dtor(&zValue);
@@ -3045,7 +3048,7 @@ static int amf3_unserialize_var(zval **r
MAKE_STD_ZVAL(zClassDef);
amf_array_init(zClassDef,nClassMemberCount+2 TSRMLS_CC);
add_next_index_long(zClassDef,(bTypedObject?1:0)|nClassMemberCount << AMF_CLASS_MEMBERCOUNT_SHIFT |iDynamicObject|iExternalizable);
- ZVAL_ADDREF(zClassname);
+ Z_ADDREF_P(zClassname);
add_next_index_zval(zClassDef, zClassname);
/* loop over classMemberCoun */
@@ -3056,7 +3059,7 @@ static int amf3_unserialize_var(zval **r
{
break;
}
- ZVAL_ADDREF(zMemberName);
+ Z_ADDREF_P(zMemberName);
add_next_index_zval(zClassDef,zMemberName); /* pass referenc */
}
@@ -3148,6 +3151,7 @@ static int amf3_unserialize_var(zval **r
return FAILURE;
}
MAKE_STD_ZVAL(zValue)
+ zValue->type = 0;
if(amf3_unserialize_var(&zValue,p,max, var_hash TSRMLS_CC) == FAILURE)
{
zval_ptr_dtor(&zValue);
@@ -3180,6 +3184,7 @@ static int amf3_unserialize_var(zval **r
break;
}
MAKE_STD_ZVAL(zValue)
+ zValue->type = 0;
if(amf3_unserialize_var(&zValue,p,max, var_hash TSRMLS_CC) == FAILURE)
{
zval_ptr_dtor(&zValue);
@@ -3201,7 +3206,7 @@ static int amf3_unserialize_var(zval **r
{
if(bTypedObject != 0)
{
- ZVAL_ADDREF(zClassname);
+ Z_ADDREF_P(zClassname);
add_assoc_zval(*rval, "_explicitType",zClassname);
}
}
@@ -3300,6 +3305,7 @@ static int amf_var_unserialize(zval **rv
{
zval * zValue;
MAKE_STD_ZVAL(zValue);
+ zValue->type = 0;
if(amf_var_unserialize(&zValue,p,max, var_hash TSRMLS_CC) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "amf bad unserialized value for array index %d",iIndex);
-------------------------------------------------end----------------------------------------