/*************************************************************************** dbg_ser.c - description ------------------- begin : Sun Sep 24 2000 copyright : (C) 2001 by Dmitri Dmitrienko : (C) 2002, 2006 NuSphere Corp. www : http://dd.cron.ru : http://www.nusphere.com/ www : http://dd.cron.ru license : This source file is subject to version 1.01 of the License, that is bundled with this package in the file LICENSE, and is available at through the world-wide-web at http://dd.cron.ru/license ***************************************************************************/ #include "php.h" #include "php_dbg.h" #include "dbg_ser.h" /* S E R I A L I Z A T I O N E F F O R T */ #define STR_CAT(P,S,I) {\ pval *__p = (P);\ ulong __i = Z_STRLEN_P(__p);\ Z_STRLEN_P(__p) += (I);\ if (Z_STRVAL_P(__p)) {\ Z_STRVAL_P(__p) = (char *)erealloc(Z_STRVAL_P(__p), Z_STRLEN_P(__p) + 1);\ } else {\ Z_STRVAL_P(__p) = emalloc(Z_STRLEN_P(__p) + 1);\ if (Z_STRVAL_P(__p)) *Z_STRVAL_P(__p) = 0;\ }\ if (Z_STRVAL_P(__p) && (I)) {\ memcpy(Z_STRVAL_P(__p) + __i, (S), (I));\ Z_STRVAL_P(__p)[__i + (I)] = 0;\ }\ } static inline void serialize_zval(HashTable *var_hash, zval *data, zval *buf, unsigned int Flags TSRMLS_DC2(DBG, E)); static inline void serialize_hash(HashTable *var_hash, HashTable *ht, zval *buf, unsigned int Flags TSRMLS_DC2(DBG, E)) { HashPosition pos; zval **tmp, *d; ulong index; char *key; int cnt = 0; zend_hash_internal_pointer_reset_ex(ht, &pos); while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &pos) == SUCCESS) { cnt++; switch (ZEND_HASH_GET_CURRENT_KEY_EX(ht, &key, NULL, &index, &pos)) { case HASH_KEY_IS_LONG: MAKE_STD_ZVAL(d); d->type = IS_LONG; d->value.lval = index; #if TRACE_EVAL DBG_TRACE(("[%d]\n",index)); #endif serialize_zval(NULL, d, buf, 0 TSRMLS_CC2(DBG, E)); FREE_ZVAL(d); break; case HASH_KEY_IS_STRING: MAKE_STD_ZVAL(d); d->type = IS_STRING; #if !defined(ZEND_ENGINE_2) Z_STRVAL_P(d) = key; Z_STRLEN_P(d) = strlen(key); #else if (Flags & DSER_DEMANGLE) { char *propname, *classname; zend_unmangle_property_name(key, &classname, &propname); Z_STRVAL_P(d) = propname; Z_STRLEN_P(d) = strlen(propname); } else { Z_STRVAL_P(d) = key; Z_STRLEN_P(d) = strlen(key); } #endif #if TRACE_EVAL DBG_TRACE(("[%s]\n", SON(key))); #endif serialize_zval(NULL, d, buf, Flags & DSER_ADD_DSIGN TSRMLS_CC2(DBG, E)); efree(key); FREE_ZVAL(d); break; } serialize_zval(var_hash, *tmp, buf, Flags & DSER_CORR_REF TSRMLS_CC2(DBG, E)); zend_hash_move_forward_ex(ht, &pos); } } static inline int add_var_hash(HashTable *var_hash, zval *var, unsigned long *var_idx, int corrRef) { unsigned long var_new_idx; unsigned long *pidx; char id[64]; snprintf(id,sizeof(id)-1, "%p", var); id[sizeof(id)-1]=0; #if TRACE_EVAL DBG_TRACE(("\n",id)); #endif if(zend_hash_find(var_hash, id, strlen(id), (void*) &pidx) == SUCCESS) { #if TRACE_EVAL DBG_TRACE(("\n",*pidx)); #endif /* if(!var->is_ref) { var_new_idx = -1; zend_hash_next_index_insert(var_hash, &var_new_idx, sizeof(var_new_idx), NULL); }*/ *var_idx = *pidx; return FAILURE; } var_new_idx = zend_hash_num_elements(var_hash) + 1 + corrRef; #if TRACE_EVAL DBG_TRACE(("\n",var_new_idx)); #endif *var_idx = var_new_idx; zend_hash_add(var_hash, id, strlen(id), &var_new_idx, sizeof(var_new_idx), NULL); return SUCCESS; } static inline void serialize_zval(HashTable *var_hash, zval *data, zval *buf, unsigned int Flags TSRMLS_DC2(DBG, E)) { ulong slen, len; int num_elements; char s[64]; HashTable *ht; unsigned long var_idx; char * type_name; if (var_hash && add_var_hash(var_hash, data, &var_idx, (Flags & DSER_CORR_REF) != 0) == FAILURE) { if (data->is_ref) { slen = sprintf(s, "R:%ld;", var_idx); } else { slen = sprintf(s, "r:%ld;", var_idx); } STR_CAT(buf, s, slen); return; } switch (data->type) { case IS_NULL: STR_CAT(buf, "N;", 2); return; case IS_LONG: slen = snprintf(s, sizeof(s) - 1, "i:%ld;", data->value.lval); STR_CAT(buf, s, slen); return; case IS_DOUBLE: { slen = snprintf(s, sizeof(s)-1, "d:%.*G;",(int) EG(precision), data->value.dval); STR_CAT(buf, s, slen); } return; case IS_CONSTANT: case IS_STRING: if ((Flags & DSER_ADD_DSIGN) != 0) { slen = snprintf(s, sizeof(s)-1, "s:%d:\"", data->value.str.len+1); STR_CAT(buf, s, slen); STR_CAT(buf, "$", 1); if (data->value.str.len != 0) { STR_CAT(buf, Z_STRVAL_P(data), Z_STRLEN_P(data)); } STR_CAT(buf, "\";", 2); } else { slen = snprintf(s, sizeof(s)-1, "s:%d:\"", data->value.str.len); STR_CAT(buf, s, slen); if (data->value.str.len != 0) { STR_CAT(buf, Z_STRVAL_P(data), Z_STRLEN_P(data)); } STR_CAT(buf, "\";", 2); } return; case IS_CONSTANT_ARRAY: case IS_ARRAY: { if (DBG(eval_nest) > 64) { return; } DBG(eval_nest)++; ht = HASH_OF(data); num_elements = ht ? zend_hash_num_elements(ht) : 0; slen = snprintf(s, sizeof(s)-1, "a:%d:{", num_elements); STR_CAT(buf, s, slen); if (ht) serialize_hash(var_hash, ht, buf, Flags & DSER_CORR_REF TSRMLS_CC2(DBG, E)); STR_CAT(buf, "}", 1); DBG(eval_nest)--; return; } case IS_OBJECT: { if (DBG(eval_nest) > 64) { return; } DBG(eval_nest)++; ht = HASH_OF(data); num_elements = ht ? zend_hash_num_elements(ht) : 0; slen = snprintf(s, sizeof(s), "O:%d:\"", Z_OBJCE_P(data)->name_length); STR_CAT(buf, s, slen); STR_CAT(buf, Z_OBJCE_P(data)->name, Z_OBJCE_P(data)->name_length); slen = snprintf(s, sizeof(s), "\":%d:{", num_elements); STR_CAT(buf, s, slen); #if 0 slen = snprintf(s, sizeof(s), "O:%d:\"", data->value.obj.ce->name_length); STR_CAT(buf, s, slen); STR_CAT(buf, data->value.obj.ce->name, data->value.obj.ce->name_length); slen = snprintf(s, sizeof(s), "\":%d:{", num_elements); STR_CAT(buf, s, slen); #endif if (ht) serialize_hash(var_hash, ht, buf, (Flags & DSER_CORR_REF) | DSER_DEMANGLE TSRMLS_CC2(DBG, E)); STR_CAT(buf, "}", 1); DBG(eval_nest)--; return; } case IS_BOOL: slen = snprintf(s, sizeof(s)-1, "b:%ld;", data->value.lval); STR_CAT(buf, s, slen); return; case IS_RESOURCE: type_name = zend_rsrc_list_get_rsrc_type(data->value.lval TSRMLS_CC0); if (!type_name) type_name = ""; len = strlen(type_name); slen = snprintf(s, sizeof(s), "z:%ld:\"", len); STR_CAT(buf, s, slen); STR_CAT(buf, type_name, len); slen = snprintf(s, sizeof(s), "\":%ld;", data->value.lval); STR_CAT(buf, s, slen); return; default: STR_CAT(buf, "?;", 2); return; } } void dbg_serialize_zval(zval *data, zval *buf, unsigned int Flags TSRMLS_DC2(DBG, E)) { HashTable var_hash; #if TRACE_EVAL DBG_TRACE((">>START OF ZVAL EVAL\n")); #endif zend_hash_init(&var_hash,16,NULL,NULL,0); serialize_zval(&var_hash, data, buf, Flags & DSER_ADD_DSIGN TSRMLS_CC2(DBG, E)); zend_hash_destroy(&var_hash); #if TRACE_EVAL DBG_TRACE((">>END OF ZVAL EVAL\n")); #endif } void dbg_serialize_hash(HashTable *ht, zval *buf, unsigned int Flags TSRMLS_DC2(DBG, E)) { int num_elements; ulong slen; char s[64]; HashTable var_hash; #if TRACE_EVAL DBG_TRACE((">>START OF HASH EVAL\n")); #endif num_elements = zend_hash_num_elements(ht); slen = snprintf(s, sizeof(s)-1, "a:%d:{", num_elements); STR_CAT(buf, s, slen); zend_hash_init(&var_hash,16,NULL,NULL,0); serialize_hash(&var_hash, ht, buf, (Flags & DSER_ADD_DSIGN) | DSER_CORR_REF TSRMLS_CC2(DBG, E)); zend_hash_destroy(&var_hash); STR_CAT(buf, "}", 1); #if TRACE_EVAL DBG_TRACE((">>END OF HASH EVAL\n")); #endif }