/* {{{ proto mixed SplPriorityQueue::top() Peek at the top element of the priority queue */ SPL_METHOD(SplPriorityQueue, top) { zval *value, *value_out; spl_heap_object *intern; if (zend_parse_parameters_none() == FAILURE) { return; } intern = Z_SPLHEAP_P(getThis()); if (intern->heap->flags & SPL_HEAP_CORRUPTED) { zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); return; } value = spl_ptr_heap_top(intern->heap); if (!value) { zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty heap", 0); return; } value_out = spl_pqueue_extract_helper(value, intern->flags); if (!value_out) { zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node"); return; } ZVAL_DEREF(value_out); ZVAL_COPY(return_value, value_out); }
static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type) { zval *arg; #ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &arg) == FAILURE) { RETURN_FALSE; } ZVAL_DEREF(arg); #else ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ZVAL_DEREF(arg) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); #endif if (Z_TYPE_P(arg) == type) { if (type == IS_OBJECT) { zend_class_entry *ce = Z_OBJCE_P(arg); if (ZSTR_LEN(ce->name) == sizeof(INCOMPLETE_CLASS) - 1 && !memcmp(ZSTR_VAL(ce->name), INCOMPLETE_CLASS, sizeof(INCOMPLETE_CLASS) - 1)) { RETURN_FALSE; } } else if (type == IS_RESOURCE) { const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg)); if (!type_name) { RETURN_FALSE; } } RETURN_TRUE; } else { RETURN_FALSE; } }
static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* {{{ */ { ZVAL_DEREF(expr); switch (Z_TYPE_P(expr)) { case IS_ARRAY: smart_str_appends(buf, "Array\n"); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) && ++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) { smart_str_appends(buf, " *RECURSION*"); Z_ARRVAL_P(expr)->u.v.nApplyCount--; return; } print_hash(buf, Z_ARRVAL_P(expr), indent, 0); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) { Z_ARRVAL_P(expr)->u.v.nApplyCount--; } break; case IS_OBJECT: { HashTable *properties; int is_temp; zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); smart_str_appends(buf, ZSTR_VAL(class_name)); zend_string_release(class_name); smart_str_appends(buf, " Object\n"); if (Z_OBJ_APPLY_COUNT_P(expr) > 0) { smart_str_appends(buf, " *RECURSION*"); return; } if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) { break; } Z_OBJ_INC_APPLY_COUNT_P(expr); print_hash(buf, properties, indent, 1); Z_OBJ_DEC_APPLY_COUNT_P(expr); if (is_temp) { zend_hash_destroy(properties); FREE_HASHTABLE(properties); } break; } case IS_LONG: smart_str_append_long(buf, Z_LVAL_P(expr)); break; default: { zend_string *str = zval_get_string(expr); smart_str_append(buf, str); zend_string_release(str); } break; } }
static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */ { /* the trivial way would be to do * convert_to_string_ex(arg); * append it and kill the now tmp arg. * but that could cause some E_NOTICE and also damn long lines. */ ZVAL_DEREF(arg); switch (Z_TYPE_P(arg)) { case IS_NULL: smart_str_appends(str, "NULL, "); break; case IS_STRING: smart_str_appendc(str, '\''); smart_str_append_escaped(str, Z_STRVAL_P(arg), MIN(Z_STRLEN_P(arg), 15)); if (Z_STRLEN_P(arg) > 15) { smart_str_appends(str, "...', "); } else { smart_str_appends(str, "', "); } break; case IS_FALSE: smart_str_appends(str, "false, "); break; case IS_TRUE: smart_str_appends(str, "true, "); break; case IS_RESOURCE: smart_str_appends(str, "Resource id #"); smart_str_append_long(str, Z_RES_HANDLE_P(arg)); smart_str_appends(str, ", "); break; case IS_LONG: smart_str_append_long(str, Z_LVAL_P(arg)); smart_str_appends(str, ", "); break; case IS_DOUBLE: { double dval = Z_DVAL_P(arg); char *s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1); int l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval); /* SAFE */ smart_str_appendl(str, s_tmp, l_tmp); smart_str_appends(str, ", "); efree(s_tmp); break; } case IS_ARRAY: smart_str_appends(str, "Array, "); break; case IS_OBJECT: smart_str_appends(str, "Object("); smart_str_appends(str, ZSTR_VAL(Z_OBJCE_P(arg)->name)); smart_str_appends(str, "), "); break; } }
static int php_ds_vector_has_dimension(zval *obj, zval *offset, int check_empty) { ZVAL_DEREF(offset); if (Z_TYPE_P(offset) != IS_LONG) { return 0; } return ds_vector_isset(Z_DS_VECTOR_P(obj), Z_LVAL_P(offset), check_empty); }
static zval *smd_get_zval_ptr_tmpvar(zend_execute_data *execute_data, uint32_t var, zend_free_op *should_free) /* {{{ */ { zval *ret = EX_VAR(var); if (should_free) { *should_free = ret; } ZVAL_DEREF(ret); return ret; } /* }}} */
static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */ { /* the trivial way would be to do * convert_to_string_ex(arg); * append it and kill the now tmp arg. * but that could cause some E_NOTICE and also damn long lines. */ ZVAL_DEREF(arg); switch (Z_TYPE_P(arg)) { case IS_NULL: smart_str_appends(str, "NULL, "); break; case IS_STRING: smart_str_appendc(str, '\''); smart_str_append_escaped(str, Z_STRVAL_P(arg), MIN(Z_STRLEN_P(arg), 15)); if (Z_STRLEN_P(arg) > 15) { smart_str_appends(str, "...', "); } else { smart_str_appends(str, "', "); } break; case IS_FALSE: smart_str_appends(str, "false, "); break; case IS_TRUE: smart_str_appends(str, "true, "); break; case IS_RESOURCE: smart_str_appends(str, "Resource id #"); smart_str_append_long(str, Z_RES_HANDLE_P(arg)); smart_str_appends(str, ", "); break; case IS_LONG: smart_str_append_long(str, Z_LVAL_P(arg)); smart_str_appends(str, ", "); break; case IS_DOUBLE: { smart_str_append_printf(str, "%.*G", (int) EG(precision), Z_DVAL_P(arg)); smart_str_appends(str, ", "); break; } case IS_ARRAY: smart_str_appends(str, "Array, "); break; case IS_OBJECT: { zend_string *class_name = Z_OBJ_HANDLER_P(arg, get_class_name)(Z_OBJ_P(arg)); smart_str_appends(str, "Object("); smart_str_appends(str, ZSTR_VAL(class_name)); smart_str_appends(str, "), "); zend_string_release_ex(class_name, 0); break; } } }
static void curlfile_get_property(char *name, size_t name_len, INTERNAL_FUNCTION_PARAMETERS) { zval *res, rv; if (zend_parse_parameters_none() == FAILURE) { return; } res = zend_read_property(curl_CURLFile_class, getThis(), name, name_len, 1, &rv); ZVAL_DEREF(res); ZVAL_COPY(return_value, res); }
/* {{{ mysqlnd_stmt_execute_prepare_param_types */ static enum_func_status mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copies_param, int * resend_types_next_time) { unsigned int i; DBG_ENTER("mysqlnd_stmt_execute_prepare_param_types"); for (i = 0; i < stmt->param_count; i++) { short current_type = stmt->param_bind[i].type; zval *parameter = &stmt->param_bind[i].zv; ZVAL_DEREF(parameter); if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { /* always copy the var, because we do many conversions */ if (Z_TYPE_P(parameter) != IS_LONG && PASS != mysqlnd_stmt_copy_it(copies_param, parameter, stmt->param_count, i)) { SET_OOM_ERROR(*stmt->error_info); goto end; } /* if it doesn't fit in a long send it as a string. Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX */ if (Z_TYPE_P(parameter) != IS_LONG) { zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: parameter; /* Because converting to double and back to long can lead to losing precision we need second variable. Conversion to double is to see if value is too big for a long. As said, precision could be lost. */ zval tmp_data_copy; ZVAL_COPY(&tmp_data_copy, tmp_data); convert_to_double_ex(&tmp_data_copy); /* if it doesn't fit in a long send it as a string. Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX We do transformation here, which will be used later when sending types. The code later relies on this. */ if (Z_DVAL(tmp_data_copy) > ZEND_LONG_MAX || Z_DVAL(tmp_data_copy) < ZEND_LONG_MIN) { stmt->send_types_to_server = *resend_types_next_time = 1; convert_to_string_ex(tmp_data); } else { convert_to_long_ex(tmp_data); } zval_ptr_dtor(&tmp_data_copy); } } } DBG_RETURN(PASS); end: DBG_RETURN(FAIL); }
ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent) /* {{{ */ { ZVAL_DEREF(expr); switch (Z_TYPE_P(expr)) { case IS_ARRAY: ZEND_PUTS_EX("Array\n"); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) && ++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) { ZEND_PUTS_EX(" *RECURSION*"); Z_ARRVAL_P(expr)->u.v.nApplyCount--; return; } print_hash(write_func, Z_ARRVAL_P(expr), indent, 0); if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) { Z_ARRVAL_P(expr)->u.v.nApplyCount--; } break; case IS_OBJECT: { HashTable *properties; int is_temp; zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); ZEND_PUTS_EX(ZSTR_VAL(class_name)); zend_string_release(class_name); ZEND_PUTS_EX(" Object\n"); if (Z_OBJ_APPLY_COUNT_P(expr) > 0) { ZEND_PUTS_EX(" *RECURSION*"); return; } if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) { break; } Z_OBJ_INC_APPLY_COUNT_P(expr); print_hash(write_func, properties, indent, 1); Z_OBJ_DEC_APPLY_COUNT_P(expr); if (is_temp) { zend_hash_destroy(properties); FREE_HASHTABLE(properties); } break; } default: zend_print_zval_ex(write_func, expr, indent); break; } }
static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements) { HashTable *ht; zend_bool has_wakeup; if (Z_TYPE_P(rval) != IS_OBJECT) { return 0; } has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY && zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1); ht = Z_OBJPROP_P(rval); if (elements >= (zend_long)(HT_MAX_SIZE - zend_hash_num_elements(ht))) { return 0; } zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED)); if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) { if (has_wakeup) { ZVAL_DEREF(rval); GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED; } return 0; } ZVAL_DEREF(rval); if (has_wakeup) { /* Delay __wakeup call until end of serialization */ zval *wakeup_var = var_tmp_var(var_hash); ZVAL_COPY(wakeup_var, rval); Z_EXTRA_P(wakeup_var) = VAR_WAKEUP_FLAG; } return finish_nested_data(UNSERIALIZE_PASSTHRU); }
/* {{{ proto mixed|NULL SplHeap::current() Return current datastructure entry */ SPL_METHOD(SplHeap, current) { spl_heap_object *intern = Z_SPLHEAP_P(getThis()); zval *element = &intern->heap->elements[0]; if (zend_parse_parameters_none() == FAILURE) { return; } if (!intern->heap->count || Z_ISUNDEF_P(element)) { RETURN_NULL(); } else { ZVAL_DEREF(element); ZVAL_COPY(return_value, element); } }
static zend_bool zlib_create_dictionary_string(HashTable *options, char **dict, size_t *dictlen) { zval *option_buffer; if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("dictionary"))) != NULL) { HashTable *dictionary; ZVAL_DEREF(option_buffer); if (Z_TYPE_P(option_buffer) != IS_ARRAY) { php_error_docref(NULL, E_WARNING, "dictionary must be of type array, got %s", zend_get_type_by_const(Z_TYPE_P(option_buffer))); return 0; } dictionary = Z_ARR_P(option_buffer); if (zend_hash_num_elements(dictionary) > 0) { char *dictptr; zval *cur; zend_string **strings = emalloc(sizeof(zend_string *) * zend_hash_num_elements(dictionary)); zend_string **end, **ptr = strings - 1; ZEND_HASH_FOREACH_VAL(dictionary, cur) { int i; *++ptr = zval_get_string(cur); if (!*ptr || (*ptr)->len == 0) { if (*ptr) { efree(*ptr); } while (--ptr >= strings) { efree(ptr); } efree(strings); php_error_docref(NULL, E_WARNING, "dictionary entries must be non-empty strings"); return 0; } for (i = 0; i < (*ptr)->len; i++) { if ((*ptr)->val[i] == 0) { do { efree(ptr); } while (--ptr >= strings); efree(strings); php_error_docref(NULL, E_WARNING, "dictionary entries must not contain a NULL-byte"); return 0; } } *dictlen += (*ptr)->len + 1; } ZEND_HASH_FOREACH_END();
/* {{{ proto SimpleXMLIterator SimpleXMLIterator::current() Get current element */ PHP_METHOD(ce_SimpleXMLIterator, current) { php_sxe_object *sxe = Z_SXEOBJ_P(getThis()); zval *data; if (zend_parse_parameters_none() == FAILURE) { return; } if (Z_ISUNDEF(sxe->iter.data)) { return; /* return NULL */ } data = &sxe->iter.data; ZVAL_DEREF(data); ZVAL_COPY(return_value, data); }
/* {{{ proto mixed|NULL SplDoublyLinkedList::current() Return current datastructure entry */ SPL_METHOD(SplDoublyLinkedList, current) { spl_dllist_object *intern = Z_SPLDLLIST_P(getThis()); spl_ptr_llist_element *element = intern->traverse_pointer; if (zend_parse_parameters_none() == FAILURE) { return; } if (element == NULL || Z_ISUNDEF(element->data)) { RETURN_NULL(); } else { zval *value = &element->data; ZVAL_DEREF(value); ZVAL_COPY(return_value, value); } }
static void php_ds_vector_write_dimension(zval *obj, zval *offset, zval *value) { ds_vector_t *vector = Z_DS_VECTOR_P(obj); /* $v[] = ... */ if (offset == NULL) { ds_vector_push(vector, value); } else { ZVAL_DEREF(offset); if (Z_TYPE_P(offset) != IS_LONG) { INTEGER_INDEX_REQUIRED(offset); } else { ds_vector_set(vector, Z_LVAL_P(offset), value); } } }
static void php_exec_ex(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ { char *cmd; size_t cmd_len; zval *ret_code=NULL, *ret_array=NULL; int ret; ZEND_PARSE_PARAMETERS_START(1, (mode ? 2 : 3)) Z_PARAM_STRING(cmd, cmd_len) Z_PARAM_OPTIONAL if (!mode) { Z_PARAM_ZVAL(ret_array) } Z_PARAM_ZVAL(ret_code) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); if (!cmd_len) { php_error_docref(NULL, E_WARNING, "Cannot execute a blank command"); RETURN_FALSE; } if (strlen(cmd) != cmd_len) { php_error_docref(NULL, E_WARNING, "NULL byte detected. Possible attack"); RETURN_FALSE; } if (!ret_array) { ret = php_exec(mode, cmd, NULL, return_value); } else { if (Z_TYPE_P(Z_REFVAL_P(ret_array)) == IS_ARRAY) { ZVAL_DEREF(ret_array); SEPARATE_ARRAY(ret_array); } else { ret_array = zend_try_array_init(ret_array); if (!ret_array) { return; } } ret = php_exec(2, cmd, ret_array, return_value); } if (ret_code) { ZEND_TRY_ASSIGN_LONG(ret_code, ret); } }
/* {{{ php_converter_default_callback */ static void php_converter_default_callback(zval *return_value, zval *zobj, zend_long reason, zval *error) { ZVAL_DEREF(error); zval_dtor(error); ZVAL_LONG(error, U_ZERO_ERROR); /* Basic functionality so children can call parent::toUCallback() */ switch (reason) { case UCNV_UNASSIGNED: case UCNV_ILLEGAL: case UCNV_IRREGULAR: { php_converter_object *objval = (php_converter_object*)CONV_GET(zobj); char chars[127]; int8_t chars_len = sizeof(chars); UErrorCode uerror = U_ZERO_ERROR; if(!objval->src) { php_converter_throw_failure(objval, U_INVALID_STATE_ERROR, "Source Converter has not been initialized yet"); chars[0] = 0x1A; chars[1] = 0; chars_len = 1; ZVAL_LONG(error, U_INVALID_STATE_ERROR); RETVAL_STRINGL(chars, chars_len); return; } /* Yes, this is fairly wasteful at first glance, * but considering that the alternative is to store * what's sent into setSubstChars() and the fact * that this is an extremely unlikely codepath * I'd rather take the CPU hit here, than waste time * storing a value I'm unlikely to use. */ ucnv_getSubstChars(objval->src, chars, &chars_len, &uerror); if (U_FAILURE(uerror)) { THROW_UFAILURE(objval, "ucnv_getSubstChars", uerror); chars[0] = 0x1A; chars[1] = 0; chars_len = 1; ZVAL_LONG(error, uerror); } RETVAL_STRINGL(chars, chars_len); } } }
U_CFUNC PHP_FUNCTION(intltz_get_canonical_id) { char *str_id; size_t str_id_len; zval *is_systemid = NULL; intl_error_reset(NULL); if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|z", &str_id, &str_id_len, &is_systemid) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intltz_get_canonical_id: bad arguments", 0); RETURN_FALSE; } UErrorCode status = UErrorCode(); UnicodeString id; if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, "intltz_get_canonical_id: could not convert time zone id to UTF-16", 0); RETURN_FALSE; } UnicodeString result; UBool isSystemID; TimeZone::getCanonicalID(id, result, isSystemID, status); INTL_CHECK_STATUS(status, "intltz_get_canonical_id: error obtaining canonical ID"); char *str; int str_len; intl_convert_utf16_to_utf8(&str, &str_len, result.getBuffer(), result.length(), &status); INTL_CHECK_STATUS(status, "intltz_get_canonical_id: could not convert time zone id to UTF-16"); RETVAL_STRINGL(str, str_len); //???? efree(str); if (is_systemid) { /* by-ref argument passed */ ZVAL_DEREF(is_systemid); zval_dtor(is_systemid); ZVAL_BOOL(is_systemid, isSystemID); } }
/* {{{ proto mixed SplDoublyLinkedList::bottom() Peek at the bottom element of the SplDoublyLinkedList */ SPL_METHOD(SplDoublyLinkedList, bottom) { zval *value; spl_dllist_object *intern; if (zend_parse_parameters_none() == FAILURE) { return; } intern = Z_SPLDLLIST_P(getThis()); value = spl_ptr_llist_first(intern->llist); if (value == NULL || Z_ISUNDEF_P(value)) { zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0); return; } ZVAL_DEREF(value); ZVAL_COPY(return_value, value); }
static void php_ds_vector_unset_dimension(zval *obj, zval *offset) { zend_long index; ds_vector_t *vector = Z_DS_VECTOR_P(obj); ZVAL_DEREF(offset); if (Z_TYPE_P(offset) == IS_LONG) { index = Z_LVAL_P(offset); } else { if (zend_parse_parameter(ZEND_PARSE_PARAMS_QUIET, 1, offset, "l", &index) == FAILURE) { return; } } if (ds_vector_index_exists(vector, index)) { // to avoid OutOfBounds ds_vector_remove(vector, index, NULL); } }
/* {{{ mysqlnd_stmt_execute_store_types */ static void mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval * copies, zend_uchar ** p) { unsigned int i; for (i = 0; i < stmt->param_count; i++) { short current_type = stmt->param_bind[i].type; zval *parameter = &stmt->param_bind[i].zv; /* our types are not unsigned */ #if SIZEOF_ZEND_LONG==8 if (current_type == MYSQL_TYPE_LONG) { current_type = MYSQL_TYPE_LONGLONG; } #endif ZVAL_DEREF(parameter); if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { /* if it doesn't fit in a long send it as a string. Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX */ if (Z_TYPE_P(parameter) != IS_LONG) { const zval *tmp_data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i] : parameter; /* In case of IS_LONG we do nothing, it is ok, in case of string, we just need to set current_type. The actual transformation has been performed several dozens line above. */ if (Z_TYPE_P(tmp_data) == IS_STRING) { current_type = MYSQL_TYPE_VAR_STRING; /* don't change stmt->param_bind[i].type to MYSQL_TYPE_VAR_STRING we force convert_to_long_ex in all cases, thus the type will be right in the next switch. if the type is however not long, then we will do a goto in the next switch. We want to preserve the original bind type given by the user. Thus, we do these hacks. */ } } } int2store(*p, current_type); *p+= 2; } }
static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type) { zval *arg; #ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) { RETURN_FALSE; } ZVAL_DEREF(arg); #else ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ZVAL_DEREF(arg) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); #endif if (Z_TYPE_P(arg) == type) { if (type == IS_OBJECT) { zend_class_entry *ce; if (Z_OBJ_HT_P(arg)->get_class_entry == NULL) { /* if there's no get_class_entry it's not a PHP object, so it can't be INCOMPLETE_CLASS */ RETURN_TRUE; } ce = Z_OBJCE_P(arg); if (ce->name->len == sizeof(INCOMPLETE_CLASS) - 1 && !strncmp(ce->name->val, INCOMPLETE_CLASS, ce->name->len)) { RETURN_FALSE; } } else if (type == IS_RESOURCE) { const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg) TSRMLS_CC); if (!type_name) { RETURN_FALSE; } } RETURN_TRUE; } else { RETURN_FALSE; } }
static PHP_METHOD(HttpMessageParser, parse) { php_http_message_parser_object_t *parser_obj; zval *zmsg; char *data_str; size_t data_len; zend_long flags; php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "slz", &data_str, &data_len, &flags, &zmsg), invalid_arg, return); parser_obj = PHP_HTTP_OBJ(NULL, getThis()); php_http_buffer_append(&parser_obj->buffer, data_str, data_len); RETVAL_LONG(php_http_message_parser_parse(parser_obj->parser, &parser_obj->buffer, flags, &parser_obj->parser->message)); ZVAL_DEREF(zmsg); zval_dtor(zmsg); ZVAL_NULL(zmsg); if (parser_obj->parser->message) { php_http_message_t *msg_cpy = php_http_message_copy(parser_obj->parser->message, NULL); php_http_message_object_t *msg_obj = php_http_message_object_new_ex(php_http_message_class_entry, msg_cpy); ZVAL_OBJ(zmsg, &msg_obj->zo); } }
/* {{{ proto mixed|NULL SplPriorityQueue::current() Return current datastructure entry */ SPL_METHOD(SplPriorityQueue, current) { spl_heap_object *intern = Z_SPLHEAP_P(getThis()); zval *element = &intern->heap->elements[0]; if (zend_parse_parameters_none() == FAILURE) { return; } if (!intern->heap->count || Z_ISUNDEF_P(element)) { RETURN_NULL(); } else { zval *data = spl_pqueue_extract_helper(element, intern->flags); if (!data) { zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node"); RETURN_NULL(); } ZVAL_DEREF(data); ZVAL_COPY(return_value, data); } }
/* {{{ mysqlnd_stmt_execute_store_param_values */ static void mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies, zend_uchar * buf, zend_uchar ** p, size_t null_byte_offset) { unsigned int i; for (i = 0; i < stmt->param_count; i++) { zval *data, *parameter = &stmt->param_bind[i].zv; ZVAL_DEREF(parameter); data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i]: parameter; /* Handle long data */ if (!Z_ISUNDEF_P(parameter) && Z_TYPE_P(data) == IS_NULL) { (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7)); } else { switch (stmt->param_bind[i].type) { case MYSQL_TYPE_DOUBLE: convert_to_double_ex(data); float8store(*p, Z_DVAL_P(data)); (*p) += 8; break; case MYSQL_TYPE_LONGLONG: if (Z_TYPE_P(data) == IS_STRING) { goto send_string; } /* data has alreade been converted to long */ int8store(*p, Z_LVAL_P(data)); (*p) += 8; break; case MYSQL_TYPE_LONG: if (Z_TYPE_P(data) == IS_STRING) { goto send_string; } /* data has alreade been converted to long */ int4store(*p, Z_LVAL_P(data)); (*p) += 4; break; case MYSQL_TYPE_LONG_BLOB: if (stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED) { stmt->param_bind[i].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED; } else { /* send_long_data() not called, send empty string */ *p = php_mysqlnd_net_store_length(*p, 0); } break; case MYSQL_TYPE_VAR_STRING: send_string: { size_t len = Z_STRLEN_P(data); /* to is after p. The latter hasn't been moved */ *p = php_mysqlnd_net_store_length(*p, len); memcpy(*p, Z_STRVAL_P(data), len); (*p) += len; } break; default: /* Won't happen, but set to NULL */ (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7)); break; } } } }
/* {{{ php_url_encode_hash */ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, const char *num_prefix, size_t num_prefix_len, const char *key_prefix, size_t key_prefix_len, const char *key_suffix, size_t key_suffix_len, zval *type, char *arg_sep, int enc_type) { zend_string *key = NULL; char *newprefix, *p; const char *prop_name; size_t arg_sep_len, newprefix_len, prop_len; zend_ulong idx; zval *zdata = NULL; if (!ht) { return FAILURE; } if (GC_IS_RECURSIVE(ht)) { /* Prevent recursion */ return SUCCESS; } if (!arg_sep) { arg_sep = INI_STR("arg_separator.output"); if (!arg_sep || !strlen(arg_sep)) { arg_sep = URL_DEFAULT_ARG_SEP; } } arg_sep_len = strlen(arg_sep); ZEND_HASH_FOREACH_KEY_VAL(ht, idx, key, zdata) { zend_bool is_dynamic = 1; if (Z_TYPE_P(zdata) == IS_INDIRECT) { zdata = Z_INDIRECT_P(zdata); if (Z_ISUNDEF_P(zdata)) { continue; } is_dynamic = 0; } /* handling for private & protected object properties */ if (key) { prop_name = ZSTR_VAL(key); prop_len = ZSTR_LEN(key); if (type != NULL && zend_check_property_access(Z_OBJ_P(type), key, is_dynamic) != SUCCESS) { /* property not visible in this scope */ continue; } if (ZSTR_VAL(key)[0] == '\0' && type != NULL) { const char *tmp; zend_unmangle_property_name_ex(key, &tmp, &prop_name, &prop_len); } else { prop_name = ZSTR_VAL(key); prop_len = ZSTR_LEN(key); } } else { prop_name = NULL; prop_len = 0; } ZVAL_DEREF(zdata); if (Z_TYPE_P(zdata) == IS_ARRAY || Z_TYPE_P(zdata) == IS_OBJECT) { if (key) { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(prop_name, prop_len); } else { ekey = php_url_encode(prop_name, prop_len); } newprefix_len = key_suffix_len + ZSTR_LEN(ekey) + key_prefix_len + 3 /* %5B */; newprefix = emalloc(newprefix_len + 1); p = newprefix; if (key_prefix) { memcpy(p, key_prefix, key_prefix_len); p += key_prefix_len; } memcpy(p, ZSTR_VAL(ekey), ZSTR_LEN(ekey)); p += ZSTR_LEN(ekey); zend_string_free(ekey); if (key_suffix) { memcpy(p, key_suffix, key_suffix_len); p += key_suffix_len; } *(p++) = '%'; *(p++) = '5'; *(p++) = 'B'; *p = '\0'; } else { char *ekey; size_t ekey_len; /* Is an integer key */ ekey_len = spprintf(&ekey, 0, ZEND_LONG_FMT, idx); newprefix_len = key_prefix_len + num_prefix_len + ekey_len + key_suffix_len + 3 /* %5B */; newprefix = emalloc(newprefix_len + 1); p = newprefix; if (key_prefix) { memcpy(p, key_prefix, key_prefix_len); p += key_prefix_len; } memcpy(p, num_prefix, num_prefix_len); p += num_prefix_len; memcpy(p, ekey, ekey_len); p += ekey_len; efree(ekey); if (key_suffix) { memcpy(p, key_suffix, key_suffix_len); p += key_suffix_len; } *(p++) = '%'; *(p++) = '5'; *(p++) = 'B'; *p = '\0'; } if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) { GC_PROTECT_RECURSION(ht); } php_url_encode_hash_ex(HASH_OF(zdata), formstr, NULL, 0, newprefix, newprefix_len, "%5D", 3, (Z_TYPE_P(zdata) == IS_OBJECT ? zdata : NULL), arg_sep, enc_type); if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) { GC_UNPROTECT_RECURSION(ht); } efree(newprefix); } else if (Z_TYPE_P(zdata) == IS_NULL || Z_TYPE_P(zdata) == IS_RESOURCE) { /* Skip these types */ continue; } else { if (formstr->s) { smart_str_appendl(formstr, arg_sep, arg_sep_len); } /* Simple key=value */ smart_str_appendl(formstr, key_prefix, key_prefix_len); if (key) { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(prop_name, prop_len); } else { ekey = php_url_encode(prop_name, prop_len); } smart_str_append(formstr, ekey); zend_string_free(ekey); } else { /* Numeric key */ if (num_prefix) { smart_str_appendl(formstr, num_prefix, num_prefix_len); } smart_str_append_long(formstr, idx); } smart_str_appendl(formstr, key_suffix, key_suffix_len); smart_str_appendl(formstr, "=", 1); switch (Z_TYPE_P(zdata)) { case IS_STRING: { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); } else { ekey = php_url_encode(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); } smart_str_append(formstr, ekey); zend_string_free(ekey); } break; case IS_LONG: smart_str_append_long(formstr, Z_LVAL_P(zdata)); break; case IS_FALSE: smart_str_appendl(formstr, "0", sizeof("0")-1); break; case IS_TRUE: smart_str_appendl(formstr, "1", sizeof("1")-1); break; case IS_DOUBLE: { char *ekey; size_t ekey_len; ekey_len = spprintf(&ekey, 0, "%.*G", (int) EG(precision), Z_DVAL_P(zdata)); smart_str_appendl(formstr, ekey, ekey_len); efree(ekey); } break; default: { zend_string *ekey; zend_string *tmp; zend_string *str= zval_get_tmp_string(zdata, &tmp); if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(ZSTR_VAL(str), ZSTR_LEN(str)); } else { ekey = php_url_encode(ZSTR_VAL(str), ZSTR_LEN(str)); } smart_str_append(formstr, ekey); zend_tmp_string_release(tmp); zend_string_free(ekey); } } } } ZEND_HASH_FOREACH_END();
/* {{{ php_url_encode_hash */ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, const char *num_prefix, size_t num_prefix_len, const char *key_prefix, size_t key_prefix_len, const char *key_suffix, size_t key_suffix_len, zval *type, char *arg_sep, int enc_type) { zend_string *key = NULL; char *newprefix, *p; const char *prop_name; size_t arg_sep_len, newprefix_len, prop_len; zend_ulong idx; zval *zdata = NULL, copyzval; if (!ht) { return FAILURE; } if (ht->u.v.nApplyCount > 0) { /* Prevent recursion */ return SUCCESS; } if (!arg_sep) { arg_sep = INI_STR("arg_separator.output"); if (!arg_sep || !strlen(arg_sep)) { arg_sep = URL_DEFAULT_ARG_SEP; } } arg_sep_len = strlen(arg_sep); ZEND_HASH_FOREACH_KEY_VAL_IND(ht, idx, key, zdata) { /* handling for private & protected object properties */ if (key) { if (key->val[0] == '\0' && type != NULL) { const char *tmp; zend_object *zobj = Z_OBJ_P(type); if (zend_check_property_access(zobj, key) != SUCCESS) { /* private or protected property access outside of the class */ continue; } zend_unmangle_property_name_ex(key, &tmp, &prop_name, &prop_len); } else { prop_name = key->val; prop_len = key->len; } } else { prop_name = NULL; prop_len = 0; } ZVAL_DEREF(zdata); if (Z_TYPE_P(zdata) == IS_ARRAY || Z_TYPE_P(zdata) == IS_OBJECT) { if (key) { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(prop_name, prop_len); } else { ekey = php_url_encode(prop_name, prop_len); } newprefix_len = key_suffix_len + ekey->len + key_prefix_len + 3 /* %5B */; newprefix = emalloc(newprefix_len + 1); p = newprefix; if (key_prefix) { memcpy(p, key_prefix, key_prefix_len); p += key_prefix_len; } memcpy(p, ekey->val, ekey->len); p += ekey->len; zend_string_free(ekey); if (key_suffix) { memcpy(p, key_suffix, key_suffix_len); p += key_suffix_len; } *(p++) = '%'; *(p++) = '5'; *(p++) = 'B'; *p = '\0'; } else { char *ekey; size_t ekey_len; /* Is an integer key */ ekey_len = spprintf(&ekey, 0, "%pd", idx); newprefix_len = key_prefix_len + num_prefix_len + ekey_len + key_suffix_len + 3 /* %5B */; newprefix = emalloc(newprefix_len + 1); p = newprefix; if (key_prefix) { memcpy(p, key_prefix, key_prefix_len); p += key_prefix_len; } memcpy(p, num_prefix, num_prefix_len); p += num_prefix_len; memcpy(p, ekey, ekey_len); p += ekey_len; efree(ekey); if (key_suffix) { memcpy(p, key_suffix, key_suffix_len); p += key_suffix_len; } *(p++) = '%'; *(p++) = '5'; *(p++) = 'B'; *p = '\0'; } if (ZEND_HASH_APPLY_PROTECTION(ht)) { ht->u.v.nApplyCount++; } php_url_encode_hash_ex(HASH_OF(zdata), formstr, NULL, 0, newprefix, newprefix_len, "%5D", 3, (Z_TYPE_P(zdata) == IS_OBJECT ? zdata : NULL), arg_sep, enc_type); if (ZEND_HASH_APPLY_PROTECTION(ht)) { ht->u.v.nApplyCount--; } efree(newprefix); } else if (Z_TYPE_P(zdata) == IS_NULL || Z_TYPE_P(zdata) == IS_RESOURCE) { /* Skip these types */ continue; } else { if (formstr->s) { smart_str_appendl(formstr, arg_sep, arg_sep_len); } /* Simple key=value */ smart_str_appendl(formstr, key_prefix, key_prefix_len); if (key) { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(prop_name, prop_len); } else { ekey = php_url_encode(prop_name, prop_len); } smart_str_append(formstr, ekey); zend_string_free(ekey); } else { /* Numeric key */ if (num_prefix) { smart_str_appendl(formstr, num_prefix, num_prefix_len); } smart_str_append_long(formstr, idx); } smart_str_appendl(formstr, key_suffix, key_suffix_len); smart_str_appendl(formstr, "=", 1); switch (Z_TYPE_P(zdata)) { case IS_STRING: { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); } else { ekey = php_url_encode(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); } smart_str_append(formstr, ekey); zend_string_free(ekey); } break; case IS_LONG: smart_str_append_long(formstr, Z_LVAL_P(zdata)); break; case IS_FALSE: smart_str_appendl(formstr, "0", sizeof("0")-1); break; case IS_TRUE: smart_str_appendl(formstr, "1", sizeof("1")-1); break; case IS_DOUBLE: { char *ekey; size_t ekey_len; ekey_len = spprintf(&ekey, 0, "%.*G", (int) EG(precision), Z_DVAL_P(zdata)); smart_str_appendl(formstr, ekey, ekey_len); efree(ekey); } break; default: { zend_string *ekey; /* fall back on convert to string */ ZVAL_DUP(©zval, zdata); convert_to_string_ex(©zval); if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(Z_STRVAL(copyzval), Z_STRLEN(copyzval)); } else { ekey = php_url_encode(Z_STRVAL(copyzval), Z_STRLEN(copyzval)); } smart_str_append(formstr, ekey); zval_ptr_dtor(©zval); zend_string_free(ekey); } } } } ZEND_HASH_FOREACH_END(); return SUCCESS; }
static zend_bool zlib_create_dictionary_string(HashTable *options, char **dict, size_t *dictlen) { zval *option_buffer; if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("dictionary"))) != NULL) { ZVAL_DEREF(option_buffer); switch (Z_TYPE_P(option_buffer)) { case IS_STRING: { zend_string *str = Z_STR_P(option_buffer); int i; zend_bool last_null = 1; for (i = 0; i < ZSTR_LEN(str); i++) { if (ZSTR_VAL(str)[i]) { last_null = 0; } else { if (last_null) { php_error_docref(NULL, E_WARNING, "dictionary string must not contain empty entries (two consecutive NULL-bytes or one at the very beginning)"); return 0; } last_null = 1; } } if (!last_null) { php_error_docref(NULL, E_WARNING, "dictionary string must be NULL-byte terminated (each dictionary entry has to be NULL-terminated)"); } *dict = emalloc(ZSTR_LEN(str)); memcpy(*dict, ZSTR_VAL(str), ZSTR_LEN(str)); *dictlen = ZSTR_LEN(str); } break; case IS_ARRAY: { HashTable *dictionary = Z_ARR_P(option_buffer); if (zend_hash_num_elements(dictionary) > 0) { char *dictptr; zval *cur; zend_string **strings = emalloc(sizeof(zend_string *) * zend_hash_num_elements(dictionary)); zend_string **end, **ptr = strings - 1; ZEND_HASH_FOREACH_VAL(dictionary, cur) { int i; *++ptr = zval_get_string(cur); if (!*ptr || ZSTR_LEN(*ptr) == 0) { if (*ptr) { efree(*ptr); } while (--ptr >= strings) { efree(ptr); } efree(strings); php_error_docref(NULL, E_WARNING, "dictionary entries must be non-empty strings"); return 0; } for (i = 0; i < ZSTR_LEN(*ptr); i++) { if (ZSTR_VAL(*ptr)[i] == 0) { do { efree(ptr); } while (--ptr >= strings); efree(strings); php_error_docref(NULL, E_WARNING, "dictionary entries must not contain a NULL-byte"); return 0; } } *dictlen += ZSTR_LEN(*ptr) + 1; } ZEND_HASH_FOREACH_END(); dictptr = *dict = emalloc(*dictlen); ptr = strings; end = strings + zend_hash_num_elements(dictionary); do { memcpy(dictptr, ZSTR_VAL(*ptr), ZSTR_LEN(*ptr)); dictptr += ZSTR_LEN(*ptr); *dictptr++ = 0; zend_string_release(*ptr); } while (++ptr != end); efree(strings); } } break;
void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) { int i = 0; zend_op *opline = op_array->opcodes; zend_op *end = opline + op_array->last; zend_bool collect_constants = (op_array == &ctx->script->main_op_array); while (opline < end) { switch (opline->opcode) { case ZEND_ADD: case ZEND_SUB: case ZEND_MUL: case ZEND_DIV: case ZEND_MOD: case ZEND_POW: case ZEND_SL: case ZEND_SR: case ZEND_CONCAT: case ZEND_FAST_CONCAT: case ZEND_IS_EQUAL: case ZEND_IS_NOT_EQUAL: case ZEND_IS_SMALLER: case ZEND_IS_SMALLER_OR_EQUAL: case ZEND_IS_IDENTICAL: case ZEND_IS_NOT_IDENTICAL: case ZEND_BW_OR: case ZEND_BW_AND: case ZEND_BW_XOR: case ZEND_BOOL_XOR: if (ZEND_OP1_TYPE(opline) == IS_CONST && ZEND_OP2_TYPE(opline) == IS_CONST) { /* binary operation with constant operands */ binary_op_type binary_op = get_binary_op(opline->opcode); uint32_t tv = ZEND_RESULT(opline).var; /* temporary variable */ zval result; int er; if (opline->opcode == ZEND_DIV && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG && Z_LVAL(ZEND_OP2_LITERAL(opline)) == 0) { /* div by 0 */ break; } er = EG(error_reporting); EG(error_reporting) = 0; /* evaluate constant expression */ if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) != SUCCESS) { EG(error_reporting) = er; break; } EG(error_reporting) = er; if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result)) { literal_dtor(&ZEND_OP1_LITERAL(opline)); literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); } } break; case ZEND_CAST: if (ZEND_OP1_TYPE(opline) == IS_CONST && opline->extended_value != IS_ARRAY && opline->extended_value != IS_OBJECT && opline->extended_value != IS_RESOURCE) { /* cast of constant operand */ zend_uchar type = opline->result_type; uint32_t tv = ZEND_RESULT(opline).var; /* temporary variable */ zval res; res = ZEND_OP1_LITERAL(opline); zval_copy_ctor(&res); switch (opline->extended_value) { case IS_NULL: convert_to_null(&res); break; case _IS_BOOL: convert_to_boolean(&res); break; case IS_LONG: convert_to_long(&res); break; case IS_DOUBLE: convert_to_double(&res); break; case IS_STRING: convert_to_string(&res); break; } if (zend_optimizer_replace_by_const(op_array, opline + 1, type, tv, &res)) { literal_dtor(&ZEND_OP1_LITERAL(opline)); MAKE_NOP(opline); } } else if (opline->extended_value == _IS_BOOL) { /* T = CAST(X, IS_BOOL) => T = BOOL(X) */ opline->opcode = ZEND_BOOL; opline->extended_value = 0; } break; case ZEND_BW_NOT: case ZEND_BOOL_NOT: if (ZEND_OP1_TYPE(opline) == IS_CONST) { /* unary operation on constant operand */ unary_op_type unary_op = get_unary_op(opline->opcode); zval result; uint32_t tv = ZEND_RESULT(opline).var; /* temporary variable */ int er; er = EG(error_reporting); EG(error_reporting) = 0; if (unary_op(&result, &ZEND_OP1_LITERAL(opline)) != SUCCESS) { EG(error_reporting) = er; break; } EG(error_reporting) = er; if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result)) { literal_dtor(&ZEND_OP1_LITERAL(opline)); MAKE_NOP(opline); } } break; #if 0 case ZEND_ADD_STRING: case ZEND_ADD_CHAR: { zend_op *next_op = opline + 1; int requires_conversion = (opline->opcode == ZEND_ADD_CHAR? 1 : 0); size_t final_length = 0; zend_string *str; char *ptr; zend_op *last_op; /* There is always a ZEND_RETURN at the end if (next_op>=end) { break; } */ while (next_op->opcode == ZEND_ADD_STRING || next_op->opcode == ZEND_ADD_CHAR) { if (ZEND_RESULT(opline).var != ZEND_RESULT(next_op).var) { break; } if (next_op->opcode == ZEND_ADD_CHAR) { final_length += 1; } else { /* ZEND_ADD_STRING */ final_length += Z_STRLEN(ZEND_OP2_LITERAL(next_op)); } next_op++; } if (final_length == 0) { break; } last_op = next_op; final_length += (requires_conversion? 1 : Z_STRLEN(ZEND_OP2_LITERAL(opline))); str = zend_string_alloc(final_length, 0); str->len = final_length; ptr = str->val; ptr[final_length] = '\0'; if (requires_conversion) { /* ZEND_ADD_CHAR */ char chval = (char)Z_LVAL(ZEND_OP2_LITERAL(opline)); ZVAL_NEW_STR(&ZEND_OP2_LITERAL(opline), str); ptr[0] = chval; opline->opcode = ZEND_ADD_STRING; ptr++; } else { /* ZEND_ADD_STRING */ memcpy(ptr, Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline))); ptr += Z_STRLEN(ZEND_OP2_LITERAL(opline)); zend_string_release(Z_STR(ZEND_OP2_LITERAL(opline))); ZVAL_NEW_STR(&ZEND_OP2_LITERAL(opline), str); } next_op = opline + 1; while (next_op < last_op) { if (next_op->opcode == ZEND_ADD_STRING) { memcpy(ptr, Z_STRVAL(ZEND_OP2_LITERAL(next_op)), Z_STRLEN(ZEND_OP2_LITERAL(next_op))); ptr += Z_STRLEN(ZEND_OP2_LITERAL(next_op)); literal_dtor(&ZEND_OP2_LITERAL(next_op)); } else { /* ZEND_ADD_CHAR */ *ptr = (char)Z_LVAL(ZEND_OP2_LITERAL(next_op)); ptr++; } MAKE_NOP(next_op); next_op++; } if (!((ZEND_OPTIMIZER_PASS_5|ZEND_OPTIMIZER_PASS_10) & OPTIMIZATION_LEVEL)) { /* NOP removal is disabled => insert JMP over NOPs */ if (last_op-opline >= 3) { /* If we have more than 2 NOPS then JMP over them */ (opline + 1)->opcode = ZEND_JMP; ZEND_OP1(opline + 1).opline_num = last_op - op_array->opcodes; /* that's OK even for ZE2, since opline_num's are resolved in pass 2 later */ } } } break; #endif case ZEND_FETCH_CONSTANT: if (ZEND_OP1_TYPE(opline) == IS_UNUSED && ZEND_OP2_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING && Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__") - 1 && memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) { /* substitute __COMPILER_HALT_OFFSET__ constant */ zend_execute_data *orig_execute_data = EG(current_execute_data); zend_execute_data fake_execute_data; zval *offset; memset(&fake_execute_data, 0, sizeof(zend_execute_data)); fake_execute_data.func = (zend_function*)op_array; EG(current_execute_data) = &fake_execute_data; if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) { uint32_t tv = ZEND_RESULT(opline).var; if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, offset)) { literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); } } EG(current_execute_data) = orig_execute_data; break; } if (ZEND_OP1_TYPE(opline) == IS_UNUSED && ZEND_OP2_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { /* substitute persistent constants */ uint32_t tv = ZEND_RESULT(opline).var; zval c; if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP2_LITERAL(opline)), &c, 1)) { if (!ctx->constants || !zend_optimizer_get_collected_constant(ctx->constants, &ZEND_OP2_LITERAL(opline), &c)) { break; } } if (Z_TYPE(c) == IS_CONSTANT_AST) { break; } if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c)) { literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); } } /* class constant */ if (ZEND_OP1_TYPE(opline) != IS_UNUSED && ZEND_OP2_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { zend_class_entry *ce = NULL; if (ZEND_OP1_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) { /* for A::B */ if (op_array->scope && !strncasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), op_array->scope->name->val, Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1)) { ce = op_array->scope; } else { if ((ce = zend_hash_find_ptr(EG(class_table), Z_STR(op_array->literals[opline->op1.constant + 1]))) == NULL || (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->type != MODULE_PERSISTENT) || (ce->type == ZEND_USER_CLASS && ZEND_CE_FILENAME(ce) != op_array->filename)) { break; } } } else if (op_array->scope && ZEND_OP1_TYPE(opline) == IS_VAR && (opline - 1)->opcode == ZEND_FETCH_CLASS && (ZEND_OP1_TYPE(opline - 1) == IS_UNUSED && ((opline - 1)->extended_value & ~ZEND_FETCH_CLASS_NO_AUTOLOAD) == ZEND_FETCH_CLASS_SELF) && ZEND_RESULT((opline - 1)).var == ZEND_OP1(opline).var) { /* for self::B */ ce = op_array->scope; } if (ce) { uint32_t tv = ZEND_RESULT(opline).var; zval *c, t; if ((c = zend_hash_find(&ce->constants_table, Z_STR(ZEND_OP2_LITERAL(opline)))) != NULL) { ZVAL_DEREF(c); if (Z_TYPE_P(c) == IS_CONSTANT_AST) { break; } if (ZEND_IS_CONSTANT_TYPE(Z_TYPE_P(c))) { if (!zend_optimizer_get_persistent_constant(Z_STR_P(c), &t, 1) || ZEND_IS_CONSTANT_TYPE(Z_TYPE(t))) { break; } } else { ZVAL_COPY_VALUE(&t, c); zval_copy_ctor(&t); } if (ZEND_OP1_TYPE(opline) == IS_CONST) { literal_dtor(&ZEND_OP1_LITERAL(opline)); } else { MAKE_NOP((opline - 1)); } if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &t)) { literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); } } } } break; case ZEND_DO_ICALL: { zend_op *send1_opline = opline - 1; zend_op *send2_opline = NULL; zend_op *init_opline = NULL; while (send1_opline->opcode == ZEND_NOP) { send1_opline--; } if (send1_opline->opcode != ZEND_SEND_VAL || ZEND_OP1_TYPE(send1_opline) != IS_CONST) { /* don't colllect constants after unknown function call */ collect_constants = 0; break; } if (send1_opline->op2.num == 2) { send2_opline = send1_opline; send1_opline--; while (send1_opline->opcode == ZEND_NOP) { send1_opline--; } if (send1_opline->opcode != ZEND_SEND_VAL || ZEND_OP1_TYPE(send1_opline) != IS_CONST) { /* don't colllect constants after unknown function call */ collect_constants = 0; break; } } init_opline = send1_opline - 1; while (init_opline->opcode == ZEND_NOP) { init_opline--; } if (init_opline->opcode != ZEND_INIT_FCALL || ZEND_OP2_TYPE(init_opline) != IS_CONST || Z_TYPE(ZEND_OP2_LITERAL(init_opline)) != IS_STRING) { /* don't colllect constants after unknown function call */ collect_constants = 0; break; } /* define("name", scalar); */ if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("define")-1 && zend_binary_strcasecmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), Z_STRLEN(ZEND_OP2_LITERAL(init_opline)), "define", sizeof("define")-1) == 0) { if (Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING && send2_opline && Z_TYPE(ZEND_OP1_LITERAL(send2_opline)) <= IS_STRING) { if (collect_constants) { zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(send1_opline), &ZEND_OP1_LITERAL(send2_opline)); } if (RESULT_UNUSED(opline) && !zend_memnstr(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), "::", sizeof("::") - 1, Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)) + Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)))) { opline->opcode = ZEND_DECLARE_CONST; opline->op1_type = IS_CONST; opline->op2_type = IS_CONST; opline->result_type = IS_UNUSED; opline->op1.constant = send1_opline->op1.constant; opline->op2.constant = send2_opline->op1.constant; opline->result.num = 0; literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); MAKE_NOP(send1_opline); MAKE_NOP(send2_opline); } break; } } /* pre-evaluate constant functions: defined(x) constant(x) function_exists(x) is_callable(x) extension_loaded(x) */ if (!send2_opline && Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING) { if ((Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("function_exists")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "function_exists", sizeof("function_exists")-1)) || (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "is_callable", sizeof("is_callable")))) { zend_internal_function *func; zend_string *lc_name = zend_string_tolower( Z_STR(ZEND_OP1_LITERAL(send1_opline))); if ((func = zend_hash_find_ptr(EG(function_table), lc_name)) != NULL && func->type == ZEND_INTERNAL_FUNCTION && func->module->type == MODULE_PERSISTENT) { zval t; if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable") - 1 || func->handler != ZEND_FN(display_disabled_function)) { ZVAL_TRUE(&t); } else { ZVAL_FALSE(&t); } if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); MAKE_NOP(opline); zend_string_release(lc_name); break; } } zend_string_release(lc_name); } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("extension_loaded")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "extension_loaded", sizeof("extension_loaded")-1)) { zval t; zend_string *lc_name = zend_string_tolower( Z_STR(ZEND_OP1_LITERAL(send1_opline))); zend_module_entry *m = zend_hash_find_ptr(&module_registry, lc_name); zend_string_release(lc_name); if (!m) { if (!PG(enable_dl)) { break; } else { ZVAL_FALSE(&t); } } else { if (m->type == MODULE_PERSISTENT) { ZVAL_TRUE(&t); } else { break; } } if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); MAKE_NOP(opline); break; } } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("defined")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "defined", sizeof("defined")-1)) { zval t; if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(send1_opline)), &t, 0)) { ZVAL_TRUE(&t); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); MAKE_NOP(opline); break; } } } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("constant")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "constant", sizeof("constant")-1)) { zval t; if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(send1_opline)), &t, 1)) { if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); MAKE_NOP(opline); break; } } } else if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN) == 0 && Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("strlen") - 1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "strlen", sizeof("strlen") - 1)) { zval t; ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(send1_opline))); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); MAKE_NOP(opline); break; } /* dirname(IS_CONST/IS_STRING) -> IS_CONST/IS_STRING */ } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("dirname")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "dirname", sizeof("dirname")-1) && IS_ABSOLUTE_PATH(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)))) { zend_string *dirname = zend_string_init(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)), 0); dirname->len = zend_dirname(dirname->val, dirname->len); if (IS_ABSOLUTE_PATH(dirname->val, dirname->len)) { zval t; ZVAL_STR(&t, dirname); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); MAKE_NOP(opline); break; } } else { zend_string_release(dirname); } } } /* don't colllect constants after any other function call */ collect_constants = 0; break; } case ZEND_STRLEN: if (ZEND_OP1_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) { zval t; ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline))); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP1_LITERAL(opline)); MAKE_NOP(opline); } } break; case ZEND_DEFINED: { zval c; uint32_t tv = ZEND_RESULT(opline).var; if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline)), &c, 0)) { break; } ZVAL_TRUE(&c); if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c)) { literal_dtor(&ZEND_OP1_LITERAL(opline)); MAKE_NOP(opline); } } break; case ZEND_DECLARE_CONST: if (collect_constants && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING && Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_STRING) { zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)); } break; case ZEND_RETURN: case ZEND_RETURN_BY_REF: case ZEND_GENERATOR_RETURN: case ZEND_EXIT: case ZEND_THROW: case ZEND_CATCH: case ZEND_BRK: case ZEND_CONT: case ZEND_GOTO: case ZEND_FAST_CALL: case ZEND_FAST_RET: case ZEND_JMP: case ZEND_JMPZNZ: case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_FE_RESET_R: case ZEND_FE_RESET_RW: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: case ZEND_NEW: case ZEND_JMP_SET: case ZEND_COALESCE: case ZEND_ASSERT_CHECK: collect_constants = 0; break; case ZEND_FETCH_R: case ZEND_FETCH_W: case ZEND_FETCH_RW: case ZEND_FETCH_FUNC_ARG: case ZEND_FETCH_IS: case ZEND_FETCH_UNSET: if (opline != op_array->opcodes && (opline-1)->opcode == ZEND_BEGIN_SILENCE && (opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_LOCAL && opline->op1_type == IS_CONST && opline->op2_type == IS_UNUSED && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING && (Z_STRLEN(ZEND_OP1_LITERAL(opline)) != sizeof("this")-1 || memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), "this", sizeof("this") - 1) != 0)) { int var = opline->result.var; int level = 0; zend_op *op = opline + 1; zend_op *use = NULL; while (op < end) { if (op->opcode == ZEND_BEGIN_SILENCE) { level++; } else if (op->opcode == ZEND_END_SILENCE) { if (level == 0) { break; } else { level--; } } if (op->op1_type == IS_VAR && op->op1.var == var) { if (use) { /* used more than once */ use = NULL; break; } use = op; } else if (op->op2_type == IS_VAR && op->op2.var == var) { if (use) { /* used more than once */ use = NULL; break; } use = op; } op++; } if (use) { if (use->op1_type == IS_VAR && use->op1.var == var) { use->op1_type = IS_CV; use->op1.var = zend_optimizer_lookup_cv(op_array, Z_STR(ZEND_OP1_LITERAL(opline))); MAKE_NOP(opline); } else if (use->op2_type == IS_VAR && use->op2.var == var) { use->op2_type = IS_CV; use->op2.var = zend_optimizer_lookup_cv(op_array, Z_STR(ZEND_OP1_LITERAL(opline))); MAKE_NOP(opline); } } } break; } opline++; i++; } }