/* {{{ zend_user_serialize */ ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data) { zend_class_entry * ce = Z_OBJCE_P(object); zval retval; int result; zend_call_method_with_0_params(object, ce, &ce->serialize_func, "serialize", &retval); if (Z_TYPE(retval) == IS_UNDEF || EG(exception)) { result = FAILURE; } else { switch(Z_TYPE(retval)) { case IS_NULL: /* we could also make this '*buf_len = 0' but this allows to skip variables */ zval_ptr_dtor(&retval); return FAILURE; case IS_STRING: *buffer = (unsigned char*)estrndup(Z_STRVAL(retval), Z_STRLEN(retval)); *buf_len = Z_STRLEN(retval); result = SUCCESS; break; default: /* failure */ result = FAILURE; break; } zval_ptr_dtor(&retval); } if (result == FAILURE && !EG(exception)) { zend_throw_exception_ex(NULL, 0, "%s::serialize() must return a string or NULL", ce->name->val); } return result; }
int wkhtmltox_set_object_params(void *settings, fp set_function, zval *params, zval *input) { zval **data; HashTable *params_hash; HashPosition pointer; int params_count; char *key; int key_len; long index; int page = 0; int html = 0; params_hash = Z_ARRVAL_P(params); params_count = zend_hash_num_elements(params_hash); for(zend_hash_internal_pointer_reset_ex(params_hash, &pointer); zend_hash_get_current_data_ex(params_hash, (void **)&data, &pointer) == SUCCESS; zend_hash_move_forward_ex(params_hash, &pointer)) { zval temp = **data; zval_copy_ctor(&temp); if (zend_hash_get_current_key_ex(params_hash, &key, &key_len, &index, 0, &pointer) == HASH_KEY_IS_STRING) { switch (Z_TYPE(temp)) { case IS_BOOL: set_function(settings, key, Z_BVAL(temp) ? "true" : "false"); break; default: convert_to_string(&temp); case IS_STRING: if (strcmp(key, "page") == 0 || strcmp(key, "out") == 0) { //TODO do checking of page/out url/file according to php security settings like open_basedir, allow_url_fopen a.s.o // php main fopenwrapper ?! php_check_specific_open_basedir php_check_open_basedir //php_printf("key: %s, val: %s\n", key, Z_STRVAL(temp)); } if (strcmp(key, "page") == 0 && Z_STRLEN(temp) > 0) { page = 1; } if (strcmp(key, "html") == 0 && Z_STRLEN(temp) > 0) { ZVAL_STRING(input, Z_STRVAL(temp), 1); html = 1; } set_function(settings, key, Z_STRVAL(temp)); break; } } zval_dtor(&temp); } if (page == 1) { return 0; } else if (page == 0 && html == 1) { return 1; } else { return 2; } }
static int accel_file_in_cache(INTERNAL_FUNCTION_PARAMETERS) { zval zfilename; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, &zfilename) == FAILURE || Z_TYPE(zfilename) != IS_STRING || Z_STRLEN(zfilename) == 0) { return 0; } return filename_is_in_cache(Z_STRVAL(zfilename), Z_STRLEN(zfilename) TSRMLS_CC); }
static int ZEND_DECLARE_INHERITED_CLASS_DELAYED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_class_entry **pce, **pce_orig; if (zend_hash_find(EG(class_table), Z_STRVAL(EX(opline)->op2.u.constant), Z_STRLEN(EX(opline)->op2.u.constant) + 1, (void **)&pce) == FAILURE || (zend_hash_find(EG(class_table), Z_STRVAL(EX(opline)->op1.u.constant), Z_STRLEN(EX(opline)->op1.u.constant), (void**)&pce_orig) == SUCCESS && *pce != *pce_orig)) { do_bind_inherited_class(EX(opline), EG(class_table), EX_T(EX(opline)->extended_value).class_entry, 0 TSRMLS_CC); } EX(opline)++; return ZEND_USER_OPCODE_CONTINUE; }
/* Lookup a key from the $PHORUM["args"] array. */ zval * get_PHORUM_args(char *key) { HashTable *args = NULL; zval zkey; zval **P; /* Lookup the $PHORUM["args"] variable. */ zval *A = get_PHORUM("args"); if (A == NULL) { zend_error(E_ERROR, "PHORUM(): Cannot find symbol $PHORUM[args]"); } args = Z_ARRVAL_P(A); /* Lookup the key in the args table. */ ZVAL_STRING(&zkey, key, 1); if (zend_hash_find(args, Z_STRVAL(zkey), Z_STRLEN(zkey)+1, (void**)&P) == FAILURE) { convert_to_long(&zkey); if (zend_hash_index_find(args, Z_LVAL(zkey), (void**)&P) == FAILURE) { return NULL; } } return *P; }
/* call userland key extraction function */ char * ra_call_extractor(RedisArray *ra, const char *key, int key_len, int *out_len) { char *out; zval z_ret; zval z_argv0; /* check that we can call the extractor function */ if (!zend_is_callable_ex(&ra->z_fun, NULL, 0, NULL, NULL, NULL)) { php_error_docref(NULL, E_ERROR, "Could not call extractor function"); return NULL; } //convert_to_string(ra->z_fun); /* call extraction function */ ZVAL_STRINGL(&z_argv0, key, key_len); call_user_function(EG(function_table), NULL, &ra->z_fun, &z_ret, 1, &z_argv0); efree(&z_argv0); if (Z_TYPE(z_ret) != IS_STRING) { zval_dtor(&z_ret); return NULL; } *out_len = Z_STRLEN(z_ret); out = emalloc(*out_len + 1); out[*out_len] = 0; memcpy(out, Z_STRVAL(z_ret), *out_len); zval_dtor(&z_ret); return out; }
void refill() { assert(buffer_used == 0); zval retval; ZVAL_NULL(&retval); zval *args[1]; MAKE_STD_ZVAL(args[0]); ZVAL_LONG(args[0], buffer_size); TSRMLS_FETCH(); zval funcname; ZVAL_STRING(&funcname, "read", 0); call_user_function(EG(function_table), &t, &funcname, &retval, 1, args TSRMLS_CC); zval_ptr_dtor(args); if (EG(exception)) { zval_dtor(&retval); zval* ex = EG(exception); EG(exception) = NULL; throw PHPExceptionWrapper(ex); } buffer_used = Z_STRLEN(retval); memcpy(buffer, Z_STRVAL(retval), buffer_used); zval_dtor(&retval); buffer_ptr = buffer; }
int GetString(structlpsolvecaller *lpsolvecaller, pMatrix ppm, int element, char *buf, int size, int ShowError) { int size1; zval arg; ZVAL_UNDEF(&arg); if (ppm != NULL) { ErrMsgTxt(lpsolvecaller, "invalid vector."); } arg = GetpMatrix(lpsolvecaller, element); if ((!Z_ISUNDEF(arg)) && (Z_TYPE(arg) != IS_STRING)) { ZVAL_UNDEF(&arg); } if (Z_ISUNDEF(arg)) { if (ShowError) ErrMsgTxt(lpsolvecaller, "Expecting a character element"); return(FALSE); } size1 = Z_STRLEN(arg); if (size1 < size) size = size1; memcpy(buf, Z_STRVAL(arg), size); buf[size] = 0; return(TRUE); }
void refill() { assert(buffer_used == 0); zval retval; zval args[1]; zval funcname; ZVAL_NULL(&retval); ZVAL_LONG(&args[0], buffer_size); ZVAL_STRING(&funcname, "read"); call_user_function(EG(function_table), &(this->t), &funcname, &retval, 1, args); zval_dtor(&args[0]); zval_dtor(&funcname); if (EG(exception)) { zval_dtor(&retval); zend_object *ex = EG(exception); EG(exception) = nullptr; throw PHPExceptionWrapper(ex); } buffer_used = Z_STRLEN(retval); memcpy(buffer, Z_STRVAL(retval), buffer_used); zval_dtor(&retval); buffer_ptr = buffer; }
/** * Checks whether put has certain index * * @param string $name * @return boolean */ PHP_METHOD(Phalcon_Http_Request, hasPut) { zval *name, is_put = {}, put = {}, raw = {}, new_put = {}; char *tmp; phalcon_fetch_params(0, 1, 0, &name); PHALCON_CALL_METHODW(&is_put, getThis(), "isput"); if (!zend_is_true(&is_put)) { phalcon_read_global_str(&new_put, SL("_PUT")); } else { phalcon_read_property(&put, getThis(), SL("_put"), PH_NOISY); if (Z_TYPE(put) != IS_ARRAY) { PHALCON_CALL_METHODW(&raw, getThis(), "getrawbody"); array_init(&new_put); PHALCON_ENSURE_IS_STRING(&raw); tmp = estrndup(Z_STRVAL(raw), Z_STRLEN(raw)); sapi_module.treat_data(PARSE_STRING, tmp, &new_put); phalcon_update_property_zval(getThis(), SL("_put"), &new_put); } else { PHALCON_CPY_WRT(&new_put, &put); } } RETVAL_BOOL(phalcon_array_isset(&new_put, name)); }
/** * Write hex string to the current position in the file pointer * * @return Phalcon\Binary\Writer */ PHP_METHOD(Phalcon_Binary_Writer, writeHexString){ zval *str, *length = NULL, *low_nibble = NULL, len = {}, format = {}, result = {}; phalcon_fetch_params(0, 1, 2, &str, &length, &low_nibble); if (length && Z_TYPE_P(length) != IS_NULL) { if (low_nibble && zend_is_true(low_nibble)) { PHALCON_CONCAT_SV(&format, "h", length); } else { PHALCON_CONCAT_SV(&format, "H", length); } } else { if (low_nibble && zend_is_true(low_nibble)) { ZVAL_STRING(&format, "h*"); } else { ZVAL_STRING(&format, "H*"); } } PHALCON_CALL_FUNCTIONW(&result, "pack", &format, str); ZVAL_LONG(&len, Z_STRLEN(result)); PHALCON_CALL_METHODW(NULL, getThis(), "write", &result, &len); RETURN_THISW(); }
/** * Decrypt a text that is coded as a base64 string * * @param string $text * @param string $key * @return string */ PHP_METHOD(Phalcon_Crypt, decryptBase64){ zval *text, *key = NULL, *safe = NULL, decrypt_text = {}, decrypt_value = {}; phalcon_fetch_params(0, 1, 2, &text, &key, &safe); PHALCON_ENSURE_IS_STRING(text); if (!key) { key = &PHALCON_GLOBAL(z_null); } if (!safe) { safe = &PHALCON_GLOBAL(z_false); } if (zend_is_true(safe)) { ZVAL_NEW_STR(&decrypt_text, zend_string_dup(Z_STR_P(text), 0)); php_strtr(Z_STRVAL(decrypt_text), Z_STRLEN(decrypt_text), "-_", "+/", 2); } else { PHALCON_CPY_WRT_CTOR(&decrypt_text, text); } phalcon_base64_decode(&decrypt_value, &decrypt_text); PHALCON_RETURN_CALL_METHODW(getThis(), "decrypt", &decrypt_value, key); }
inline int sw_zend_hash_get_current_key(HashTable *ht, char **key, uint32_t *keylen, ulong *num) { zval str_key; int type = zend_hash_get_current_key(ht, &Z_STR(str_key), (zend_ulong* ) num); *key = Z_STRVAL(str_key); *keylen = Z_STRLEN(str_key); return type; }
/* CONVERSIONS for integers */ static zend_long from_zval_integer_common(const zval *arr_value, ser_context *ctx) { zend_long ret = 0; zval lzval; ZVAL_NULL(&lzval); if (Z_TYPE_P(arr_value) != IS_LONG) { ZVAL_COPY(&lzval, (zval *)arr_value); arr_value = &lzval; } switch (Z_TYPE_P(arr_value)) { case IS_LONG: long_case: ret = Z_LVAL_P(arr_value); break; /* if not long we're operating on lzval */ case IS_DOUBLE: double_case: convert_to_long(&lzval); goto long_case; case IS_OBJECT: case IS_STRING: { zend_long lval; double dval; convert_to_string(&lzval); switch (is_numeric_string(Z_STRVAL(lzval), Z_STRLEN(lzval), &lval, &dval, 0)) { case IS_DOUBLE: zval_dtor(&lzval); ZVAL_DOUBLE(&lzval, dval); goto double_case; case IS_LONG: zval_dtor(&lzval); ZVAL_LONG(&lzval, lval); goto long_case; } /* if we get here, we don't have a numeric string */ do_from_zval_err(ctx, "expected an integer, but got a non numeric " "string (possibly from a converted object): '%s'", Z_STRVAL_P(arr_value)); break; } default: do_from_zval_err(ctx, "%s", "expected an integer, either of a PHP " "integer type or of a convertible type"); break; } zval_dtor(&lzval); return ret; }
/* {{{ proto Closure Closure::bind(Closure $old, object $to [, mixed $scope = "static" ] ) Create a closure from another one and bind to another object and scope */ ZEND_METHOD(Closure, bind) /* {{{ */ { zval *newthis, *zclosure, *scope_arg = NULL; zend_closure *closure; zend_class_entry *ce, **ce_p; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) { RETURN_NULL(); } closure = (zend_closure *)zend_object_store_get_object(zclosure TSRMLS_CC); if ((newthis != NULL) && (closure->func.common.fn_flags & ZEND_ACC_STATIC)) { zend_error(E_WARNING, "Cannot bind an instance to a static closure"); } if (scope_arg != NULL) { /* scope argument was given */ if (IS_ZEND_STD_OBJECT(*scope_arg)) { ce = Z_OBJCE_P(scope_arg); } else if (Z_TYPE_P(scope_arg) == IS_NULL) { ce = NULL; } else { char *class_name; int class_name_len; zval tmp_zval; INIT_ZVAL(tmp_zval); if (Z_TYPE_P(scope_arg) == IS_STRING) { class_name = Z_STRVAL_P(scope_arg); class_name_len = Z_STRLEN_P(scope_arg); } else { tmp_zval = *scope_arg; zval_copy_ctor(&tmp_zval); convert_to_string(&tmp_zval); class_name = Z_STRVAL(tmp_zval); class_name_len = Z_STRLEN(tmp_zval); } if ((class_name_len == sizeof("static") - 1) && (memcmp("static", class_name, sizeof("static") - 1) == 0)) { ce = closure->func.common.scope; } else if (zend_lookup_class_ex(class_name, class_name_len, NULL, 1, &ce_p TSRMLS_CC) == FAILURE) { zend_error(E_WARNING, "Class '%s' not found", class_name); zval_dtor(&tmp_zval); RETURN_NULL(); } else { ce = *ce_p; } zval_dtor(&tmp_zval); } } else { /* scope argument not given; do not change the scope by default */ ce = closure->func.common.scope; } zend_create_closure(return_value, &closure->func, ce, newthis TSRMLS_CC); }
/* {{{ php_dba_myke_key */ static size_t php_dba_make_key(zval *key, char **key_str, char **key_free) { if (Z_TYPE_P(key) == IS_ARRAY) { zval *group, *name; HashPosition pos; size_t len; if (zend_hash_num_elements(Z_ARRVAL_P(key)) != 2) { php_error_docref(NULL, E_RECOVERABLE_ERROR, "Key does not have exactly two elements: (key, name)"); return 0; } zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(key), &pos); group = zend_hash_get_current_data_ex(Z_ARRVAL_P(key), &pos); zend_hash_move_forward_ex(Z_ARRVAL_P(key), &pos); name = zend_hash_get_current_data_ex(Z_ARRVAL_P(key), &pos); convert_to_string_ex(group); convert_to_string_ex(name); if (Z_STRLEN_P(group) == 0) { *key_str = Z_STRVAL_P(name); *key_free = NULL; return Z_STRLEN_P(name); } len = spprintf(key_str, 0, "[%s]%s", Z_STRVAL_P(group), Z_STRVAL_P(name)); *key_free = *key_str; return len; } else { zval tmp; int len; ZVAL_COPY(&tmp, key); convert_to_string(&tmp); len = Z_STRLEN(tmp); if (len) { *key_free = *key_str = estrndup(Z_STRVAL(tmp), Z_STRLEN(tmp)); } zval_ptr_dtor(&tmp); return len; } }
/** * Gets a variable from put request * *<code> * $userEmail = $request->getPut("user_email"); * * $userEmail = $request->getPut("user_email", "email"); *</code> * * @param string $name * @param string|array $filters * @param mixed $defaultValue * @param boolean $notAllowEmpty * @param boolean $noRecursive * @return mixed */ PHP_METHOD(Phalcon_Http_Request, getPut) { zval *name = NULL, *filters = NULL, *default_value = NULL, *not_allow_empty = NULL, *norecursive = NULL, is_put = {}, put = {}, raw = {}, new_put = {}; char *tmp; phalcon_fetch_params(0, 0, 5, &name, &filters, &default_value, ¬_allow_empty, &norecursive); if (!name) { name = &PHALCON_GLOBAL(z_null); } if (!filters) { filters = &PHALCON_GLOBAL(z_null); } if (!default_value) { default_value = &PHALCON_GLOBAL(z_null); } if (!not_allow_empty) { not_allow_empty = &PHALCON_GLOBAL(z_false); } if (!norecursive) { norecursive = &PHALCON_GLOBAL(z_false); } PHALCON_CALL_METHODW(&is_put, getThis(), "isput"); if (!zend_is_true(&is_put)) { RETURN_EMPTY_ARRAY(); } else { phalcon_read_property(&put, getThis(), SL("_put"), PH_NOISY); if (Z_TYPE(put) != IS_ARRAY) { PHALCON_CALL_METHODW(&raw, getThis(), "getrawbody"); array_init(&new_put); PHALCON_ENSURE_IS_STRING(&raw); tmp = estrndup(Z_STRVAL(raw), Z_STRLEN(raw)); sapi_module.treat_data(PARSE_STRING, tmp, &new_put); phalcon_update_property_zval(getThis(), SL("_put"), &new_put); } else { PHALCON_CPY_WRT(&new_put, &put); } } PHALCON_RETURN_CALL_SELFW("_get", &new_put, name, filters, default_value, not_allow_empty, norecursive); }
long get_constant_long(char *key) { zval zkey; zval zvalue; ZVAL_STRING(&zkey, key, 0); if (!zend_get_constant(Z_STRVAL(zkey), Z_STRLEN(zkey), &zvalue TSRMLS_CC)) { zend_error(E_ERROR, "get_constant_long(): Cannot find symbol %s, is this function called inside an initialized Phorum environment?", key); } convert_to_long(&zvalue); return Z_LVAL(zvalue); }
static void _breakiterator_parts_move_forward(zend_object_iterator *iter) { zoi_break_iter_parts *zoi_bit = (zoi_break_iter_parts*)iter; BreakIterator_object *bio = zoi_bit->bio; iter->funcs->invalidate_current(iter); int32_t cur, next; cur = bio->biter->current(); if (cur == BreakIterator::DONE) { return; } next = bio->biter->next(); if (next == BreakIterator::DONE) { return; } if (zoi_bit->key_type == PARTS_ITERATOR_KEY_LEFT) { iter->index = cur; } else if (zoi_bit->key_type == PARTS_ITERATOR_KEY_RIGHT) { iter->index = next; } /* else zoi_bit->key_type == PARTS_ITERATOR_KEY_SEQUENTIAL * No need to do anything, the engine increments ->index */ const char *s = Z_STRVAL(bio->text); size_t slen = Z_STRLEN(bio->text); zend_string *res; if (next == BreakIterator::DONE) { next = (int32_t)slen; } assert(next <= slen && next >= cur); res = zend_string_alloc(next - cur, 0); memcpy(res->val, &s[cur], res->len); res->val[res->len] = '\0'; ZVAL_STR(&zoi_bit->zoi_cur.current, res); }
/* Lookup a key from the $PHORUM["DATA"] array. */ zval * get_PHORUM_DATA(char *key) { HashTable *data = NULL; zval zkey; zval **P; /* Lookup the $PHORUM["DATA"] variable. If there is no such variable, * then return NULL. */ zval *A = get_PHORUM("DATA"); if (A == NULL) return NULL; data = Z_ARRVAL_P(A); /* Lookup the key in the DATA table. */ ZVAL_STRING(&zkey, key, 1); if (zend_hash_find(data, Z_STRVAL(zkey), Z_STRLEN(zkey)+1, (void**)&P) == FAILURE) { convert_to_long(&zkey); if (zend_hash_index_find(data, Z_LVAL(zkey), (void**)&P) == FAILURE) { return NULL; } } return *P; }
/* {{{ _php_mb_regex_ereg_search_exec */ static void _php_mb_regex_ereg_search_exec(INTERNAL_FUNCTION_PARAMETERS, int mode) { char *arg_pattern = NULL, *arg_options = NULL; size_t arg_pattern_len, arg_options_len; int err; size_t n, i, pos, len, beg, end; OnigOptionType option; OnigUChar *str; OnigSyntaxType *syntax; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ss", &arg_pattern, &arg_pattern_len, &arg_options, &arg_options_len) == FAILURE) { return; } option = MBREX(regex_default_options); if (arg_options) { option = 0; _php_mb_regex_init_options(arg_options, arg_options_len, &option, &syntax, NULL); } if (arg_pattern) { /* create regex pattern buffer */ if ((MBREX(search_re) = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, option, MBREX(current_mbctype), MBREX(regex_default_syntax))) == NULL) { RETURN_FALSE; } } pos = MBREX(search_pos); str = NULL; len = 0; if (!Z_ISUNDEF(MBREX(search_str)) && Z_TYPE(MBREX(search_str)) == IS_STRING){ str = (OnigUChar *)Z_STRVAL(MBREX(search_str)); len = Z_STRLEN(MBREX(search_str)); } if (MBREX(search_re) == NULL) { php_error_docref(NULL, E_WARNING, "No regex given"); RETURN_FALSE; } if (str == NULL) { php_error_docref(NULL, E_WARNING, "No string given"); RETURN_FALSE; } if (MBREX(search_regs)) { onig_region_free(MBREX(search_regs), 1); } MBREX(search_regs) = onig_region_new(); err = onig_search(MBREX(search_re), str, str + len, str + pos, str + len, MBREX(search_regs), 0); if (err == ONIG_MISMATCH) { MBREX(search_pos) = len; RETVAL_FALSE; } else if (err <= -2) { OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(err_str, err); php_error_docref(NULL, E_WARNING, "mbregex search failure in mbregex_search(): %s", err_str); RETVAL_FALSE; } else { switch (mode) { case 1: array_init(return_value); beg = MBREX(search_regs)->beg[0]; end = MBREX(search_regs)->end[0]; add_next_index_long(return_value, beg); add_next_index_long(return_value, end - beg); break; case 2: array_init(return_value); n = MBREX(search_regs)->num_regs; for (i = 0; i < n; i++) { beg = MBREX(search_regs)->beg[i]; end = MBREX(search_regs)->end[i]; if (beg >= 0 && beg <= end && end <= len) { add_index_stringl(return_value, i, (char *)&str[beg], end - beg); } else { add_index_bool(return_value, i, 0); } } break; default: RETVAL_TRUE; break; } end = MBREX(search_regs)->end[0]; if (pos <= end) { MBREX(search_pos) = end; } else { MBREX(search_pos) = pos + 1; } } if (err < 0) { onig_region_free(MBREX(search_regs), 1); MBREX(search_regs) = (OnigRegion *)NULL; } }
/* {{{ 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; }
zval * php_can_strtr_array(char *str, int slen, HashTable *hash) { zval **entry; char *string_key; uint string_key_len; zval **trans; zval ctmp; ulong num_key; int minlen = 128*1024; int maxlen = 0, pos, len, found; char *key; HashPosition hpos; smart_str result = {0}; HashTable tmp_hash; zend_hash_init(&tmp_hash, zend_hash_num_elements(hash), NULL, NULL, 0); zend_hash_internal_pointer_reset_ex(hash, &hpos); while (zend_hash_get_current_data_ex(hash, (void **)&entry, &hpos) == SUCCESS) { switch (zend_hash_get_current_key_ex(hash, &string_key, &string_key_len, &num_key, 0, &hpos)) { case HASH_KEY_IS_STRING: len = string_key_len-1; if (len < 1) { zend_hash_destroy(&tmp_hash); return NULL; } zend_hash_add(&tmp_hash, string_key, string_key_len, entry, sizeof(zval*), NULL); if (len > maxlen) { maxlen = len; } if (len < minlen) { minlen = len; } break; case HASH_KEY_IS_LONG: Z_TYPE(ctmp) = IS_LONG; Z_LVAL(ctmp) = num_key; convert_to_string(&ctmp); len = Z_STRLEN(ctmp); zend_hash_add(&tmp_hash, Z_STRVAL(ctmp), len+1, entry, sizeof(zval*), NULL); zval_dtor(&ctmp); if (len > maxlen) { maxlen = len; } if (len < minlen) { minlen = len; } break; } zend_hash_move_forward_ex(hash, &hpos); } key = emalloc(maxlen+1); pos = 0; while (pos < slen) { if ((pos + maxlen) > slen) { maxlen = slen - pos; } found = 0; memcpy(key, str+pos, maxlen); for (len = maxlen; len >= minlen; len--) { key[len] = 0; if (zend_hash_find(&tmp_hash, key, len+1, (void**)&trans) == SUCCESS) { char *tval; int tlen; zval tmp; if (Z_TYPE_PP(trans) != IS_STRING) { tmp = **trans; zval_copy_ctor(&tmp); convert_to_string(&tmp); tval = Z_STRVAL(tmp); tlen = Z_STRLEN(tmp); } else { tval = Z_STRVAL_PP(trans); tlen = Z_STRLEN_PP(trans); } smart_str_appendl(&result, tval, tlen); pos += len; found = 1; if (Z_TYPE_PP(trans) != IS_STRING) { zval_dtor(&tmp); } break; } } if (! found) { smart_str_appendc(&result, str[pos++]); } } efree(key); zend_hash_destroy(&tmp_hash); smart_str_0(&result); zval *retval; MAKE_STD_ZVAL(retval); ZVAL_STRINGL(retval, result.c, result.len, 0); return retval; }
/* {{{ _php_array_to_envp */ static php_process_env_t _php_array_to_envp(zval *environment, int is_persistent TSRMLS_DC) { zval **element; php_process_env_t env; char *string_key, *data; #ifndef PHP_WIN32 char **ep; #endif char *p; uint string_length, cnt, l, sizeenv=0, el_len; ulong num_key; HashTable *target_hash; HashPosition pos; memset(&env, 0, sizeof(env)); if (!environment) { return env; } cnt = zend_hash_num_elements(Z_ARRVAL_P(environment)); if (cnt < 1) { #ifndef PHP_WIN32 env.envarray = (char **) pecalloc(1, sizeof(char *), is_persistent); #endif env.envp = (char *) pecalloc(4, 1, is_persistent); return env; } target_hash = HASH_OF(environment); if (!target_hash) { return env; } /* first, we have to get the size of all the elements in the hash */ for (zend_hash_internal_pointer_reset_ex(target_hash, &pos); zend_hash_get_current_data_ex(target_hash, (void **) &element, &pos) == SUCCESS; zend_hash_move_forward_ex(target_hash, &pos)) { if (Z_TYPE_PP(element) != IS_STRING) { zval tmp; MAKE_COPY_ZVAL(element, &tmp); convert_to_string(&tmp); el_len = Z_STRLEN(tmp); zval_dtor(&tmp); } else { el_len = Z_STRLEN_PP(element); } if (el_len == 0) { continue; } sizeenv += el_len+1; switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_length, &num_key, 0, &pos)) { case HASH_KEY_IS_STRING: if (string_length == 0) { continue; } sizeenv += string_length; break; } } #ifndef PHP_WIN32 ep = env.envarray = (char **) pecalloc(cnt + 1, sizeof(char *), is_persistent); #endif p = env.envp = (char *) pecalloc(sizeenv + 4, 1, is_persistent); for (zend_hash_internal_pointer_reset_ex(target_hash, &pos); zend_hash_get_current_data_ex(target_hash, (void **) &element, &pos) == SUCCESS; zend_hash_move_forward_ex(target_hash, &pos)) { zval tmp; if (Z_TYPE_PP(element) != IS_STRING) { MAKE_COPY_ZVAL(element, &tmp); convert_to_string(&tmp); } else { tmp = **element; } el_len = Z_STRLEN(tmp); if (el_len == 0) { goto next_element; } data = Z_STRVAL(tmp); switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_length, &num_key, 0, &pos)) { case HASH_KEY_IS_STRING: if (string_length == 0) { goto next_element; } l = string_length + el_len + 1; memcpy(p, string_key, string_length); strncat(p, "=", 1); strncat(p, data, el_len); #ifndef PHP_WIN32 *ep = p; ++ep; #endif p += l; break; case HASH_KEY_IS_LONG: memcpy(p,data,el_len); #ifndef PHP_WIN32 *ep = p; ++ep; #endif p += el_len + 1; break; case HASH_KEY_NON_EXISTENT: break; } next_element: if (Z_TYPE_PP(element) != IS_STRING) { zval_dtor(&tmp); } } assert((uint)(p - env.envp) <= sizeenv); zend_hash_internal_pointer_reset_ex(target_hash, &pos); return env; }
void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx) { zend_op *opline, *end; int i, j, n, *map, cache_size; zval zv, *pos; literal_info *info; int l_null = -1; int l_false = -1; int l_true = -1; int l_empty_arr = -1; HashTable hash; zend_string *key = NULL; void *checkpoint = zend_arena_checkpoint(ctx->arena); int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot; if (op_array->last_literal) { info = (literal_info*)zend_arena_calloc(&ctx->arena, op_array->last_literal, sizeof(literal_info)); /* Mark literals of specific types */ opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { switch (opline->opcode) { case ZEND_INIT_FCALL: LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1); break; case ZEND_INIT_FCALL_BY_NAME: LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 2); break; case ZEND_INIT_NS_FCALL_BY_NAME: LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 3); break; case ZEND_INIT_METHOD_CALL: if (opline->op1_type == IS_CONST) { LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1); } if (opline->op2_type == IS_CONST) { LITERAL_INFO(opline->op2.constant, LITERAL_METHOD, 2); } break; case ZEND_INIT_STATIC_METHOD_CALL: if (opline->op1_type == IS_CONST) { LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 2); } if (opline->op2_type == IS_CONST) { LITERAL_INFO(opline->op2.constant, LITERAL_STATIC_METHOD, 2); } break; case ZEND_CATCH: LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 2); break; case ZEND_DEFINED: LITERAL_INFO(opline->op1.constant, LITERAL_CONST, 2); break; case ZEND_FETCH_CONSTANT: if ((opline->op1.num & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) { LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 5); } else { LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 3); } break; case ZEND_FETCH_CLASS_CONSTANT: if (opline->op1_type == IS_CONST) { LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 2); } LITERAL_INFO(opline->op2.constant, LITERAL_CLASS_CONST, 1); break; case ZEND_FETCH_STATIC_PROP_R: case ZEND_FETCH_STATIC_PROP_W: case ZEND_FETCH_STATIC_PROP_RW: case ZEND_FETCH_STATIC_PROP_IS: case ZEND_FETCH_STATIC_PROP_UNSET: case ZEND_FETCH_STATIC_PROP_FUNC_ARG: case ZEND_UNSET_STATIC_PROP: case ZEND_ISSET_ISEMPTY_STATIC_PROP: if (opline->op2_type == IS_CONST) { LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 2); } if (opline->op1_type == IS_CONST) { LITERAL_INFO(opline->op1.constant, LITERAL_STATIC_PROPERTY, 1); } break; case ZEND_FETCH_CLASS: case ZEND_INSTANCEOF: if (opline->op2_type == IS_CONST) { LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 2); } break; case ZEND_NEW: if (opline->op1_type == IS_CONST) { LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 2); } break; case ZEND_ASSIGN_OBJ: case ZEND_FETCH_OBJ_R: case ZEND_FETCH_OBJ_W: case ZEND_FETCH_OBJ_RW: case ZEND_FETCH_OBJ_IS: case ZEND_FETCH_OBJ_UNSET: case ZEND_FETCH_OBJ_FUNC_ARG: case ZEND_UNSET_OBJ: case ZEND_PRE_INC_OBJ: case ZEND_PRE_DEC_OBJ: case ZEND_POST_INC_OBJ: case ZEND_POST_DEC_OBJ: case ZEND_ISSET_ISEMPTY_PROP_OBJ: if (opline->op2_type == IS_CONST) { LITERAL_INFO(opline->op2.constant, LITERAL_PROPERTY, 1); } break; case ZEND_ASSIGN_ADD: case ZEND_ASSIGN_SUB: case ZEND_ASSIGN_MUL: case ZEND_ASSIGN_DIV: case ZEND_ASSIGN_POW: case ZEND_ASSIGN_MOD: case ZEND_ASSIGN_SL: case ZEND_ASSIGN_SR: case ZEND_ASSIGN_CONCAT: case ZEND_ASSIGN_BW_OR: case ZEND_ASSIGN_BW_AND: case ZEND_ASSIGN_BW_XOR: if (opline->op2_type == IS_CONST) { if (opline->extended_value == ZEND_ASSIGN_OBJ) { LITERAL_INFO(opline->op2.constant, LITERAL_PROPERTY, 1); } else if (opline->extended_value == ZEND_ASSIGN_DIM) { if (Z_EXTRA(op_array->literals[opline->op2.constant]) == ZEND_EXTRA_VALUE) { LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 2); } else { LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1); } } else { LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1); } } break; case ZEND_BIND_GLOBAL: LITERAL_INFO(opline->op2.constant, LITERAL_GLOBAL, 1); break; case ZEND_RECV_INIT: LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1); break; case ZEND_DECLARE_FUNCTION: case ZEND_DECLARE_CLASS: LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 2); break; case ZEND_DECLARE_INHERITED_CLASS: case ZEND_DECLARE_INHERITED_CLASS_DELAYED: LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 2); LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 2); break; case ZEND_DECLARE_ANON_INHERITED_CLASS: LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1); LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 2); break; case ZEND_ISSET_ISEMPTY_DIM_OBJ: case ZEND_ASSIGN_DIM: case ZEND_UNSET_DIM: case ZEND_FETCH_DIM_R: case ZEND_FETCH_DIM_W: case ZEND_FETCH_DIM_RW: case ZEND_FETCH_DIM_IS: case ZEND_FETCH_DIM_FUNC_ARG: case ZEND_FETCH_DIM_UNSET: case ZEND_FETCH_LIST_R: case ZEND_FETCH_LIST_W: if (opline->op1_type == IS_CONST) { LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1); } if (opline->op2_type == IS_CONST) { if (Z_EXTRA(op_array->literals[opline->op2.constant]) == ZEND_EXTRA_VALUE) { LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 2); } else { LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1); } } break; default: if (opline->op1_type == IS_CONST) { LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1); } if (opline->op2_type == IS_CONST) { LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1); } break; } opline++; } #if DEBUG_COMPACT_LITERALS { int i, use_copy; fprintf(stderr, "File %s func %s\n", op_array->filename->val, op_array->function_name ? op_array->function_name->val : "main"); fprintf(stderr, "Literlas table size %d\n", op_array->last_literal); for (i = 0; i < op_array->last_literal; i++) { zval zv; ZVAL_COPY_VALUE(&zv, op_array->literals + i); use_copy = zend_make_printable_zval(op_array->literals + i, &zv); fprintf(stderr, "Literal %d, val (%d):%s\n", i, Z_STRLEN(zv), Z_STRVAL(zv)); if (use_copy) { zval_ptr_dtor_nogc(&zv); } } fflush(stderr); } #endif /* Merge equal constants */ j = 0; zend_hash_init(&hash, op_array->last_literal, NULL, NULL, 0); map = (int*)zend_arena_alloc(&ctx->arena, op_array->last_literal * sizeof(int)); memset(map, 0, op_array->last_literal * sizeof(int)); for (i = 0; i < op_array->last_literal; i++) { if (!info[i].flags) { /* unset literal */ zval_ptr_dtor_nogc(&op_array->literals[i]); continue; } switch (Z_TYPE(op_array->literals[i])) { case IS_NULL: if (l_null < 0) { l_null = j; if (i != j) { op_array->literals[j] = op_array->literals[i]; info[j] = info[i]; } j++; } map[i] = l_null; break; case IS_FALSE: if (l_false < 0) { l_false = j; if (i != j) { op_array->literals[j] = op_array->literals[i]; info[j] = info[i]; } j++; } map[i] = l_false; break; case IS_TRUE: if (l_true < 0) { l_true = j; if (i != j) { op_array->literals[j] = op_array->literals[i]; info[j] = info[i]; } j++; } map[i] = l_true; break; case IS_LONG: if (LITERAL_NUM_RELATED(info[i].flags) == 1) { if ((pos = zend_hash_index_find(&hash, Z_LVAL(op_array->literals[i]))) != NULL) { map[i] = Z_LVAL_P(pos); } else { map[i] = j; ZVAL_LONG(&zv, j); zend_hash_index_add_new(&hash, Z_LVAL(op_array->literals[i]), &zv); if (i != j) { op_array->literals[j] = op_array->literals[i]; info[j] = info[i]; } j++; } } else { ZEND_ASSERT(LITERAL_NUM_RELATED(info[i].flags) == 2); key = zend_string_init(Z_STRVAL(op_array->literals[i+1]), Z_STRLEN(op_array->literals[i+1]), 0); ZSTR_H(key) = ZSTR_HASH(Z_STR(op_array->literals[i+1])) + 100 + LITERAL_NUM_RELATED(info[i].flags) - 1; if ((pos = zend_hash_find(&hash, key)) != NULL && LITERAL_NUM_RELATED(info[Z_LVAL_P(pos)].flags) == 2) { map[i] = Z_LVAL_P(pos); zval_ptr_dtor_nogc(&op_array->literals[i+1]); } else { map[i] = j; ZVAL_LONG(&zv, j); zend_hash_add_new(&hash, key, &zv); if (i != j) { op_array->literals[j] = op_array->literals[i]; info[j] = info[i]; op_array->literals[j+1] = op_array->literals[i+1]; info[j+1] = info[i+1]; } j += 2; } zend_string_release_ex(key, 0); i++; } break; case IS_DOUBLE: if ((pos = zend_hash_str_find(&hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double))) != NULL) { map[i] = Z_LVAL_P(pos); } else { map[i] = j; ZVAL_LONG(&zv, j); zend_hash_str_add(&hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double), &zv); if (i != j) { op_array->literals[j] = op_array->literals[i]; info[j] = info[i]; } j++; } break; case IS_STRING: if (LITERAL_NUM_RELATED(info[i].flags) == 1) { key = zend_string_copy(Z_STR(op_array->literals[i])); } else { key = zend_string_init(Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]), 0); ZSTR_H(key) = ZSTR_HASH(Z_STR(op_array->literals[i])) + LITERAL_NUM_RELATED(info[i].flags) - 1; } pos = zend_hash_find(&hash, key); if (pos != NULL && Z_TYPE(op_array->literals[Z_LVAL_P(pos)]) == IS_STRING && LITERAL_NUM_RELATED(info[i].flags) == LITERAL_NUM_RELATED(info[Z_LVAL_P(pos)].flags) && (LITERAL_NUM_RELATED(info[i].flags) != 2 || ((info[i].flags & LITERAL_KIND_MASK) != LITERAL_VALUE && (info[Z_LVAL_P(pos)].flags & LITERAL_KIND_MASK) != LITERAL_VALUE))) { zend_string_release_ex(key, 0); map[i] = Z_LVAL_P(pos); zval_ptr_dtor_nogc(&op_array->literals[i]); n = LITERAL_NUM_RELATED(info[i].flags); while (n > 1) { i++; zval_ptr_dtor_nogc(&op_array->literals[i]); n--; } } else { map[i] = j; ZVAL_LONG(&zv, j); zend_hash_add_new(&hash, key, &zv); zend_string_release_ex(key, 0); if (i != j) { op_array->literals[j] = op_array->literals[i]; info[j] = info[i]; } j++; n = LITERAL_NUM_RELATED(info[i].flags); while (n > 1) { i++; if (i != j) op_array->literals[j] = op_array->literals[i]; j++; n--; } } break; case IS_ARRAY: if (zend_hash_num_elements(Z_ARRVAL(op_array->literals[i])) == 0) { if (l_empty_arr < 0) { l_empty_arr = j; if (i != j) { op_array->literals[j] = op_array->literals[i]; info[j] = info[i]; } j++; } else { zval_ptr_dtor_nogc(&op_array->literals[i]); } map[i] = l_empty_arr; break; } /* break missing intentionally */ default: /* don't merge other types */ map[i] = j; if (i != j) { op_array->literals[j] = op_array->literals[i]; info[j] = info[i]; } j++; break; } } zend_hash_clean(&hash); op_array->last_literal = j; const_slot = zend_arena_alloc(&ctx->arena, j * 6 * sizeof(int)); memset(const_slot, -1, j * 6 * sizeof(int)); class_slot = const_slot + j; func_slot = class_slot + j; bind_var_slot = func_slot + j; property_slot = bind_var_slot + j; method_slot = property_slot + j; /* Update opcodes to use new literals table */ cache_size = 0; opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { if (opline->op1_type == IS_CONST) { opline->op1.constant = map[opline->op1.constant]; } if (opline->op2_type == IS_CONST) { opline->op2.constant = map[opline->op2.constant]; } switch (opline->opcode) { case ZEND_RECV_INIT: if (class_name_type_hint(op_array, opline->op1.num)) { opline->extended_value = cache_size; cache_size += sizeof(void *); } break; case ZEND_RECV: case ZEND_RECV_VARIADIC: if (class_name_type_hint(op_array, opline->op1.num)) { opline->op2.num = cache_size; cache_size += sizeof(void *); } break; case ZEND_VERIFY_RETURN_TYPE: if (class_name_type_hint(op_array, 0)) { opline->op2.num = cache_size; cache_size += sizeof(void *); } break; case ZEND_ASSIGN_ADD: case ZEND_ASSIGN_SUB: case ZEND_ASSIGN_MUL: case ZEND_ASSIGN_DIV: case ZEND_ASSIGN_POW: case ZEND_ASSIGN_MOD: case ZEND_ASSIGN_SL: case ZEND_ASSIGN_SR: case ZEND_ASSIGN_CONCAT: case ZEND_ASSIGN_BW_OR: case ZEND_ASSIGN_BW_AND: case ZEND_ASSIGN_BW_XOR: if (opline->extended_value != ZEND_ASSIGN_OBJ) { break; } if (opline->op2_type == IS_CONST) { // op2 property if (opline->op1_type == IS_UNUSED && property_slot[opline->op2.constant] >= 0) { (opline+1)->extended_value = property_slot[opline->op2.constant]; } else { (opline+1)->extended_value = cache_size; cache_size += 2 * sizeof(void *); if (opline->op1_type == IS_UNUSED) { property_slot[opline->op2.constant] = (opline+1)->extended_value; } } } break; case ZEND_ASSIGN_OBJ: case ZEND_FETCH_OBJ_R: case ZEND_FETCH_OBJ_W: case ZEND_FETCH_OBJ_RW: case ZEND_FETCH_OBJ_IS: case ZEND_FETCH_OBJ_UNSET: case ZEND_FETCH_OBJ_FUNC_ARG: case ZEND_UNSET_OBJ: case ZEND_PRE_INC_OBJ: case ZEND_PRE_DEC_OBJ: case ZEND_POST_INC_OBJ: case ZEND_POST_DEC_OBJ: if (opline->op2_type == IS_CONST) { // op2 property if (opline->op1_type == IS_UNUSED && property_slot[opline->op2.constant] >= 0) { opline->extended_value = property_slot[opline->op2.constant]; } else { opline->extended_value = cache_size; cache_size += 2 * sizeof(void *); if (opline->op1_type == IS_UNUSED) { property_slot[opline->op2.constant] = opline->extended_value; } } } break; case ZEND_ISSET_ISEMPTY_PROP_OBJ: if (opline->op2_type == IS_CONST) { // op2 property if (opline->op1_type == IS_UNUSED && property_slot[opline->op2.constant] >= 0) { opline->extended_value = property_slot[opline->op2.constant] | (opline->extended_value & ZEND_ISEMPTY); } else { opline->extended_value = cache_size | (opline->extended_value & ZEND_ISEMPTY); cache_size += 2 * sizeof(void *); if (opline->op1_type == IS_UNUSED) { property_slot[opline->op2.constant] = opline->extended_value & ~ZEND_ISEMPTY; } } } break; case ZEND_INIT_FCALL: case ZEND_INIT_FCALL_BY_NAME: case ZEND_INIT_NS_FCALL_BY_NAME: // op2 func if (func_slot[opline->op2.constant] >= 0) { opline->result.num = func_slot[opline->op2.constant]; } else { opline->result.num = cache_size; cache_size += sizeof(void *); func_slot[opline->op2.constant] = opline->result.num; } break; case ZEND_INIT_METHOD_CALL: if (opline->op2_type == IS_CONST) { // op2 method if (opline->op1_type == IS_UNUSED && method_slot[opline->op2.constant] >= 0) { opline->result.num = method_slot[opline->op2.constant]; } else { opline->result.num = cache_size; cache_size += 2 * sizeof(void *); if (opline->op1_type == IS_UNUSED) { method_slot[opline->op2.constant] = opline->result.num; } } } break; case ZEND_INIT_STATIC_METHOD_CALL: if (opline->op2_type == IS_CONST) { // op2 static method if (opline->op1_type == IS_CONST) { opline->result.num = add_static_slot(&hash, op_array, opline->op1.constant, opline->op2.constant, LITERAL_STATIC_METHOD, &cache_size); } else { opline->result.num = cache_size; cache_size += 2 * sizeof(void *); } } else if (opline->op1_type == IS_CONST) { // op1 class if (class_slot[opline->op1.constant] >= 0) { opline->result.num = class_slot[opline->op1.constant]; } else { opline->result.num = cache_size; cache_size += sizeof(void *); class_slot[opline->op1.constant] = opline->result.num; } } break; case ZEND_DEFINED: // op1 const if (const_slot[opline->op1.constant] >= 0) { opline->extended_value = const_slot[opline->op1.constant]; } else { opline->extended_value = cache_size; cache_size += sizeof(void *); const_slot[opline->op1.constant] = opline->extended_value; } break; case ZEND_FETCH_CONSTANT: // op2 const if (const_slot[opline->op2.constant] >= 0) { opline->extended_value = const_slot[opline->op2.constant]; } else { opline->extended_value = cache_size; cache_size += sizeof(void *); const_slot[opline->op2.constant] = opline->extended_value; } break; case ZEND_FETCH_CLASS_CONSTANT: if (opline->op1_type == IS_CONST) { // op1/op2 class_const opline->extended_value = add_static_slot(&hash, op_array, opline->op1.constant, opline->op2.constant, LITERAL_CLASS_CONST, &cache_size); } else { opline->extended_value = cache_size; cache_size += 2 * sizeof(void *); } break; case ZEND_FETCH_STATIC_PROP_R: case ZEND_FETCH_STATIC_PROP_W: case ZEND_FETCH_STATIC_PROP_RW: case ZEND_FETCH_STATIC_PROP_IS: case ZEND_FETCH_STATIC_PROP_UNSET: case ZEND_FETCH_STATIC_PROP_FUNC_ARG: case ZEND_UNSET_STATIC_PROP: if (opline->op1_type == IS_CONST) { // op1 static property if (opline->op2_type == IS_CONST) { opline->extended_value = add_static_slot(&hash, op_array, opline->op2.constant, opline->op1.constant, LITERAL_STATIC_PROPERTY, &cache_size); } else { opline->extended_value = cache_size; cache_size += 2 * sizeof(void *); } } else if (opline->op2_type == IS_CONST) { // op2 class if (class_slot[opline->op2.constant] >= 0) { opline->extended_value = class_slot[opline->op2.constant]; } else { opline->extended_value = cache_size; cache_size += sizeof(void *); class_slot[opline->op2.constant] = opline->extended_value; } } break; case ZEND_ISSET_ISEMPTY_STATIC_PROP: if (opline->op1_type == IS_CONST) { // op1 static property if (opline->op2_type == IS_CONST) { opline->extended_value = add_static_slot(&hash, op_array, opline->op2.constant, opline->op1.constant, LITERAL_STATIC_PROPERTY, &cache_size) | (opline->extended_value & ZEND_ISEMPTY); } else { opline->extended_value = cache_size | (opline->extended_value & ZEND_ISEMPTY); cache_size += 2 * sizeof(void *); } } else if (opline->op2_type == IS_CONST) { // op2 class if (class_slot[opline->op2.constant] >= 0) { opline->extended_value = class_slot[opline->op2.constant] | (opline->extended_value & ZEND_ISEMPTY); } else { opline->extended_value = cache_size | (opline->extended_value & ZEND_ISEMPTY); cache_size += sizeof(void *); class_slot[opline->op2.constant] = opline->extended_value & ~ZEND_ISEMPTY; } } break; case ZEND_FETCH_CLASS: case ZEND_INSTANCEOF: if (opline->op2_type == IS_CONST) { // op2 class if (class_slot[opline->op2.constant] >= 0) { opline->extended_value = class_slot[opline->op2.constant]; } else { opline->extended_value = cache_size; cache_size += sizeof(void *); class_slot[opline->op2.constant] = opline->extended_value; } } break; case ZEND_NEW: if (opline->op1_type == IS_CONST) { // op1 class if (class_slot[opline->op1.constant] >= 0) { opline->op2.num = class_slot[opline->op1.constant]; } else { opline->op2.num = cache_size; cache_size += sizeof(void *); class_slot[opline->op1.constant] = opline->op2.num; } } break; case ZEND_CATCH: if (opline->op1_type == IS_CONST) { // op1 class if (class_slot[opline->op1.constant] >= 0) { opline->extended_value = class_slot[opline->op1.constant] | (opline->extended_value & ZEND_LAST_CATCH); } else { opline->extended_value = cache_size | (opline->extended_value & ZEND_LAST_CATCH); cache_size += sizeof(void *); class_slot[opline->op1.constant] = opline->extended_value & ~ZEND_LAST_CATCH; } } break; case ZEND_BIND_GLOBAL: // op2 bind var if (bind_var_slot[opline->op2.constant] >= 0) { opline->extended_value = bind_var_slot[opline->op2.constant]; } else { opline->extended_value = cache_size; cache_size += sizeof(void *); bind_var_slot[opline->op2.constant] = opline->extended_value; } break; } opline++; } op_array->cache_size = cache_size; zend_hash_destroy(&hash); zend_arena_release(&ctx->arena, checkpoint); if (1) { opline = op_array->opcodes; while (1) { if (opline->opcode == ZEND_RECV_INIT) { zval *val = &op_array->literals[opline->op2.constant]; if (Z_TYPE_P(val) == IS_CONSTANT_AST) { uint32_t slot = ZEND_MM_ALIGNED_SIZE_EX(op_array->cache_size, 8); Z_CACHE_SLOT_P(val) = slot; op_array->cache_size += sizeof(zval); } } else if (opline->opcode != ZEND_RECV) { break; } opline++; } } #if DEBUG_COMPACT_LITERALS { int i, use_copy; fprintf(stderr, "Optimized literlas table size %d\n", op_array->last_literal); for (i = 0; i < op_array->last_literal; i++) { zval zv; ZVAL_COPY_VALUE(&zv, op_array->literals + i); use_copy = zend_make_printable_zval(op_array->literals + i, &zv); fprintf(stderr, "Literal %d, val (%d):%s\n", i, Z_STRLEN(zv), Z_STRVAL(zv)); if (use_copy) { zval_ptr_dtor_nogc(&zv); } } fflush(stderr); } #endif } }
PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, size_t inquery_len, char **outquery, size_t *outquery_len) { Scanner s; char *ptr, *newbuffer; int t; int bindno = 0; int ret = 0; size_t newbuffer_len; HashTable *params; struct pdo_bound_param_data *param; int query_type = PDO_PLACEHOLDER_NONE; struct placeholder *placeholders = NULL, *placetail = NULL, *plc = NULL; ptr = *outquery; s.cur = inquery; s.end = inquery + inquery_len + 1; /* phase 1: look for args */ while((t = scan(&s)) != PDO_PARSER_EOI) { if (t == PDO_PARSER_BIND || t == PDO_PARSER_BIND_POS) { if (t == PDO_PARSER_BIND) { int len = s.cur - s.tok; if ((inquery < (s.cur - len)) && isalnum(*(s.cur - len - 1))) { continue; } query_type |= PDO_PLACEHOLDER_NAMED; } else { query_type |= PDO_PLACEHOLDER_POSITIONAL; } plc = emalloc(sizeof(*plc)); memset(plc, 0, sizeof(*plc)); plc->next = NULL; plc->pos = s.tok; plc->len = s.cur - s.tok; plc->bindno = bindno++; if (placetail) { placetail->next = plc; } else { placeholders = plc; } placetail = plc; } } if (bindno == 0) { /* nothing to do; good! */ return 0; } /* did the query make sense to me? */ if (query_type == (PDO_PLACEHOLDER_NAMED|PDO_PLACEHOLDER_POSITIONAL)) { /* they mixed both types; punt */ pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "mixed named and positional parameters"); ret = -1; goto clean_up; } if (stmt->supports_placeholders == query_type && !stmt->named_rewrite_template) { /* query matches native syntax */ ret = 0; goto clean_up; } if (stmt->named_rewrite_template) { /* magic/hack. * We we pretend that the query was positional even if * it was named so that we fall into the * named rewrite case below. Not too pretty, * but it works. */ query_type = PDO_PLACEHOLDER_POSITIONAL; } params = stmt->bound_params; /* Do we have placeholders but no bound params */ if (bindno && !params && stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) { pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "no parameters were bound"); ret = -1; goto clean_up; } if (params && bindno != zend_hash_num_elements(params) && stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) { /* extra bit of validation for instances when same params are bound more than once */ if (query_type != PDO_PLACEHOLDER_POSITIONAL && bindno > zend_hash_num_elements(params)) { int ok = 1; for (plc = placeholders; plc; plc = plc->next) { if ((param = zend_hash_str_find_ptr(params, plc->pos, plc->len)) == NULL) { ok = 0; break; } } if (ok) { goto safe; } } pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "number of bound variables does not match number of tokens"); ret = -1; goto clean_up; } safe: /* what are we going to do ? */ if (stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) { /* query generation */ newbuffer_len = inquery_len; /* let's quote all the values */ for (plc = placeholders; plc; plc = plc->next) { if (query_type == PDO_PLACEHOLDER_POSITIONAL) { param = zend_hash_index_find_ptr(params, plc->bindno); } else { param = zend_hash_str_find_ptr(params, plc->pos, plc->len); } if (param == NULL) { /* parameter was not defined */ ret = -1; pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined"); goto clean_up; } if (stmt->dbh->methods->quoter) { zval *parameter; if (Z_ISREF(param->parameter)) { parameter = Z_REFVAL(param->parameter); } else { parameter = ¶m->parameter; } if (param->param_type == PDO_PARAM_LOB && Z_TYPE_P(parameter) == IS_RESOURCE) { php_stream *stm; php_stream_from_zval_no_verify(stm, parameter); if (stm) { zend_string *buf; buf = php_stream_copy_to_mem(stm, PHP_STREAM_COPY_ALL, 0); if (!buf) { buf = ZSTR_EMPTY_ALLOC(); } if (!stmt->dbh->methods->quoter(stmt->dbh, ZSTR_VAL(buf), ZSTR_LEN(buf), &plc->quoted, &plc->qlen, param->param_type)) { /* bork */ ret = -1; strncpy(stmt->error_code, stmt->dbh->error_code, 6); if (buf) { zend_string_release(buf); } goto clean_up; } if (buf) { zend_string_release(buf); } } else { pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource"); ret = -1; goto clean_up; } plc->freeq = 1; } else { zval tmp_param; ZVAL_DUP(&tmp_param, parameter); switch (Z_TYPE(tmp_param)) { case IS_NULL: plc->quoted = "NULL"; plc->qlen = sizeof("NULL")-1; plc->freeq = 0; break; case IS_FALSE: case IS_TRUE: convert_to_long(&tmp_param); /* fall through */ case IS_LONG: case IS_DOUBLE: convert_to_string(&tmp_param); plc->qlen = Z_STRLEN(tmp_param); plc->quoted = estrdup(Z_STRVAL(tmp_param)); plc->freeq = 1; break; default: convert_to_string(&tmp_param); if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL(tmp_param), Z_STRLEN(tmp_param), &plc->quoted, &plc->qlen, param->param_type)) { /* bork */ ret = -1; strncpy(stmt->error_code, stmt->dbh->error_code, 6); goto clean_up; } plc->freeq = 1; } zval_dtor(&tmp_param); } } else { zval *parameter; if (Z_ISREF(param->parameter)) { parameter = Z_REFVAL(param->parameter); } else { parameter = ¶m->parameter; } plc->quoted = Z_STRVAL_P(parameter); plc->qlen = Z_STRLEN_P(parameter); } newbuffer_len += plc->qlen; } rewrite: /* allocate output buffer */ newbuffer = emalloc(newbuffer_len + 1); *outquery = newbuffer; /* and build the query */ plc = placeholders; ptr = inquery; do { t = plc->pos - ptr; if (t) { memcpy(newbuffer, ptr, t); newbuffer += t; } memcpy(newbuffer, plc->quoted, plc->qlen); newbuffer += plc->qlen; ptr = plc->pos + plc->len; plc = plc->next; } while (plc); t = (inquery + inquery_len) - ptr; if (t) { memcpy(newbuffer, ptr, t); newbuffer += t; } *newbuffer = '\0'; *outquery_len = newbuffer - *outquery; ret = 1; goto clean_up; } else if (query_type == PDO_PLACEHOLDER_POSITIONAL) { /* rewrite ? to :pdoX */ char *name, *idxbuf; const char *tmpl = stmt->named_rewrite_template ? stmt->named_rewrite_template : ":pdo%d"; int bind_no = 1; newbuffer_len = inquery_len; if (stmt->bound_param_map == NULL) { ALLOC_HASHTABLE(stmt->bound_param_map); zend_hash_init(stmt->bound_param_map, 13, NULL, free_param_name, 0); } for (plc = placeholders; plc; plc = plc->next) { int skip_map = 0; char *p; name = estrndup(plc->pos, plc->len); /* check if bound parameter is already available */ if (!strcmp(name, "?") || (p = zend_hash_str_find_ptr(stmt->bound_param_map, name, plc->len)) == NULL) { spprintf(&idxbuf, 0, tmpl, bind_no++); } else { idxbuf = estrdup(p); skip_map = 1; } plc->quoted = idxbuf; plc->qlen = strlen(plc->quoted); plc->freeq = 1; newbuffer_len += plc->qlen; if (!skip_map && stmt->named_rewrite_template) { /* create a mapping */ zend_hash_str_update_mem(stmt->bound_param_map, name, plc->len, idxbuf, plc->qlen + 1); } /* map number to name */ zend_hash_index_update_mem(stmt->bound_param_map, plc->bindno, idxbuf, plc->qlen + 1); efree(name); } goto rewrite; } else { /* rewrite :name to ? */ newbuffer_len = inquery_len; if (stmt->bound_param_map == NULL) { ALLOC_HASHTABLE(stmt->bound_param_map); zend_hash_init(stmt->bound_param_map, 13, NULL, free_param_name, 0); } for (plc = placeholders; plc; plc = plc->next) { char *name; name = estrndup(plc->pos, plc->len); zend_hash_index_update_mem(stmt->bound_param_map, plc->bindno, name, plc->len + 1); efree(name); plc->quoted = "?"; plc->qlen = 1; } goto rewrite; } clean_up: while (placeholders) { plc = placeholders; placeholders = plc->next; if (plc->freeq) { efree(plc->quoted); } efree(plc); } return ret; }
static int do_callback(struct pdo_sqlite_fci *fc, zval *cb, int argc, sqlite3_value **argv, sqlite3_context *context, int is_agg) { zval *zargs = NULL; zval retval; int i; int ret; int fake_argc; zend_reference *agg_context = NULL; if (is_agg) { is_agg = 2; } fake_argc = argc + is_agg; fc->fci.size = sizeof(fc->fci); ZVAL_COPY_VALUE(&fc->fci.function_name, cb); fc->fci.object = NULL; fc->fci.retval = &retval; fc->fci.param_count = fake_argc; /* build up the params */ if (fake_argc) { zargs = safe_emalloc(fake_argc, sizeof(zval), 0); } if (is_agg) { agg_context = (zend_reference*)sqlite3_aggregate_context(context, sizeof(zend_reference)); if (!agg_context) { ZVAL_NULL(&zargs[0]); } else { if (Z_ISUNDEF(agg_context->val)) { GC_REFCOUNT(agg_context) = 1; GC_TYPE_INFO(agg_context) = IS_REFERENCE; ZVAL_NULL(&agg_context->val); } ZVAL_REF(&zargs[0], agg_context); } ZVAL_LONG(&zargs[1], sqlite3_aggregate_count(context)); } for (i = 0; i < argc; i++) { /* get the value */ switch (sqlite3_value_type(argv[i])) { case SQLITE_INTEGER: ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i])); break; case SQLITE_FLOAT: ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i])); break; case SQLITE_NULL: ZVAL_NULL(&zargs[i + is_agg]); break; case SQLITE_BLOB: case SQLITE3_TEXT: default: ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i])); break; } } fc->fci.params = zargs; if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) { php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback"); } /* clean up the params */ if (zargs) { for (i = is_agg; i < fake_argc; i++) { zval_ptr_dtor(&zargs[i]); } if (is_agg) { zval_ptr_dtor(&zargs[1]); } efree(zargs); } if (!is_agg || !argv) { /* only set the sqlite return value if we are a scalar function, * or if we are finalizing an aggregate */ if (!Z_ISUNDEF(retval)) { switch (Z_TYPE(retval)) { case IS_LONG: sqlite3_result_int(context, Z_LVAL(retval)); break; case IS_NULL: sqlite3_result_null(context); break; case IS_DOUBLE: sqlite3_result_double(context, Z_DVAL(retval)); break; default: convert_to_string_ex(&retval); sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT); break; } } else { sqlite3_result_error(context, "failed to invoke callback", 0); } if (agg_context) { zval_ptr_dtor(&agg_context->val); } } else { /* we're stepping in an aggregate; the return value goes into * the context */ if (agg_context) { zval_ptr_dtor(&agg_context->val); } if (!Z_ISUNDEF(retval)) { ZVAL_COPY_VALUE(&agg_context->val, &retval); ZVAL_UNDEF(&retval); } else { ZVAL_UNDEF(&agg_context->val); } } if (!Z_ISUNDEF(retval)) { zval_ptr_dtor(&retval); } return ret; }
/* {{{ php_dba_open */ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent) { zval *args = NULL; int ac = ZEND_NUM_ARGS(); dba_mode_t modenr; dba_info *info, *other; dba_handler *hptr; char *key = NULL, *error = NULL; int keylen = 0; int i; int lock_mode, lock_flag, lock_dbf = 0; char *file_mode; char mode[4], *pmode, *lock_file_mode = NULL; int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0; zend_string *opened_path = NULL; char *lock_name; if (ac < 2) { WRONG_PARAM_COUNT; } /* we pass additional args to the respective handler */ args = safe_emalloc(ac, sizeof(zval), 0); if (zend_get_parameters_array_ex(ac, args) != SUCCESS) { efree(args); WRONG_PARAM_COUNT; } /* we only take string arguments */ for (i = 0; i < ac; i++) { if (Z_TYPE(args[i]) != IS_STRING) { convert_to_string_ex(&args[i]); } else if (Z_REFCOUNTED(args[i])) { Z_ADDREF(args[i]); } keylen += Z_STRLEN(args[i]); } if (persistent) { zend_resource *le; /* calculate hash */ key = safe_emalloc(keylen, 1, 1); key[keylen] = '\0'; keylen = 0; for(i = 0; i < ac; i++) { memcpy(key+keylen, Z_STRVAL(args[i]), Z_STRLEN(args[i])); keylen += Z_STRLEN(args[i]); } /* try to find if we already have this link in our persistent list */ if ((le = zend_hash_str_find_ptr(&EG(persistent_list), key, keylen)) != NULL) { FREENOW; if (le->type != le_pdb) { RETURN_FALSE; } info = (dba_info *)le->ptr; GC_REFCOUNT(le)++; RETURN_RES(le); return; } } if (ac==2) { hptr = DBA_G(default_hptr); if (!hptr) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "No default handler selected"); FREENOW; RETURN_FALSE; } } else { for (hptr = handler; hptr->name && strcasecmp(hptr->name, Z_STRVAL(args[2])); hptr++); } if (!hptr->name) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "No such handler: %s", Z_STRVAL(args[2])); FREENOW; RETURN_FALSE; } /* Check mode: [rwnc][fl]?t? * r: Read * w: Write * n: Create/Truncate * c: Create * * d: force lock on database file * l: force lock on lck file * -: ignore locking * * t: test open database, warning if locked */ strlcpy(mode, Z_STRVAL(args[1]), sizeof(mode)); pmode = &mode[0]; if (pmode[0] && (pmode[1]=='d' || pmode[1]=='l' || pmode[1]=='-')) { /* force lock on db file or lck file or disable locking */ switch (pmode[1]) { case 'd': lock_dbf = 1; if ((hptr->flags & DBA_LOCK_ALL) == 0) { lock_flag = (hptr->flags & DBA_LOCK_ALL); break; } /* no break */ case 'l': lock_flag = DBA_LOCK_ALL; if ((hptr->flags & DBA_LOCK_ALL) == 0) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_NOTICE, "Handler %s does locking internally", hptr->name); } break; default: case '-': if ((hptr->flags & DBA_LOCK_ALL) == 0) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Locking cannot be disabled for handler %s", hptr->name); FREENOW; RETURN_FALSE; } lock_flag = 0; break; } } else { lock_flag = (hptr->flags&DBA_LOCK_ALL); lock_dbf = 1; } switch (*pmode++) { case 'r': modenr = DBA_READER; lock_mode = (lock_flag & DBA_LOCK_READER) ? LOCK_SH : 0; file_mode = "r"; break; case 'w': modenr = DBA_WRITER; lock_mode = (lock_flag & DBA_LOCK_WRITER) ? LOCK_EX : 0; file_mode = "r+b"; break; case 'c': modenr = DBA_CREAT; lock_mode = (lock_flag & DBA_LOCK_CREAT) ? LOCK_EX : 0; if (lock_mode) { if (lock_dbf) { /* the create/append check will be done on the lock * when the lib opens the file it is already created */ file_mode = "r+b"; /* read & write, seek 0 */ lock_file_mode = "a+b"; /* append */ } else { file_mode = "a+b"; /* append */ lock_file_mode = "w+b"; /* create/truncate */ } } else { file_mode = "a+b"; } /* In case of the 'a+b' append mode, the handler is responsible * to handle any rewind problems (see flatfile handler). */ break; case 'n': modenr = DBA_TRUNC; lock_mode = (lock_flag & DBA_LOCK_TRUNC) ? LOCK_EX : 0; file_mode = "w+b"; break; default: php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Illegal DBA mode"); FREENOW; RETURN_FALSE; } if (!lock_file_mode) { lock_file_mode = file_mode; } if (*pmode=='d' || *pmode=='l' || *pmode=='-') { pmode++; /* done already - skip here */ } if (*pmode=='t') { pmode++; if (!lock_flag) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "You cannot combine modifiers - (no lock) and t (test lock)"); FREENOW; RETURN_FALSE; } if (!lock_mode) { if ((hptr->flags & DBA_LOCK_ALL) == 0) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Handler %s uses its own locking which doesn't support mode modifier t (test lock)", hptr->name); FREENOW; RETURN_FALSE; } else { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Handler %s doesn't uses locking for this mode which makes modifier t (test lock) obsolete", hptr->name); FREENOW; RETURN_FALSE; } } else { lock_mode |= LOCK_NB; /* test =: non blocking */ } } if (*pmode) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Illegal DBA mode"); FREENOW; RETURN_FALSE; } info = pemalloc(sizeof(dba_info), persistent); memset(info, 0, sizeof(dba_info)); info->path = pestrdup(Z_STRVAL(args[0]), persistent); info->mode = modenr; info->argc = ac - 3; info->argv = args + 3; info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0); info->lock.mode = lock_mode; /* if any open call is a locking call: * check if we already habe a locking call open that should block this call * the problem is some systems would allow read during write */ if (hptr->flags & DBA_LOCK_ALL) { if ((other = php_dba_find(info->path)) != NULL) { if ( ( (lock_mode&LOCK_EX) && (other->lock.mode&(LOCK_EX|LOCK_SH)) ) || ( (other->lock.mode&LOCK_EX) && (lock_mode&(LOCK_EX|LOCK_SH)) ) ) { error = "Unable to establish lock (database file already open)"; /* force failure exit */ } } } if (!error && lock_mode) { if (lock_dbf) { lock_name = Z_STRVAL(args[0]); } else { spprintf(&lock_name, 0, "%s.lck", info->path); if (!strcmp(file_mode, "r")) { /* when in read only mode try to use existing .lck file first */ /* do not log errors for .lck file while in read ony mode on .lck file */ lock_file_mode = "rb"; info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, &opened_path); } if (!info->lock.fp) { /* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */ lock_file_mode = "a+b"; } else { if (opened_path) { info->lock.name = pestrndup(opened_path->val, opened_path->len, persistent); zend_string_release(opened_path); } } } if (!info->lock.fp) { info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path); if (info->lock.fp) { if (lock_dbf) { /* replace the path info with the real path of the opened file */ pefree(info->path, persistent); info->path = pestrndup(opened_path->val, opened_path->len, persistent); } /* now store the name of the lock */ info->lock.name = pestrndup(opened_path->val, opened_path->len, persistent); zend_string_release(opened_path); } } if (!lock_dbf) { efree(lock_name); } if (!info->lock.fp) { dba_close(info); /* stream operation already wrote an error message */ FREENOW; RETURN_FALSE; } if (!php_stream_supports_lock(info->lock.fp)) { error = "Stream does not support locking"; } if (php_stream_lock(info->lock.fp, lock_mode)) { error = "Unable to establish lock"; /* force failure exit */ } } /* centralised open stream for builtin */ if (!error && (hptr->flags&DBA_STREAM_OPEN)==DBA_STREAM_OPEN) { if (info->lock.fp && lock_dbf) { info->fp = info->lock.fp; /* use the same stream for locking and database access */ } else { info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL); } if (!info->fp) { dba_close(info); /* stream operation already wrote an error message */ FREENOW; RETURN_FALSE; } if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) { /* Needed because some systems do not allow to write to the original * file contents with O_APPEND being set. */ if (SUCCESS != php_stream_cast(info->fp, PHP_STREAM_AS_FD, (void*)&info->fd, 1)) { php_error_docref(NULL, E_WARNING, "Could not cast stream"); dba_close(info); FREENOW; RETURN_FALSE; #ifdef F_SETFL } else if (modenr == DBA_CREAT) { int flags = fcntl(info->fd, F_SETFL); fcntl(info->fd, F_SETFL, flags & ~O_APPEND); #endif } } } if (error || hptr->open(info, &error) != SUCCESS) { dba_close(info); php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Driver initialization failed for handler: %s%s%s", hptr->name, error?": ":"", error?error:""); FREENOW; RETURN_FALSE; } info->hnd = hptr; info->argc = 0; info->argv = NULL; if (persistent) { zend_resource new_le; new_le.type = le_pdb; new_le.ptr = info; if (zend_hash_str_update_mem(&EG(persistent_list), key, keylen, &new_le, sizeof(zend_resource)) == NULL) { dba_close(info); php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Could not register persistent resource"); FREENOW; RETURN_FALSE; } } RETVAL_RES(zend_register_resource(info, (persistent ? le_pdb : le_db))); FREENOW; }
static void call_php(char *name, PARAMDSC *r, int argc, PARAMDSC **argv) { do { zval callback, args[4], *argp[4], return_value; PARAMVARY *res = (PARAMVARY*)r->dsc_address; int i; INIT_ZVAL(callback); ZVAL_STRING(&callback,name,0); LOCK(); /* check if the requested function exists */ if (!zend_is_callable(&callback, 0, NULL TSRMLS_CC)) { break; } UNLOCK(); /* create the argument array */ for (i = 0; i < argc; ++i) { INIT_ZVAL(args[i]); argp[i] = &args[i]; /* test arg for null */ if (argv[i]->dsc_flags & DSC_null) { ZVAL_NULL(argp[i]); continue; } switch (argv[i]->dsc_dtype) { ISC_INT64 l; struct tm t; char const *fmt; char d[64]; case dtype_cstring: ZVAL_STRING(argp[i], (char*)argv[i]->dsc_address,0); break; case dtype_text: ZVAL_STRINGL(argp[i], (char*)argv[i]->dsc_address, argv[i]->dsc_length,0); break; case dtype_varying: ZVAL_STRINGL(argp[i], ((PARAMVARY*)argv[i]->dsc_address)->vary_string, ((PARAMVARY*)argv[i]->dsc_address)->vary_length,0); break; case dtype_short: if (argv[i]->dsc_scale == 0) { ZVAL_LONG(argp[i], *(short*)argv[i]->dsc_address); } else { ZVAL_DOUBLE(argp[i], ((double)*(short*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]); } break; case dtype_long: if (argv[i]->dsc_scale == 0) { ZVAL_LONG(argp[i], *(ISC_LONG*)argv[i]->dsc_address); } else { ZVAL_DOUBLE(argp[i], ((double)*(ISC_LONG*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]); } break; case dtype_int64: l = *(ISC_INT64*)argv[i]->dsc_address; if (argv[i]->dsc_scale == 0 && l <= LONG_MAX && l >= LONG_MIN) { ZVAL_LONG(argp[i], (long)l); } else { ZVAL_DOUBLE(argp[i], ((double)l)/scales[-argv[i]->dsc_scale]); } break; case dtype_real: ZVAL_DOUBLE(argp[i], *(float*)argv[i]->dsc_address); break; case dtype_double: ZVAL_DOUBLE(argp[i], *(double*)argv[i]->dsc_address); break; case dtype_sql_date: isc_decode_sql_date((ISC_DATE*)argv[i]->dsc_address, &t); ZVAL_STRINGL(argp[i], d, strftime(d, sizeof(d), INI_STR("ibase.dateformat"), &t),1); break; case dtype_sql_time: isc_decode_sql_time((ISC_TIME*)argv[i]->dsc_address, &t); ZVAL_STRINGL(argp[i], d, strftime(d, sizeof(d), INI_STR("ibase.timeformat"), &t),1); break; case dtype_timestamp: isc_decode_timestamp((ISC_TIMESTAMP*)argv[i]->dsc_address, &t); ZVAL_STRINGL(argp[i], d, strftime(d, sizeof(d), INI_STR("ibase.timestampformat"), &t),1); break; } } LOCK(); /* now call the function */ if (FAILURE == call_user_function(EG(function_table), NULL, &callback, &return_value, argc, argp TSRMLS_CC)) { UNLOCK(); break; } UNLOCK(); for (i = 0; i < argc; ++i) { switch (argv[i]->dsc_dtype) { case dtype_sql_date: case dtype_sql_time: case dtype_timestamp: zval_dtor(argp[i]); } } /* return whatever type we got back from the callback: let DB handle conversion */ switch (Z_TYPE(return_value)) { case IS_LONG: r->dsc_dtype = dtype_long; *(long*)r->dsc_address = Z_LVAL(return_value); r->dsc_length = sizeof(long); break; case IS_DOUBLE: r->dsc_dtype = dtype_double; *(double*)r->dsc_address = Z_DVAL(return_value); r->dsc_length = sizeof(double); break; case IS_NULL: r->dsc_flags |= DSC_null; break; default: convert_to_string(&return_value); case IS_STRING: r->dsc_dtype = dtype_varying; memcpy(res->vary_string, Z_STRVAL(return_value), (res->vary_length = min(r->dsc_length-2,Z_STRLEN(return_value)))); r->dsc_length = res->vary_length+2; break; } zval_dtor(&return_value); return; } while (0); /** * If we end up here, we should report an error back to the DB engine, but * that's not possible. We can however report it back to PHP. */ LOCK(); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error calling function '%s' from database", name); UNLOCK(); }
/* {{{ _php_mb_regex_ereg_replace_exec */ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOptionType options, int is_callable) { zval *arg_pattern_zval; char *arg_pattern; size_t arg_pattern_len; char *replace; size_t replace_len; zend_fcall_info arg_replace_fci; zend_fcall_info_cache arg_replace_fci_cache; char *string; size_t string_len; char *p; php_mb_regex_t *re; OnigSyntaxType *syntax; OnigRegion *regs = NULL; smart_str out_buf = {0}; smart_str eval_buf = {0}; smart_str *pbuf; size_t i; int err, eval, n; OnigUChar *pos; OnigUChar *string_lim; char *description = NULL; char pat_buf[6]; const mbfl_encoding *enc; { const char *current_enc_name; current_enc_name = _php_mb_regex_mbctype2name(MBREX(current_mbctype)); if (current_enc_name == NULL || (enc = mbfl_name2encoding(current_enc_name)) == NULL) { php_error_docref(NULL, E_WARNING, "Unknown error"); RETURN_FALSE; } } eval = 0; { char *option_str = NULL; size_t option_str_len = 0; if (!is_callable) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "zss|s", &arg_pattern_zval, &replace, &replace_len, &string, &string_len, &option_str, &option_str_len) == FAILURE) { RETURN_FALSE; } } else { if (zend_parse_parameters(ZEND_NUM_ARGS(), "zfs|s", &arg_pattern_zval, &arg_replace_fci, &arg_replace_fci_cache, &string, &string_len, &option_str, &option_str_len) == FAILURE) { RETURN_FALSE; } } if (!php_mb_check_encoding( string, string_len, _php_mb_regex_mbctype2name(MBREX(current_mbctype)) )) { RETURN_NULL(); } if (option_str != NULL) { _php_mb_regex_init_options(option_str, option_str_len, &options, &syntax, &eval); } else { options |= MBREX(regex_default_options); syntax = MBREX(regex_default_syntax); } } if (eval && !is_callable) { php_error_docref(NULL, E_DEPRECATED, "The 'e' option is deprecated, use mb_ereg_replace_callback instead"); } if (Z_TYPE_P(arg_pattern_zval) == IS_STRING) { arg_pattern = Z_STRVAL_P(arg_pattern_zval); arg_pattern_len = Z_STRLEN_P(arg_pattern_zval); } else { /* FIXME: this code is not multibyte aware! */ convert_to_long_ex(arg_pattern_zval); pat_buf[0] = (char)Z_LVAL_P(arg_pattern_zval); pat_buf[1] = '\0'; pat_buf[2] = '\0'; pat_buf[3] = '\0'; pat_buf[4] = '\0'; pat_buf[5] = '\0'; arg_pattern = pat_buf; arg_pattern_len = 1; } /* create regex pattern buffer */ re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, options, MBREX(current_mbctype), syntax); if (re == NULL) { RETURN_FALSE; } if (eval || is_callable) { pbuf = &eval_buf; description = zend_make_compiled_string_description("mbregex replace"); } else { pbuf = &out_buf; description = NULL; } if (is_callable) { if (eval) { php_error_docref(NULL, E_WARNING, "Option 'e' cannot be used with replacement callback"); RETURN_FALSE; } } /* do the actual work */ err = 0; pos = (OnigUChar *)string; string_lim = (OnigUChar*)(string + string_len); regs = onig_region_new(); while (err >= 0) { err = onig_search(re, (OnigUChar *)string, (OnigUChar *)string_lim, pos, (OnigUChar *)string_lim, regs, 0); if (err <= -2) { OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(err_str, err); php_error_docref(NULL, E_WARNING, "mbregex search failure in php_mbereg_replace_exec(): %s", err_str); break; } if (err >= 0) { #if moriyoshi_0 if (regs->beg[0] == regs->end[0]) { php_error_docref(NULL, E_WARNING, "Empty regular expression"); break; } #endif /* copy the part of the string before the match */ smart_str_appendl(&out_buf, (char *)pos, (size_t)((OnigUChar *)(string + regs->beg[0]) - pos)); if (!is_callable) { /* copy replacement and backrefs */ i = 0; p = replace; while (i < replace_len) { int fwd = (int) php_mb_mbchar_bytes_ex(p, enc); n = -1; if ((replace_len - i) >= 2 && fwd == 1 && p[0] == '\\' && p[1] >= '0' && p[1] <= '9') { n = p[1] - '0'; } if (n >= 0 && n < regs->num_regs) { if (regs->beg[n] >= 0 && regs->beg[n] < regs->end[n] && (size_t)regs->end[n] <= string_len) { smart_str_appendl(pbuf, string + regs->beg[n], regs->end[n] - regs->beg[n]); } p += 2; i += 2; } else { smart_str_appendl(pbuf, p, fwd); p += fwd; i += fwd; } } } if (eval) { zval v; zend_string *eval_str; /* null terminate buffer */ smart_str_0(&eval_buf); if (eval_buf.s) { eval_str = eval_buf.s; } else { eval_str = ZSTR_EMPTY_ALLOC(); } /* do eval */ if (zend_eval_stringl(ZSTR_VAL(eval_str), ZSTR_LEN(eval_str), &v, description) == FAILURE) { efree(description); zend_throw_error(NULL, "Failed evaluating code: %s%s", PHP_EOL, ZSTR_VAL(eval_str)); onig_region_free(regs, 0); smart_str_free(&out_buf); smart_str_free(&eval_buf); RETURN_FALSE; } /* result of eval */ convert_to_string(&v); smart_str_appendl(&out_buf, Z_STRVAL(v), Z_STRLEN(v)); /* Clean up */ smart_str_free(&eval_buf); zval_dtor(&v); } else if (is_callable) { zval args[1]; zval subpats, retval; int i; array_init(&subpats); for (i = 0; i < regs->num_regs; i++) { add_next_index_stringl(&subpats, string + regs->beg[i], regs->end[i] - regs->beg[i]); } ZVAL_COPY_VALUE(&args[0], &subpats); /* null terminate buffer */ smart_str_0(&eval_buf); arg_replace_fci.param_count = 1; arg_replace_fci.params = args; arg_replace_fci.retval = &retval; if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache) == SUCCESS && !Z_ISUNDEF(retval)) { convert_to_string_ex(&retval); smart_str_appendl(&out_buf, Z_STRVAL(retval), Z_STRLEN(retval)); smart_str_free(&eval_buf); zval_ptr_dtor(&retval); } else { if (!EG(exception)) { php_error_docref(NULL, E_WARNING, "Unable to call custom replacement function"); } } zval_ptr_dtor(&subpats); } n = regs->end[0]; if ((pos - (OnigUChar *)string) < n) { pos = (OnigUChar *)string + n; } else { if (pos < string_lim) { smart_str_appendl(&out_buf, (char *)pos, 1); } pos++; } } else { /* nomatch */ /* stick that last bit of string on our output */ if (string_lim - pos > 0) { smart_str_appendl(&out_buf, (char *)pos, string_lim - pos); } } onig_region_free(regs, 0); } if (description) { efree(description); } if (regs != NULL) { onig_region_free(regs, 1); } smart_str_free(&eval_buf); if (err <= -2) { smart_str_free(&out_buf); RETVAL_FALSE; } else if (out_buf.s) { smart_str_0(&out_buf); RETVAL_STR(out_buf.s); } else { RETVAL_EMPTY_STRING(); } }