/* {{{ _php_regcomp */ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags) { int r = 0; int patlen = strlen(pattern); reg_cache *rc = NULL; if (zend_hash_num_elements(&EREG(ht_rc)) >= EREG_CACHE_SIZE) { /* easier than dealing with overflow as it happens */ if (EREG(lru_counter) >= (1 << 31) || zend_hash_sort(&EREG(ht_rc), zend_qsort, ereg_lru_cmp, 0) == FAILURE) { zend_hash_clean(&EREG(ht_rc)); EREG(lru_counter) = 0; } else { int num_clean = EREG_CACHE_SIZE / 4; zend_hash_apply_with_argument(&EREG(ht_rc), ereg_clean_cache, &num_clean); } } rc = zend_hash_str_find_ptr(&EREG(ht_rc), pattern, patlen); if (rc && rc->cflags == cflags) { #ifdef HAVE_REGEX_T_RE_MAGIC /* * We use a saved magic number to see whether cache is corrupted, and if it * is, we flush it and compile the pattern from scratch. */ if (rc->preg.re_magic != reg_magic) { zend_hash_clean(&EREG(ht_rc)); EREG(lru_counter) = 0; } else { memcpy(preg, &rc->preg, sizeof(*preg)); return r; } } r = regcomp(preg, pattern, cflags); if(!r) { reg_cache rcp; rcp.cflags = cflags; rcp.lastuse = ++(EREG(lru_counter)); memcpy(&rcp.preg, preg, sizeof(*preg)); /* * Since we don't have access to the actual MAGIC1 definition in the private * header file, we save the magic value immediately after compilation. Hopefully, * it's good. */ if (!reg_magic) reg_magic = preg->re_magic; zend_hash_str_update_mem(&EREG(ht_rc), pattern, patlen, &rcp, sizeof(rcp)); } #else memcpy(preg, &rc->preg, sizeof(*preg)); } else {
static int timecop_func_override() { const struct timecop_override_func_entry *p; zend_function *zf_orig, *zf_ovrd, *zf_save; p = &(timecop_override_func_table[0]); while (p->orig_func != NULL) { zf_orig = zend_hash_str_find_ptr(EG(function_table), p->orig_func, strlen(p->orig_func)); if (zf_orig == NULL) { // Do nothing. Because some functions are introduced by optional extensions. p++; continue; } zf_ovrd = zend_hash_str_find_ptr(EG(function_table), p->ovrd_func, strlen(p->ovrd_func)); if (zf_ovrd == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find function %s.", p->ovrd_func); p++; continue; } zf_save = zend_hash_str_find_ptr(EG(function_table), p->save_func, strlen(p->save_func)); if (zf_save != NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't create function %s because already exists.", p->save_func); p++; continue; } TIMECOP_ASSERT(zf_orig->type == ZEND_INTERNAL_FUNCTION); TIMECOP_ASSERT(zf_ovrd->type == ZEND_INTERNAL_FUNCTION); zend_hash_str_add_mem(EG(function_table), p->save_func, strlen(p->save_func), zf_orig, sizeof(zend_internal_function)); function_add_ref(zf_orig); zend_hash_str_update_mem(EG(function_table), p->orig_func, strlen(p->orig_func), zf_ovrd, sizeof(zend_internal_function)); function_add_ref(zf_ovrd); p++; } return SUCCESS; }
static int timecop_class_override_clear() { const struct timecop_override_class_entry *p; zend_class_entry *ce_orig; zend_function *zf_orig, *zf_ovrd, *zf_save; p = &(timecop_override_class_table[0]); while (p->orig_class != NULL) { ce_orig = zend_hash_str_find_ptr(EG(class_table), p->orig_class, strlen(p->orig_class)); if (ce_orig == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find class %s.", p->orig_class); p++; continue; } zf_orig = zend_hash_str_find_ptr(&ce_orig->function_table, p->save_method, strlen(p->save_method)); if (zf_orig == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find method %s::%s.", p->orig_class, p->save_method); p++; continue; } zend_hash_str_update_mem(&ce_orig->function_table, p->orig_method, strlen(p->orig_method), zf_orig, sizeof(zend_internal_function)); function_add_ref(zf_orig); zend_hash_str_del(&ce_orig->function_table, p->save_method, strlen(p->save_method)); if (strcmp(p->orig_method, "__construct") == 0) { ce_orig->constructor = zf_orig; } p++; } return SUCCESS; }
/* clear overrideed function. */ static int timecop_func_override_clear() { const struct timecop_override_func_entry *p; zend_function *zf_orig; p = &(timecop_override_func_table[0]); while (p->orig_func != NULL) { zf_orig = zend_hash_str_find_ptr(EG(function_table), p->save_func, strlen(p->save_func)); if (zf_orig == NULL) { p++; continue; } zend_hash_str_update_mem(EG(function_table), p->orig_func, strlen(p->orig_func), zf_orig, sizeof(zend_internal_function)); function_add_ref(zf_orig); zend_hash_str_del(EG(function_table), p->save_func, strlen(p->save_func)); p++; } return SUCCESS; }
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; }
/* {{{ 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 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; }
static int LoadDirectory(HashTable *directories, HKEY key, char *path, int path_len, HashTable *parent_ht) { DWORD keys, values, max_key, max_name, max_value; int ret = 0; HashTable *ht = NULL; if (RegQueryInfoKey(key, NULL, NULL, NULL, &keys, &max_key, NULL, &values, &max_name, &max_value, NULL, NULL) == ERROR_SUCCESS) { if (values) { DWORD i; char *name = (char*)emalloc(max_name+1); char *value = (char*)emalloc(max_value+1); DWORD name_len, type, value_len; for (i = 0; i < values; i++) { name_len = max_name+1; value_len = max_value+1; memset(name, '\0', max_name+1); memset(value, '\0', max_value+1); if (RegEnumValue(key, i, name, &name_len, NULL, &type, value, &value_len) == ERROR_SUCCESS) { if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) { zval data; if (!ht) { ht = (HashTable*)malloc(sizeof(HashTable)); if (!ht) { return ret; } zend_hash_init(ht, 0, NULL, ZVAL_INTERNAL_PTR_DTOR, 1); } ZVAL_PSTRINGL(&data, value, value_len-1); zend_hash_str_update(ht, name, name_len, &data); } } } if (ht) { if (parent_ht) { zend_string *index; zend_ulong num; zval *tmpdata; ZEND_HASH_FOREACH_KEY_VAL(parent_ht, num, index, tmpdata) { zend_hash_add(ht, index, tmpdata); } ZEND_HASH_FOREACH_END(); } zend_hash_str_update_mem(directories, path, path_len, ht, sizeof(HashTable)); ret = 1; } efree(name); efree(value); } if (ht == NULL) { ht = parent_ht; } if (keys) { DWORD i; char *name = (char*)emalloc(max_key+1); char *new_path = (char*)emalloc(path_len+max_key+2); DWORD name_len; FILETIME t; HKEY subkey; for (i = 0; i < keys; i++) { name_len = max_key+1; if (RegEnumKeyEx(key, i, name, &name_len, NULL, NULL, NULL, &t) == ERROR_SUCCESS) { if (RegOpenKeyEx(key, name, 0, KEY_READ, &subkey) == ERROR_SUCCESS) { if (path_len) { memcpy(new_path, path, path_len); new_path[path_len] = '/'; memcpy(new_path+path_len+1, name, name_len+1); zend_str_tolower(new_path, path_len+name_len+1); name_len += path_len+1; } else { memcpy(new_path, name, name_len+1); zend_str_tolower(new_path, name_len); } if (LoadDirectory(directories, subkey, new_path, name_len, ht)) { ret = 1; } RegCloseKey(subkey); } } } efree(new_path); efree(name); } }
YRMCDS_METHOD(Client, __construct) { char* node; size_t node_len; long port = 11211; char* persist_id = NULL; size_t persist_id_len = 0; char* prefix = NULL; size_t prefix_len = 0; zval* objptr = getThis(); if( ! objptr ) { php_error(E_ERROR, "Constructor called statically!"); RETURN_FALSE; } if( zend_parse_parameters(ZEND_NUM_ARGS(), "s|ls!s!", &node, &node_len, &port, &persist_id, &persist_id_len, &prefix, &prefix_len) == FAILURE ) { php_error(E_ERROR, "Invalid argument"); RETURN_FALSE; } yrmcds_client_object* obj = YRMCDS_CLIENT_OBJECT_P(objptr); if( persist_id_len > 0 ) { size_t hash_key_len = 7 + persist_id_len; char* hash_key = alloca(hash_key_len); memcpy(hash_key, "yrmcds:", 7); memcpy(hash_key+7, persist_id, persist_id_len); yrmcds_error err = YRMCDS_OK; yrmcds_status status = YRMCDS_STATUS_OK; uepc_status s = use_existing_persistent_connection( hash_key, hash_key_len, &obj->conn, &err, &status); if( s == UEPC_BROKEN_AND_OCCUPIED ) { // Since the persistent connection is broken and used by other client, // we cannot destruct the connection. // Therefore, we throw exception and return. CHECK_YRMCDS(err); zend_throw_exception_ex(ce_yrmcds_error, PHP_YRMCDS_UNEXPECTED_RESPONSE, "yrmcds: unexpected response (%d)", status); RETURN_FALSE; } if( s == UEPC_NOT_FOUND || s == UEPC_BROKEN ) { // There are no persistent connections with the given ID, or // there is a broken persistent connection with the given ID and // no one use it. // Therefore, we create new persistent connection with the given ID. php_yrmcds_t* c = pemalloc(sizeof(php_yrmcds_t), 1); c->pkey = pemalloc(hash_key_len, 1); c->pkey_len = hash_key_len; memcpy(c->pkey, hash_key, hash_key_len); c->reference_count = 1; CHECK_YRMCDS( yrmcds_connect(&c->res, node, (uint16_t)port) ); CHECK_YRMCDS( yrmcds_set_compression( &c->res, (size_t)YRMCDS_G(compression_threshold)) ); CHECK_YRMCDS( yrmcds_set_timeout( &c->res, (int)YRMCDS_G(default_timeout)) ); obj->conn = c; zend_resource le; le.type = le_yrmcds; le.ptr = c; GC_REFCOUNT(&le) = 1; zend_hash_str_update_mem(&EG(persistent_list), hash_key, hash_key_len, &le, sizeof(le)); // There is no need to free the return value of the above function // as plist_entry_destructor defined in Zend/zend_list.c does // it automatically. } // If s == UEPC_OK, we can use the returned presistent connection. } else { php_yrmcds_t* c = ecalloc(1, sizeof(php_yrmcds_t)); c->reference_count = 1; CHECK_YRMCDS( yrmcds_connect(&c->res, node, (uint16_t)port) ); CHECK_YRMCDS( yrmcds_set_compression( &c->res, (size_t)YRMCDS_G(compression_threshold)) ); CHECK_YRMCDS( yrmcds_set_timeout( &c->res, (int)YRMCDS_G(default_timeout)) ); obj->conn = c; } if( prefix_len > 0 ) obj->prefix = zend_string_init(prefix, prefix_len, 0); }
static int timecop_class_override() { const struct timecop_override_class_entry *p; zend_class_entry *ce_orig, *ce_ovrd; zend_function *zf_orig, *zf_ovrd, *zf_save, *zf_new; p = &(timecop_override_class_table[0]); while (p->orig_class != NULL) { ce_orig = zend_hash_str_find_ptr(EG(class_table), p->orig_class, strlen(p->orig_class)); if (ce_orig == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find class %s.", p->orig_class); p++; continue; } ce_ovrd = zend_hash_str_find_ptr(EG(class_table), p->ovrd_class, strlen(p->ovrd_class)); if (ce_ovrd == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find class %s.", p->ovrd_class); p++; continue; } zf_orig = zend_hash_str_find_ptr(&ce_orig->function_table, p->orig_method, strlen(p->orig_method)); if (zf_orig == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find method %s::%s.", p->orig_class, p->orig_method); p++; continue; } zf_ovrd = zend_hash_str_find_ptr(&ce_ovrd->function_table, p->orig_method, strlen(p->orig_method)); if (zf_ovrd == NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't find method %s::%s.", p->ovrd_class, p->orig_method); p++; continue; } zf_save = zend_hash_str_find_ptr(&ce_orig->function_table, p->save_method, strlen(p->save_method)); if (zf_save != NULL) { php_error_docref("https://github.com/hnw/php-timecop", E_WARNING, "timecop couldn't create method %s::%s because already exists.", p->orig_class, p->save_method); p++; continue; } TIMECOP_ASSERT(zf_orig->type == ZEND_INTERNAL_FUNCTION); TIMECOP_ASSERT(ce_orig->type & ZEND_INTERNAL_CLASS); TIMECOP_ASSERT(zf_ovrd->type == ZEND_INTERNAL_FUNCTION); TIMECOP_ASSERT(ce_ovrd->type & ZEND_INTERNAL_CLASS); zend_hash_str_add_mem(&ce_orig->function_table, p->save_method, strlen(p->save_method), zf_orig, sizeof(zend_internal_function)); function_add_ref(zf_orig); zf_new = zend_hash_str_update_mem(&ce_orig->function_table, p->orig_method, strlen(p->orig_method), zf_ovrd, sizeof(zend_internal_function)); function_add_ref(zf_ovrd); TIMECOP_ASSERT(zf_new != NULL); TIMECOP_ASSERT(zf_new != zf_orig); if (strcmp(p->orig_method, "__construct") == 0) { ce_orig->constructor = zf_new; } p++; } return SUCCESS; }
void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_connect, zend_bool in_ctor) /* {{{ */ { MY_MYSQL *mysql = NULL; MYSQLI_RESOURCE *mysqli_resource = NULL; zval *object = getThis(); char *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL; size_t hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0; zend_bool persistent = FALSE; zend_long port = 0, flags = 0; zend_string *hash_key = NULL; zend_bool new_connection = FALSE; zend_resource *le; mysqli_plist_entry *plist = NULL; zend_bool self_alloced = 0; #if !defined(MYSQL_USE_MYSQLND) if ((MYSQL_VERSION_ID / 100) != (mysql_get_client_version() / 100)) { php_error_docref(NULL, E_WARNING, "Headers and client library minor version mismatch. Headers:%d Library:%ld", MYSQL_VERSION_ID, mysql_get_client_version()); } #endif if (getThis() && !ZEND_NUM_ARGS() && in_ctor) { php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, in_ctor); return; } hostname = username = dbname = passwd = socket = NULL; if (!is_real_connect) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ssssls", &hostname, &hostname_len, &username, &username_len, &passwd, &passwd_len, &dbname, &dbname_len, &port, &socket, &socket_len) == FAILURE) { return; } if (object && instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry)) { mysqli_resource = (Z_MYSQLI_P(object))->ptr; if (mysqli_resource && mysqli_resource->ptr) { mysql = (MY_MYSQL*) mysqli_resource->ptr; } } if (!mysql) { mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL)); self_alloced = 1; } flags |= CLIENT_MULTI_RESULTS; /* needed for mysql_multi_query() */ } else { /* We have flags too */ if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|sssslsl", &object, mysqli_link_class_entry, &hostname, &hostname_len, &username, &username_len, &passwd, &passwd_len, &dbname, &dbname_len, &port, &socket, &socket_len, &flags) == FAILURE) { return; } mysqli_resource = (Z_MYSQLI_P(object))->ptr; MYSQLI_FETCH_RESOURCE_CONN(mysql, object, MYSQLI_STATUS_INITIALIZED); /* set some required options */ flags |= CLIENT_MULTI_RESULTS; /* needed for mysql_multi_query() */ /* remove some insecure options */ flags &= ~CLIENT_MULTI_STATEMENTS; /* don't allow multi_queries via connect parameter */ #if !defined(MYSQLI_USE_MYSQLND) if (PG(open_basedir) && PG(open_basedir)[0] != '\0') { flags &= ~CLIENT_LOCAL_FILES; } #endif } if (!socket_len || !socket) { socket = MyG(default_socket); } if (!port){ port = MyG(default_port); } if (!passwd) { passwd = MyG(default_pw); passwd_len = strlen(SAFE_STR(passwd)); } if (!username){ username = MyG(default_user); } if (!hostname || !hostname_len) { hostname = MyG(default_host); } if (mysql->mysql && mysqli_resource && (mysqli_resource->status > MYSQLI_STATUS_INITIALIZED)) { /* already connected, we should close the connection */ php_mysqli_close(mysql, MYSQLI_CLOSE_IMPLICIT, mysqli_resource->status); } if (strlen(SAFE_STR(hostname)) > 2 && !strncasecmp(hostname, "p:", 2)) { hostname += 2; if (!MyG(allow_persistent)) { php_error_docref(NULL, E_WARNING, "Persistent connections are disabled. Downgrading to normal"); } else { mysql->persistent = persistent = TRUE; hash_key = strpprintf(0, "mysqli_%s_%s" ZEND_LONG_FMT "%s%s%s", SAFE_STR(hostname), SAFE_STR(socket), port, SAFE_STR(username), SAFE_STR(dbname), SAFE_STR(passwd)); mysql->hash_key = hash_key; /* check if we can reuse exisiting connection ... */ if ((le = zend_hash_find_ptr(&EG(persistent_list), hash_key)) != NULL) { if (le->type == php_le_pmysqli()) { plist = (mysqli_plist_entry *) le->ptr; do { if (zend_ptr_stack_num_elements(&plist->free_links)) { mysql->mysql = zend_ptr_stack_pop(&plist->free_links); MyG(num_inactive_persistent)--; /* reset variables */ #ifndef MYSQLI_NO_CHANGE_USER_ON_PCONNECT if (!mysqli_change_user_silent(mysql->mysql, username, passwd, dbname, passwd_len)) { #else if (!mysql_ping(mysql->mysql)) { #endif #ifdef MYSQLI_USE_MYSQLND mysqlnd_restart_psession(mysql->mysql); #endif MyG(num_active_persistent)++; /* clear error */ php_mysqli_set_error(mysql_errno(mysql->mysql), (char *) mysql_error(mysql->mysql)); goto end; } else { mysqli_close(mysql->mysql, MYSQLI_CLOSE_IMPLICIT); mysql->mysql = NULL; } } } while (0); } } else { zend_resource le; le.type = php_le_pmysqli(); le.ptr = plist = calloc(1, sizeof(mysqli_plist_entry)); zend_ptr_stack_init_ex(&plist->free_links, 1); zend_hash_str_update_mem(&EG(persistent_list), ZSTR_VAL(hash_key), ZSTR_LEN(hash_key), &le, sizeof(le)); } }