static inline zend_long *pthreads_get_guard(zend_object *zobj, zval *member) /* {{{ */ { HashTable *guards; zend_long stub, *guard; zval tmp; ZEND_ASSERT(GC_FLAGS(zobj) & IS_OBJ_USE_GUARDS); if (GC_FLAGS(zobj) & IS_OBJ_HAS_GUARDS) { guards = Z_PTR(zobj->properties_table[zobj->ce->default_properties_count]); ZEND_ASSERT(guards != NULL); if (Z_TYPE_P(member) == IS_LONG) { if ((guard = (zend_long *)zend_hash_index_find_ptr(guards, Z_LVAL_P(member))) != NULL) { return guard; } } else { if ((guard = (zend_long *)zend_hash_find_ptr(guards, Z_STR_P(member))) != NULL) { return guard; } } } else { ALLOC_HASHTABLE(guards); zend_hash_init(guards, 8, NULL, pthreads_guard_dtor, 0); ZVAL_PTR(&tmp, guards); Z_PTR(zobj->properties_table[zobj->ce->default_properties_count]) = guards; GC_FLAGS(zobj) |= IS_OBJ_HAS_GUARDS; } stub = 0; if (Z_TYPE_P(member) == IS_LONG) { return (zend_long *)zend_hash_index_add_mem(guards, Z_LVAL_P(member), &stub, sizeof(zend_ulong)); } else return (zend_long *)zend_hash_add_mem(guards, Z_STR_P(member), &stub, sizeof(zend_ulong)); }
static int pgsql_stmt_describe(pdo_stmt_t *stmt, int colno) { pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; struct pdo_column_data *cols = stmt->columns; struct pdo_bound_param_data *param; char *str; if (!S->result) { return 0; } str = PQfname(S->result, colno); cols[colno].name = zend_string_init(str, strlen(str), 0); cols[colno].maxlen = PQfsize(S->result, colno); cols[colno].precision = PQfmod(S->result, colno); S->cols[colno].pgsql_type = PQftype(S->result, colno); switch (S->cols[colno].pgsql_type) { case BOOLOID: cols[colno].param_type = PDO_PARAM_BOOL; break; case OIDOID: /* did the user bind the column as a LOB ? */ if (stmt->bound_columns && ( (param = zend_hash_index_find_ptr(stmt->bound_columns, colno)) != NULL || (param = zend_hash_find_ptr(stmt->bound_columns, cols[colno].name)) != NULL)) { if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) { cols[colno].param_type = PDO_PARAM_LOB; break; } } cols[colno].param_type = PDO_PARAM_INT; break; case INT2OID: case INT4OID: cols[colno].param_type = PDO_PARAM_INT; break; case INT8OID: if (sizeof(zend_long)>=8) { cols[colno].param_type = PDO_PARAM_INT; } else { cols[colno].param_type = PDO_PARAM_STR; } break; case BYTEAOID: cols[colno].param_type = PDO_PARAM_LOB; break; default: cols[colno].param_type = PDO_PARAM_STR; } return 1; }
static APC_HOTSPOT zend_reference* my_copy_reference(const zend_reference* src, apc_context_t *ctxt) { apc_pool* pool = ctxt->pool; zend_reference *dst; assert(src != NULL); if (ctxt->copied.nTableSize) { zend_reference *rc = zend_hash_index_find_ptr(&ctxt->copied, (uintptr_t) src); if (rc) { GC_REFCOUNT(rc)++; return rc; } } if (ctxt->copy == APC_COPY_IN) { dst = pool->palloc(pool, sizeof(zend_reference)); } else { dst = emalloc(sizeof(zend_reference)); } GC_REFCOUNT(dst) = 1; GC_TYPE_INFO(dst) = IS_REFERENCE; my_copy_zval(&dst->val, &src->val, ctxt); if (ctxt->copied.nTableSize) { zend_hash_index_update_ptr(&ctxt->copied, (uintptr_t) src, dst); } return dst; }
static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, uint32_t type, HashTable *vars) /* {{{ */ { char *decode = NULL; switch (type &~ EXT_TYPE_UNUSED) { case IS_CV: { zend_string *var = ops->vars[EX_VAR_TO_NUM(op->var)]; asprintf(&decode, "$%.*s%c", ZSTR_LEN(var) <= 19 ? (int) ZSTR_LEN(var) : 18, ZSTR_VAL(var), ZSTR_LEN(var) <= 19 ? 0 : '+'); } break; case IS_VAR: case IS_TMP_VAR: { zend_ulong id = 0, *pid = NULL; if (vars != NULL) { if ((pid = zend_hash_index_find_ptr(vars, (zend_ulong) ops->vars - op->var))) { id = *pid; } else { id = zend_hash_num_elements(vars); zend_hash_index_update_mem(vars, (zend_ulong) ops->vars - op->var, &id, sizeof(zend_ulong)); } } asprintf(&decode, "@" ZEND_ULONG_FMT, id); } break; case IS_CONST: { zval *literal = RT_CONSTANT(ops, *op); decode = phpdbg_short_zval_print(literal, 20); } break; } return decode; } /* }}} */
int zend_shared_memdup_size(void *source, size_t size) { void *old_p; if ((old_p = zend_hash_index_find_ptr(&ZCG(xlat_table), (zend_ulong)source)) != NULL) { /* we already duplicated this pointer */ return 0; } zend_shared_alloc_register_xlat_entry(source, source); return ZEND_ALIGNED_SIZE(size); }
void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source) { void *old_p, *retval; if ((old_p = zend_hash_index_find_ptr(&ZCG(xlat_table), (zend_ulong)source)) != NULL) { /* we already duplicated this pointer */ return old_p; } retval = ZCG(mem); ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size)); memcpy(retval, source, size); zend_shared_alloc_register_xlat_entry(source, retval); if (free_source) { efree(source); } return retval; }
/* {{{ php_find_dbm */ dba_info *php_dba_find(const char* path) { zend_resource *le; dba_info *info; int numitems, i; numitems = zend_hash_next_free_element(&EG(regular_list)); for (i=1; i<numitems; i++) { if ((le = zend_hash_index_find_ptr(&EG(regular_list), i)) == NULL) { continue; } if (le->type == le_db || le->type == le_pdb) { info = (dba_info *)(le->ptr); if (!strcmp(info->path, path)) { return (dba_info *)(le->ptr); } } } return NULL; }
static void phpdbg_remove_watch_collision(phpdbg_watchpoint_t *watch) { phpdbg_watch_collision *cur; if ((cur = zend_hash_index_find_ptr(&PHPDBG_G(watch_collisions), (zend_ulong) Z_COUNTED_P(watch->addr.zv)))) { if (cur->refs && !--cur->refs) { phpdbg_delete_watchpoints_recursive(watch); } zend_hash_del(&cur->watches, watch->str); zend_hash_del(&cur->implicit_watches, watch->str); if (zend_hash_num_elements(&cur->watches) > 0) { cur->watch = Z_PTR_P(zend_hash_get_current_data_ex(&cur->watches, NULL)); } else if (zend_hash_num_elements(&cur->implicit_watches) > 0) { cur->watch = Z_PTR_P(zend_hash_get_current_data_ex(&cur->implicit_watches, NULL)); } else { phpdbg_deactivate_watchpoint(cur->watch); phpdbg_remove_watchpoint(cur->watch); zend_hash_index_del(&PHPDBG_G(watch_collisions), (zend_ulong) Z_COUNTED_P(watch->addr.zv)); } } }
int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery, int *outquery_len) { Scanner s; char *ptr; int t; int bindno = 0; int newbuffer_len; int padding; HashTable *params = stmt->bound_params; struct pdo_bound_param_data *param; /* allocate buffer for query with expanded binds, ptr is our writing pointer */ newbuffer_len = inquery_len; /* calculate the possible padding factor due to quoting */ if(stmt->dbh->max_escaped_char_length) { padding = stmt->dbh->max_escaped_char_length; } else { padding = 3; } if(params) { ZEND_HASH_FOREACH_PTR(params, param) { if(param->parameter) { convert_to_string(param->parameter); /* accommodate a string that needs to be fully quoted bind placeholders are at least 2 characters, so the accommodate their own "'s */ newbuffer_len += padding * Z_STRLEN_P(param->parameter); } } ZEND_HASH_FOREACH_END(); } *outquery = (char *) emalloc(newbuffer_len + 1); *outquery_len = 0; ptr = *outquery; s.cur = inquery; while((t = scan(&s)) != PDO_PARSER_EOI) { if(t == PDO_PARSER_TEXT) { memcpy(ptr, s.tok, s.cur - s.tok); ptr += (s.cur - s.tok); *outquery_len += (s.cur - s.tok); } else if(t == PDO_PARSER_BIND) { if(!params) { /* error */ efree(*outquery); *outquery = NULL; return (int) (s.cur - inquery); } /* lookup bind first via hash and then index */ /* stupid keys need to be null-terminated, even though we know their length */ if((NULL != (param = zend_hash_str_find_ptr(params, s.tok, s.cur-s.tok)) || NULL != (params = zend_hash_index_find_ptr(params, bindno))) { char *quotedstr; int quotedstrlen; /* restore the in-string key, doesn't need null-termination here */ /* currently everything is a string here */ /* quote the bind value if necessary */ if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), Z_STRLEN_P(param->parameter), "edstr, "edstrlen)) { memcpy(ptr, quotedstr, quotedstrlen); ptr += quotedstrlen; *outquery_len += quotedstrlen; efree(quotedstr); } else { memcpy(ptr, Z_STRVAL_P(param->parameter), Z_STRLEN_P(param->parameter)); ptr += Z_STRLEN_P(param->parameter); *outquery_len += (Z_STRLEN_P(param->parameter)); } } else { /* error and cleanup */ efree(*outquery); *outquery = NULL; return (int) (s.cur - inquery); } bindno++; }
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; }
U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, HashTable *args, UChar **formatted, int32_t *formatted_len) { int arg_count = zend_hash_num_elements(args); std::vector<Formattable> fargs; std::vector<UnicodeString> farg_names; MessageFormat *mf = (MessageFormat *)mfo->mf_data.umsgf; HashTable *types; intl_error& err = INTL_DATA_ERROR(mfo); if (U_FAILURE(err.code)) { return; } types = umsg_get_types(mfo, err); umsg_set_timezone(mfo, err); fargs.resize(arg_count); farg_names.resize(arg_count); int argNum = 0; zval *elem; // Key related variables zend_string *str_index; zend_ulong num_index; ZEND_HASH_FOREACH_KEY_VAL(args, num_index, str_index, elem) { Formattable& formattable = fargs[argNum]; UnicodeString& key = farg_names[argNum]; Formattable::Type argType = Formattable::kObject, //unknown *storedArgType = NULL; if (!U_SUCCESS(err.code)) { break; } /* Process key and retrieve type */ if (str_index == NULL) { /* includes case where index < 0 because it's exposed as unsigned */ if (num_index > (zend_ulong)INT32_MAX) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found negative or too large array key", 0); continue; } UChar temp[16]; int32_t len = u_sprintf(temp, "%u", (uint32_t)num_index); key.append(temp, len); storedArgType = (Formattable::Type*)zend_hash_index_find_ptr(types, (zend_ulong)num_index); } else { //string; assumed to be in UTF-8 intl_stringFromChar(key, ZSTR_VAL(str_index), ZSTR_LEN(str_index), &err.code); if (U_FAILURE(err.code)) { char *message; spprintf(&message, 0, "Invalid UTF-8 data in argument key: '%s'", ZSTR_VAL(str_index)); intl_errors_set(&err, err.code, message, 1); efree(message); continue; } storedArgType = (Formattable::Type*)zend_hash_str_find_ptr(types, (char*)key.getBuffer(), key.length()); } if (storedArgType != NULL) { argType = *storedArgType; } /* Convert zval to formattable according to message format type * or (as a fallback) the zval type */ if (argType != Formattable::kObject) { switch (argType) { case Formattable::kString: { string_arg: /* This implicitly converts objects * Note that our vectors will leak if object conversion fails * and PHP ends up with a fatal error and calls longjmp * as a result of that. */ convert_to_string_ex(elem); UnicodeString *text = new UnicodeString(); intl_stringFromChar(*text, Z_STRVAL_P(elem), Z_STRLEN_P(elem), &err.code); if (U_FAILURE(err.code)) { char *message; spprintf(&message, 0, "Invalid UTF-8 data in string argument: " "'%s'", Z_STRVAL_P(elem)); intl_errors_set(&err, err.code, message, 1); efree(message); delete text; continue; } formattable.adoptString(text); break; } case Formattable::kDouble: { double d; if (Z_TYPE_P(elem) == IS_DOUBLE) { d = Z_DVAL_P(elem); } else if (Z_TYPE_P(elem) == IS_LONG) { d = (double)Z_LVAL_P(elem); } else { SEPARATE_ZVAL_IF_NOT_REF(elem); convert_scalar_to_number(elem); d = (Z_TYPE_P(elem) == IS_DOUBLE) ? Z_DVAL_P(elem) : (double)Z_LVAL_P(elem); } formattable.setDouble(d); break; } case Formattable::kLong: { int32_t tInt32 = 0; retry_klong: if (Z_TYPE_P(elem) == IS_DOUBLE) { if (Z_DVAL_P(elem) > (double)INT32_MAX || Z_DVAL_P(elem) < (double)INT32_MIN) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found PHP float with absolute value too large for " "32 bit integer argument", 0); } else { tInt32 = (int32_t)Z_DVAL_P(elem); } } else if (Z_TYPE_P(elem) == IS_LONG) { if (Z_LVAL_P(elem) > INT32_MAX || Z_LVAL_P(elem) < INT32_MIN) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found PHP integer with absolute value too large " "for 32 bit integer argument", 0); } else { tInt32 = (int32_t)Z_LVAL_P(elem); } } else { SEPARATE_ZVAL_IF_NOT_REF(elem); convert_scalar_to_number(elem); goto retry_klong; } formattable.setLong(tInt32); break; } case Formattable::kInt64: { int64_t tInt64 = 0; retry_kint64: if (Z_TYPE_P(elem) == IS_DOUBLE) { if (Z_DVAL_P(elem) > (double)U_INT64_MAX || Z_DVAL_P(elem) < (double)U_INT64_MIN) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found PHP float with absolute value too large for " "64 bit integer argument", 0); } else { tInt64 = (int64_t)Z_DVAL_P(elem); } } else if (Z_TYPE_P(elem) == IS_LONG) { /* assume long is not wider than 64 bits */ tInt64 = (int64_t)Z_LVAL_P(elem); } else { SEPARATE_ZVAL_IF_NOT_REF(elem); convert_scalar_to_number(elem); goto retry_kint64; } formattable.setInt64(tInt64); break; } case Formattable::kDate: { double dd = intl_zval_to_millis(elem, &err, "msgfmt_format"); if (U_FAILURE(err.code)) { char *message; zend_string *u8key; UErrorCode status = UErrorCode(); u8key = intl_charFromString(key, &status); if (u8key) { spprintf(&message, 0, "The argument for key '%s' " "cannot be used as a date or time", ZSTR_VAL(u8key)); intl_errors_set(&err, err.code, message, 1); zend_string_release(u8key); efree(message); } continue; } formattable.setDate(dd); break; } default: intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found unsupported argument type", 0); break; } } else { /* We couldn't find any information about the argument in the pattern, this * means it's an extra argument. So convert it to a number if it's a number or * bool or null and to a string if it's anything else except arrays . */ switch (Z_TYPE_P(elem)) { case IS_DOUBLE: formattable.setDouble(Z_DVAL_P(elem)); break; case IS_TRUE: case IS_FALSE: convert_to_long_ex(elem); /* Intentional fallthrough */ case IS_LONG: formattable.setInt64((int64_t)Z_LVAL_P(elem)); break; case IS_NULL: formattable.setInt64((int64_t)0); break; case IS_STRING: case IS_OBJECT: goto string_arg; default: { char *message; zend_string *u8key; UErrorCode status = UErrorCode(); u8key = intl_charFromString(key, &status); if (u8key) { spprintf(&message, 0, "No strategy to convert the " "value given for the argument with key '%s' " "is available", ZSTR_VAL(u8key)); intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, message, 1); zend_string_release(u8key); efree(message); } } } } argNum++; } ZEND_HASH_FOREACH_END(); // visiting each argument
static HashTable *umsg_parse_format(MessageFormatter_object *mfo, const MessagePattern& mp, intl_error& err) { HashTable *ret; int32_t parts_count; if (U_FAILURE(err.code)) { return NULL; } if (!((MessageFormat *)mfo->mf_data.umsgf)->usesNamedArguments()) { return umsg_get_numeric_types(mfo, err); } if (mfo->mf_data.arg_types) { /* already cached */ return mfo->mf_data.arg_types; } /* Hash table will store Formattable::Type objects directly, * so no need for destructor */ ALLOC_HASHTABLE(ret); zend_hash_init(ret, 32, NULL, arg_types_dtor, 0); parts_count = mp.countParts(); // See MessageFormat::cacheExplicitFormats() /* * Looking through the pattern, go to each arg_start part type. * The arg-typeof that tells us the argument type (simple, complicated) * then the next part is either the arg_name or arg number * and then if it's simple after that there could be a part-type=arg-type * while substring will tell us number, spellout, etc. * If the next thing isn't an arg-type then assume string. */ /* The last two "parts" can at most be ARG_LIMIT and MSG_LIMIT * which we need not examine. */ for (int32_t i = 0; i < parts_count - 2 && U_SUCCESS(err.code); i++) { MessagePattern::Part p = mp.getPart(i); if (p.getType() != UMSGPAT_PART_TYPE_ARG_START) { continue; } MessagePattern::Part name_part = mp.getPart(++i); /* Getting name, advancing i */ Formattable::Type type, *storedType; if (name_part.getType() == UMSGPAT_PART_TYPE_ARG_NAME) { UnicodeString argName = mp.getSubstring(name_part); if ((storedType = (Formattable::Type*)zend_hash_str_find_ptr(ret, (char*)argName.getBuffer(), argName.length())) == NULL) { /* not found already; create new entry in HT */ Formattable::Type bogusType = Formattable::kObject; if ((storedType = (Formattable::Type*)zend_hash_str_update_mem(ret, (char*)argName.getBuffer(), argName.length(), (void*)&bogusType, sizeof(bogusType))) == NULL) { intl_errors_set(&err, U_MEMORY_ALLOCATION_ERROR, "Write to argument types hash table failed", 0); continue; } } } else if (name_part.getType() == UMSGPAT_PART_TYPE_ARG_NUMBER) { int32_t argNumber = name_part.getValue(); if (argNumber < 0) { intl_errors_set(&err, U_INVALID_FORMAT_ERROR, "Found part with negative number", 0); continue; } if ((storedType = (Formattable::Type*)zend_hash_index_find_ptr(ret, (zend_ulong)argNumber)) == NULL) { /* not found already; create new entry in HT */ Formattable::Type bogusType = Formattable::kObject; if ((storedType = (Formattable::Type*)zend_hash_index_update_mem(ret, (zend_ulong)argNumber, (void*)&bogusType, sizeof(bogusType))) == NULL) { intl_errors_set(&err, U_MEMORY_ALLOCATION_ERROR, "Write to argument types hash table failed", 0); continue; } } } else { intl_errors_set(&err, U_INVALID_FORMAT_ERROR, "Invalid part type encountered", 0); continue; } UMessagePatternArgType argType = p.getArgType(); /* No type specified, treat it as a string */ if (argType == UMSGPAT_ARG_TYPE_NONE) { type = Formattable::kString; } else { /* Some type was specified, might be simple or complicated */ if (argType == UMSGPAT_ARG_TYPE_SIMPLE) { /* For a SIMPLE arg, after the name part, there should be * an ARG_TYPE part whose string value tells us what to do */ MessagePattern::Part type_part = mp.getPart(++i); /* Getting type, advancing i */ if (type_part.getType() == UMSGPAT_PART_TYPE_ARG_TYPE) { UnicodeString typeString = mp.getSubstring(type_part); /* This is all based on the rules in the docs for MessageFormat * @see http://icu-project.org/apiref/icu4c/classMessageFormat.html */ if (typeString == "number") { MessagePattern::Part style_part = mp.getPart(i + 1); /* Not advancing i */ if (style_part.getType() == UMSGPAT_PART_TYPE_ARG_STYLE) { UnicodeString styleString = mp.getSubstring(style_part); if (styleString == "integer") { type = Formattable::kInt64; } else if (styleString == "currency") { type = Formattable::kDouble; } else if (styleString == "percent") { type = Formattable::kDouble; } else { /* some style invalid/unknown to us */ type = Formattable::kDouble; } } else { // if missing style, part, make it a double type = Formattable::kDouble; } } else if ((typeString == "date") || (typeString == "time")) { type = Formattable::kDate; } else if ((typeString == "spellout") || (typeString == "ordinal") || (typeString == "duration")) { type = Formattable::kDouble; } } else { /* If there's no UMSGPAT_PART_TYPE_ARG_TYPE right after a * UMSGPAT_ARG_TYPE_SIMPLE argument, then the pattern * is broken. */ intl_errors_set(&err, U_PARSE_ERROR, "Expected UMSGPAT_PART_TYPE_ARG_TYPE part following " "UMSGPAT_ARG_TYPE_SIMPLE part", 0); continue; } } else if (argType == UMSGPAT_ARG_TYPE_PLURAL) { type = Formattable::kDouble; } else if (argType == UMSGPAT_ARG_TYPE_CHOICE) { type = Formattable::kDouble; } else if (argType == UMSGPAT_ARG_TYPE_SELECT) { type = Formattable::kString; } else { type = Formattable::kString; } } /* was type specified? */ /* We found a different type for the same arg! */ if (*storedType != Formattable::kObject && *storedType != type) { intl_errors_set(&err, U_ARGUMENT_TYPE_MISMATCH, "Inconsistent types declared for an argument", 0); continue; } *storedType = type; } /* visiting each part */ if (U_FAILURE(err.code)) { zend_hash_destroy(ret); efree(ret); return NULL; } mfo->mf_data.arg_types = ret; return ret; }
/* Must prevent duplicates ... if there are duplicates, replace new by old! */ static void phpdbg_add_watch_collision(phpdbg_watchpoint_t *watch) { phpdbg_watch_collision *cur; /* Check for either recursive or (simple and/or implicit) */ ZEND_ASSERT(((watch->flags & PHPDBG_WATCH_RECURSIVE) == 0) ^ ((watch->flags & (PHPDBG_WATCH_IMPLICIT | PHPDBG_WATCH_SIMPLE)) == 0)); if ((cur = zend_hash_index_find_ptr(&PHPDBG_G(watch_collisions), (zend_ulong) watch->addr.ref))) { phpdbg_watchpoint_t *old; int flags = 0; if ((old = zend_hash_find_ptr(&cur->watches, watch->str)) || (old = zend_hash_find_ptr(&cur->implicit_watches, watch->str))) { if (((old->flags ^ watch->flags) & (PHPDBG_WATCH_NORMAL|PHPDBG_WATCH_IMPLICIT)) == 0) { return; /* there was no change ... */ } flags = old->flags; if (flags & PHPDBG_WATCH_RECURSIVE) { if (!(watch->flags & PHPDBG_WATCH_RECURSIVE) && !--cur->refs) { phpdbg_delete_watchpoints_recursive(watch); } } if (flags & PHPDBG_WATCH_NORMAL) { zend_hash_del(&cur->watches, watch->str); if (zend_hash_num_elements(&cur->watches) > 0) { cur->watch = Z_PTR_P(zend_hash_get_current_data_ex(&cur->watches, NULL)); } else { cur->watch = Z_PTR_P(zend_hash_get_current_data_ex(&cur->implicit_watches, NULL)); } } if (flags & PHPDBG_WATCH_IMPLICIT) { zend_hash_del(&cur->implicit_watches, watch->str); } old->flags = watch->flags; phpdbg_free_watch(watch); efree(watch); watch = old; } if (watch->flags & PHPDBG_WATCH_RECURSIVE) { if (!(flags & PHPDBG_WATCH_RECURSIVE) && !cur->refs++) { phpdbg_create_recursive_zval_watch(watch->parent); } } } else { phpdbg_watch_collision coll; coll.refs = (watch->flags & PHPDBG_WATCH_RECURSIVE) != 0; coll.watch = watch; zend_hash_init(&coll.watches, 8, arghs, NULL, 0); zend_hash_init(&coll.implicit_watches, 8, ..., NULL, 0); cur = zend_hash_index_add_mem(&PHPDBG_G(watch_collisions), (zend_ulong) watch->addr.ref, &coll, sizeof(phpdbg_watch_collision)); phpdbg_store_watchpoint(cur->watch); phpdbg_activate_watchpoint(cur->watch); if (coll.refs) { phpdbg_create_recursive_zval_watch(watch->parent); } } if (watch->flags & PHPDBG_WATCH_NORMAL) { cur->watch = watch; zend_hash_add_ptr(&cur->watches, watch->str, watch->parent); } if (watch->flags & PHPDBG_WATCH_IMPLICIT) { zend_hash_add_ptr(&cur->implicit_watches, watch->str, watch->parent); } }
static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, uint32_t type, HashTable *vars) /* {{{ */ { char *decode = NULL; switch (type &~ EXT_TYPE_UNUSED) { case IS_CV: { zend_string *var = ops->vars[EX_VAR_TO_NUM(op->var)]; asprintf(&decode, "$%.*s%c", var->len <= 19 ? (int) var->len : 18, var->val, var->len <= 19 ? 0 : '+'); } break; case IS_VAR: case IS_TMP_VAR: { zend_ulong id = 0, *pid = NULL; if (vars != NULL) { if ((pid = zend_hash_index_find_ptr(vars, (zend_ulong) ops->vars - op->var))) { id = *pid; } else { id = zend_hash_num_elements(vars); zend_hash_index_update_mem(vars, (zend_ulong) ops->vars - op->var, &id, sizeof(zend_ulong)); } } asprintf(&decode, "@" ZEND_ULONG_FMT, id); } break; case IS_CONST: { zval *literal = RT_CONSTANT(ops, *op); switch (Z_TYPE_P(literal)) { case IS_UNDEF: decode = zend_strndup("", 0); break; case IS_NULL: decode = zend_strndup(ZEND_STRL("null")); break; case IS_FALSE: decode = zend_strndup(ZEND_STRL("false")); break; case IS_TRUE: decode = zend_strndup(ZEND_STRL("true")); break; case IS_LONG: asprintf(&decode, "%lld", Z_LVAL_P(literal)); break; case IS_DOUBLE: asprintf(&decode, "%.*G", 14, Z_DVAL_P(literal)); break; case IS_STRING: { int i; zend_string *str = php_addcslashes(Z_STR_P(literal), 0, "\\\"", 2); for (i = 0; i < str->len; i++) { if (str->val[i] < 32) { str->val[i] = ' '; } } asprintf(&decode, "\"%.*s\"%c", str->len <= 18 ? (int) str->len : 17, str->val, str->len <= 18 ? 0 : '+'); zend_string_release(str); } break; case IS_RESOURCE: asprintf(&decode, "Rsrc #%d", Z_RES_HANDLE_P(literal)); break; case IS_ARRAY: asprintf(&decode, "array(%d)", zend_hash_num_elements(Z_ARR_P(literal))); break; case IS_OBJECT: { zend_string *str = Z_OBJCE_P(literal)->name; asprintf(&decode, "%.*s%c", str->len <= 18 ? (int) str->len : 18, str->val, str->len <= 18 ? 0 : '+'); } break; case IS_CONSTANT: decode = zend_strndup(ZEND_STRL("<constant>")); break; case IS_CONSTANT_AST: decode = zend_strndup(ZEND_STRL("<ast>")); break; default: asprintf(&decode, "unknown type: %d", Z_TYPE_P(literal)); break; } } break; case IS_UNUSED: asprintf(&decode, "<unused>"); break; } return decode; } /* }}} */