コード例 #1
0
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_ADD_INTERFACE:
				case ZEND_ADD_TRAIT:
				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 {
							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:
				case ZEND_DECLARE_INHERITED_CLASS:
				case ZEND_DECLARE_INHERITED_CLASS_DELAYED:
					LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 2);
					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) {
				/* unsed 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 ((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++;
					}
					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_ADD_INTERFACE:
				case ZEND_ADD_TRAIT:
				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
	}
}
コード例 #2
0
ファイル: pass3.c プロジェクト: jpauli/php-src
void zend_optimizer_pass3(zend_op_array *op_array)
{
	zend_op *opline;
	zend_op *end = op_array->opcodes + op_array->last;
	zend_op **jmp_hitlist;
	int jmp_hitlist_count;
	int i;
	uint32_t opline_num = 0;
	ALLOCA_FLAG(use_heap);

	jmp_hitlist = (zend_op**)do_alloca(sizeof(zend_op*)*op_array->last, use_heap);
	opline = op_array->opcodes;

	while (opline < end) {
		jmp_hitlist_count = 0;

		switch (opline->opcode) {
			case ZEND_ADD:
			case ZEND_SUB:
			case ZEND_MUL:
			case ZEND_DIV:
			case ZEND_MOD:
			case ZEND_POW:
			case ZEND_CONCAT:
			case ZEND_SL:
			case ZEND_SR:
			case ZEND_BW_OR:
			case ZEND_BW_AND:
			case ZEND_BW_XOR:
				{
					zend_op *next_opline = opline + 1;

					while (next_opline < end && next_opline->opcode == ZEND_NOP) {
						++next_opline;
					}

					if (next_opline >= end || next_opline->opcode != ZEND_ASSIGN) {
						break;
					}

					if ((ZEND_OP2_TYPE(opline) & (IS_VAR | IS_CV))
						&& ZEND_OP2(opline).var == ZEND_OP1(next_opline).var &&
						(opline->opcode == ZEND_ADD ||
						 opline->opcode == ZEND_MUL ||
						 opline->opcode == ZEND_BW_OR ||
						 opline->opcode == ZEND_BW_AND ||
						 opline->opcode == ZEND_BW_XOR)) {
						/* change $i=expr+$i to $i=$i+expr so that the next
						* optimization works on it
						*/
						zend_uchar tmp_type = opline->op1_type;
						znode_op tmp = opline->op1;

						if (opline->opcode != ZEND_ADD
								|| (ZEND_OP1_TYPE(opline) == IS_CONST
									&& Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_ARRAY)) {
							/* protection from array add: $a = array + $a is not commutative! */
							COPY_NODE(opline->op1, opline->op2);
							COPY_NODE(opline->op2, tmp);
						}
					}
					if ((ZEND_OP1_TYPE(opline) & (IS_VAR | IS_CV))
						&& ZEND_OP1(opline).var == ZEND_OP1(next_opline).var
						&& ZEND_OP1_TYPE(opline) == ZEND_OP1_TYPE(next_opline)) {
						switch (opline->opcode) {
							case ZEND_ADD:
								opline->opcode = ZEND_ASSIGN_ADD;
								break;
							case ZEND_SUB:
								opline->opcode = ZEND_ASSIGN_SUB;
								break;
							case ZEND_MUL:
								opline->opcode = ZEND_ASSIGN_MUL;
								break;
							case ZEND_DIV:
								opline->opcode = ZEND_ASSIGN_DIV;
								break;
							case ZEND_MOD:
								opline->opcode = ZEND_ASSIGN_MOD;
								break;
							case ZEND_POW:
								opline->opcode = ZEND_ASSIGN_POW;
								break;
							case ZEND_CONCAT:
								opline->opcode = ZEND_ASSIGN_CONCAT;
								break;
							case ZEND_SL:
								opline->opcode = ZEND_ASSIGN_SL;
								break;
							case ZEND_SR:
								opline->opcode = ZEND_ASSIGN_SR;
								break;
							case ZEND_BW_OR:
								opline->opcode = ZEND_ASSIGN_BW_OR;
								break;
							case ZEND_BW_AND:
								opline->opcode = ZEND_ASSIGN_BW_AND;
								break;
							case ZEND_BW_XOR:
								opline->opcode = ZEND_ASSIGN_BW_XOR;
								break;
						}
						COPY_NODE(opline->result, next_opline->result);
						MAKE_NOP(next_opline);
						opline++;
						opline_num++;
					}
				}
				break;

			case ZEND_JMP:
				if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
					break;
				}

				/* convert L: JMP L+1 to NOP */
				if (ZEND_OP1_JMP_ADDR(opline) == opline + 1) {
					MAKE_NOP(opline);
					goto done_jmp_optimization;
				}

				/* convert JMP L1 ... L1: JMP L2 to JMP L2 .. L1: JMP L2 */
				while (ZEND_OP1_JMP_ADDR(opline) < end
						&& ZEND_OP1_JMP_ADDR(opline)->opcode == ZEND_JMP) {
					zend_op *target = ZEND_OP1_JMP_ADDR(opline);
					CHECK_JMP(target, done_jmp_optimization);
					ZEND_SET_OP_JMP_ADDR(opline, opline->op1, ZEND_OP1_JMP_ADDR(target));
				}
				break;

			case ZEND_JMP_SET:
			case ZEND_COALESCE:
				if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
					break;
				}

				while (ZEND_OP2_JMP_ADDR(opline) < end) {
					zend_op *target = ZEND_OP2_JMP_ADDR(opline);
					if (target->opcode == ZEND_JMP) {
						ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(target));
					} else {
						break;
					}
				}
				break;
			case ZEND_JMPZ:
			case ZEND_JMPNZ:
				if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
					break;
				}

				while (ZEND_OP2_JMP_ADDR(opline) < end) {
					zend_op *target = ZEND_OP2_JMP_ADDR(opline);

					if (target->opcode == ZEND_JMP) {
						/* plain JMP */
						/* JMPZ(X,L1), L1: JMP(L2) => JMPZ(X,L2), L1: JMP(L2) */
						CHECK_JMP(target, done_jmp_optimization);
						ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(target));
					} else if (target->opcode == opline->opcode &&
					           SAME_VAR(opline->op1, target->op1)) {
						/* same opcode and same var as this opcode */
						/* JMPZ(X,L1), L1: JMPZ(X,L2) => JMPZ(X,L2), L1: JMPZ(X,L2) */
						CHECK_JMP2(target, done_jmp_optimization);
						ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
					} else if (target->opcode == opline->opcode + 3 &&
					           SAME_VAR(opline->op1, target->op1)) {
						/* convert JMPZ(X,L1), L1: T JMPZ_EX(X,L2) to
						   T = JMPZ_EX(X, L2) */
						ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
						opline->opcode += 3;
						COPY_NODE(opline->result, target->result);
						break;
					} else if (target->opcode == INV_COND(opline->opcode) &&
					           SAME_VAR(opline->op1, target->op1)) {
						/* convert JMPZ(X,L1), L1: JMPNZ(X,L2) to
						   JMPZ(X,L1+1) */
						ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
						break;
					} else if (target->opcode == INV_COND_EX(opline->opcode) &&
					           SAME_VAR(opline->op1, target->op1)) {
						/* convert JMPZ(X,L1), L1: T = JMPNZ_EX(X,L2) to
						   T = JMPZ_EX(X,L1+1) */
						ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
						opline->opcode += 3;
						COPY_NODE(opline->result, target->result);
						break;
					} else {
						break;
					}
				}
				break;

			case ZEND_JMPZ_EX:
			case ZEND_JMPNZ_EX: {
					zend_uchar T_type = opline->result_type;
					znode_op T = opline->result;

					if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
						break;
					}

					/* convert L: T = JMPZ_EX X,L+1 to T = BOOL(X) */
					/* convert L: T = JMPZ_EX T,L+1 to NOP */
					if (ZEND_OP2_JMP_ADDR(opline) == opline + 1) {
						if (ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
							MAKE_NOP(opline);
						} else {
							opline->opcode = ZEND_BOOL;
							SET_UNUSED(opline->op2);
						}
						goto done_jmp_optimization;
					}

					while (ZEND_OP2_JMP_ADDR(opline) < end) {
						zend_op *target = ZEND_OP2_JMP_ADDR(opline);

						if (SAME_OPCODE_EX(opline->opcode, target->opcode) &&
							SAME_VAR(target->op1, T)) {
							/* Check for JMPZ_EX to JMPZ[_EX] with the same condition, either with _EX or not */
							if (target->opcode == opline->opcode) {
								/* change T only if we have _EX opcode there */
								COPY_NODE(T, target->result);
							}
							CHECK_JMP2(target, continue_jmp_ex_optimization);
							ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
						} else if (target->opcode == ZEND_JMPZNZ &&
								  SAME_VAR(target->op1, T)) {
							/* Check for JMPZNZ with same cond variable */
							zend_op *new_target;

							CHECK_JMP2(target, continue_jmp_ex_optimization);
							if (opline->opcode == ZEND_JMPZ_EX) {
								new_target = ZEND_OP2_JMP_ADDR(target);
							} else {
								/* JMPNZ_EX */
								new_target = ZEND_OFFSET_TO_OPLINE(target, target->extended_value);
							}
							ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_target);
						} else if ((target->opcode == INV_EX_COND_EX(opline->opcode) ||
									target->opcode == INV_EX_COND(opline->opcode)) &&
									SAME_VAR(opline->op1, target->op1)) {
						   /* convert JMPZ_EX(X,L1), L1: JMPNZ_EX(X,L2) to
							  JMPZ_EX(X,L1+1) */
							ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
							break;
						} else if (target->opcode == ZEND_BOOL &&
						           SAME_VAR(opline->result, target->op1)) {
							/* convert Y = JMPZ_EX(X,L1), L1: Z = BOOL(Y) to
							   Z = JMPZ_EX(X,L1+1) */
							opline->result.var = target->result.var;
							ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
							break;
						} else {
							break;
						}
					} /* while */
continue_jmp_ex_optimization:
					break;
#if 0
					/* If Ti = JMPZ_EX(X, L) and Ti is not used, convert to JMPZ(X, L) */
					{
						zend_op *op;
						for(op = opline+1; op<end; op++) {
							if(ZEND_RESULT_TYPE(op) == IS_TMP_VAR &&
							   ZEND_RESULT(op).var == ZEND_RESULT(opline).var) {
								break; /* can pass to part 2 */
							}

							if(op->opcode == ZEND_JMP ||
							   op->opcode == ZEND_JMPZ ||
							   op->opcode == ZEND_JMPZ_EX ||
							   op->opcode == ZEND_JMPNZ ||
							   op->opcode == ZEND_JMPNZ_EX ||
							   op->opcode == ZEND_JMPZNZ ||
							   op->opcode == ZEND_CASE ||
							   op->opcode == ZEND_RETURN ||
							   op->opcode == ZEND_RETURN_BY_REF ||
							   op->opcode == ZEND_FAST_RET ||
							   op->opcode == ZEND_FE_FETCH_R ||
							   op->opcode == ZEND_FE_FETCH_RW ||
							   op->opcode == ZEND_EXIT) {
								break;
							}

							if(ZEND_OP1_TYPE(op) == IS_TMP_VAR &&
							   ZEND_OP1(op).var == ZEND_RESULT(opline).var) {
								goto done_jmp_optimization;
							}

							if(ZEND_OP2_TYPE(op) == IS_TMP_VAR &&
							   ZEND_OP2(op).var == ZEND_RESULT(opline).var) {
								goto done_jmp_optimization;
							}
						} /* for */

						for(op = &op_array->opcodes[ZEND_OP2(opline).opline_num]; op<end; op++) {

							if(ZEND_RESULT_TYPE(op) == IS_TMP_VAR &&
							   ZEND_RESULT(op).var == ZEND_RESULT(opline).var) {
								break; /* can pass to optimization */
							}

							if(op->opcode == ZEND_JMP ||
							   op->opcode == ZEND_JMPZ ||
							   op->opcode == ZEND_JMPZ_EX ||
							   op->opcode == ZEND_JMPNZ ||
							   op->opcode == ZEND_JMPNZ_EX ||
							   op->opcode == ZEND_JMPZNZ ||
							   op->opcode == ZEND_CASE ||
							   op->opcode == ZEND_RETURN ||
							   op->opcode == ZEND_RETURN_BY_REF ||
							   op->opcode == ZEND_FAST_RET ||
							   op->opcode == ZEND_FE_FETCH_R ||
							   op->opcode == ZEND_FE_FETCH_RW ||
							   op->opcode == ZEND_EXIT) {
								break;
							}

							if(ZEND_OP1_TYPE(op) == IS_TMP_VAR &&
							   ZEND_OP1(op).var == ZEND_RESULT(opline).var) {
								goto done_jmp_optimization;
							}

							if(ZEND_OP2_TYPE(op) == IS_TMP_VAR &&
							   ZEND_OP2(op).var == ZEND_RESULT(opline).var) {
								goto done_jmp_optimization;
							}
						}

						opline->opcode = opline->opcode-3; /* JMP_EX -> JMP */
						SET_UNUSED(opline->result);
						break;
					}
#endif
				}
				break;

			case ZEND_JMPZNZ:
				if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
					break;
				}

				/* JMPZNZ(X,L1,L2), L1: JMP(L3) => JMPZNZ(X,L3,L2), L1: JMP(L3) */
				while (ZEND_OP2_JMP_ADDR(opline) < end
						&& ZEND_OP2_JMP_ADDR(opline)->opcode == ZEND_JMP) {
					zend_op *target = ZEND_OP2_JMP_ADDR(opline);
					CHECK_JMP(target, continue_jmpznz_optimization);
					ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(target));
				}
continue_jmpznz_optimization:
				/* JMPZNZ(X,L1,L2), L2: JMP(L3) => JMPZNZ(X,L1,L3), L2: JMP(L3) */
				while (ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value) < end
						&& ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value)->opcode == ZEND_JMP) {
					zend_op *target = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
					CHECK_JMP(target, done_jmp_optimization);
					opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP1_JMP_ADDR(target));
				}
				break;

			case ZEND_POST_INC:
			case ZEND_POST_DEC: {
					/* POST_INC, FREE => PRE_INC */
					zend_op *next_op = opline + 1;

					if (next_op >= end) {
						break;
					}
					if (next_op->opcode == ZEND_FREE &&
						ZEND_OP1(next_op).var == ZEND_RESULT(opline).var) {
						MAKE_NOP(next_op);
						opline->opcode -= 2;
						ZEND_RESULT_TYPE(opline) = IS_UNUSED;
					}
				}
				break;
		}
done_jmp_optimization:
		opline++;
		opline_num++;
	}
	free_alloca(jmp_hitlist, use_heap);
}
コード例 #3
0
ファイル: tokenizer.c プロジェクト: AmesianX/php-src
static void tokenize(zval *return_value)
{
	zval token;
	zval keyword;
	int token_type;
	zend_bool destroy;
	int token_line = 1;
	int need_tokens = -1; // for __halt_compiler lexing. -1 = disabled

	array_init(return_value);

	ZVAL_NULL(&token);
	while ((token_type = lex_scan(&token))) {
		destroy = 1;
		switch (token_type) {
			case T_CLOSE_TAG:
				if (zendtext[zendleng - 1] != '>') {
					CG(zend_lineno)++;
				}
			case T_OPEN_TAG:
			case T_OPEN_TAG_WITH_ECHO:
			case T_WHITESPACE:
			case T_COMMENT:
			case T_DOC_COMMENT:
				destroy = 0;
				break;
		}

		if (token_type >= 256) {
			array_init(&keyword);
			add_next_index_long(&keyword, token_type);
			if (token_type == T_END_HEREDOC) {
				if (CG(increment_lineno)) {
					token_line = ++CG(zend_lineno);
					CG(increment_lineno) = 0;
				}
			}
			add_next_index_stringl(&keyword, (char *)zendtext, zendleng);
			add_next_index_long(&keyword, token_line);
			add_next_index_zval(return_value, &keyword);
		} else {
			add_next_index_stringl(return_value, (char *)zendtext, zendleng);
		}
		if (destroy && Z_TYPE(token) != IS_NULL) {
			zval_dtor(&token);
		}
		ZVAL_NULL(&token);

		// after T_HALT_COMPILER collect the next three non-dropped tokens
		if (need_tokens != -1) {
			if (token_type != T_WHITESPACE && token_type != T_OPEN_TAG
			    && token_type != T_COMMENT && token_type != T_DOC_COMMENT
			    && --need_tokens == 0
			) {
				// fetch the rest into a T_INLINE_HTML
				if (zendcursor != zendlimit) {
					array_init(&keyword);
					add_next_index_long(&keyword, T_INLINE_HTML);
					add_next_index_stringl(&keyword, (char *)zendcursor, zendlimit - zendcursor);
					add_next_index_long(&keyword, token_line);
					add_next_index_zval(return_value, &keyword);
				}
				break;
			}
		} else if (token_type == T_HALT_COMPILER) {
			need_tokens = 3;
		}

		token_line = CG(zend_lineno);
	}
}
コード例 #4
0
ファイル: console.c プロジェクト: dreamsxin/cphalcon7
/**
 * Handle the command-line arguments.
 *  
 * 
 * <code>
 * 	$arguments = array(
 * 		'task' => 'taskname',
 * 		'action' => 'action',
 * 		'params' => array('parameter1', 'parameter2')
 * 	);
 * 	$console->handle($arguments);
 * </code>
 *
 * @param array $arguments
 * @return mixed
 */
PHP_METHOD(Phalcon_CLI_Console, handle){

	zval *_arguments = NULL, arguments = {}, dependency_injector = {}, events_manager = {}, event_name = {}, service = {}, router = {}, module_name = {};
	zval status = {}, modules = {}, exception_msg = {}, module = {}, path = {}, class_name = {}, module_object = {};
	zval namespace_name = {}, task_name = {}, action_name = {}, params = {}, dispatcher = {};

	phalcon_fetch_params(0, 0, 1, &_arguments);

	if (!_arguments) {
		array_init(&arguments);
	} else {
		PHALCON_CPY_WRT(&arguments, _arguments);
	}

	phalcon_return_property(&events_manager, getThis(), SL("_eventsManager"));

	ZVAL_STRING(&service, ISV(router));

	PHALCON_CALL_METHODW(&dependency_injector, getThis(), "getdi");
	if (Z_TYPE(dependency_injector) != IS_OBJECT) {
		PHALCON_THROW_EXCEPTION_FORMATW(phalcon_cli_console_exception_ce, "A dependency injection container is required to access the '%s' service", Z_STRVAL(service));
		return;
	}

	PHALCON_CALL_METHODW(&router, &dependency_injector, "getshared", &service);
	PHALCON_VERIFY_CLASSW(&router, phalcon_cli_router_ce);

	PHALCON_CALL_METHODW(NULL, &router, "handle", &arguments);
	PHALCON_CALL_METHODW(&module_name, &router, "getmodulename");
	if (zend_is_true(&module_name)) {
		if (Z_TYPE(events_manager) == IS_OBJECT) {
			ZVAL_STRING(&event_name, "console:beforeStartModule");

			PHALCON_CALL_METHODW(&status, &events_manager, "fire", &event_name, getThis(), &module_name);
			if (PHALCON_IS_FALSE(&status)) {
				RETURN_FALSE;
			}
		}

		phalcon_read_property(&modules, getThis(), SL("_modules"), PH_NOISY);
		if (!phalcon_array_isset_fetch(&module, &modules, &module_name, 0)) {
			PHALCON_CONCAT_SVS(&exception_msg, "Module '", &module_name, "' isn't registered in the console container");
			PHALCON_THROW_EXCEPTION_ZVALW(phalcon_cli_console_exception_ce, &exception_msg);
			return;
		}

		if (Z_TYPE_P(&module) != IS_ARRAY) { 
			PHALCON_THROW_EXCEPTION_STRW(phalcon_cli_console_exception_ce, "Invalid module definition path");
			return;
		}

		if (phalcon_array_isset_fetch_str(&path, &module, SL("path"))) {
			convert_to_string_ex(&path);

			if (phalcon_file_exists(&path) == SUCCESS) {
				RETURN_ON_FAILURE(phalcon_require(Z_STRVAL(path)));
			} else {
				zend_throw_exception_ex(phalcon_cli_console_exception_ce, 0, "Modules definition path '%s' does not exist", Z_STRVAL(path));
				return;
			}
		}

		if (!phalcon_array_isset_fetch_str(&class_name, &module, SL("className"))) {
			ZVAL_STRING(&class_name, "Module");
		}

		PHALCON_CALL_METHODW(&module_object, &dependency_injector, "getshared", &class_name);
		PHALCON_CALL_METHODW(NULL, &module_object, "registerautoloaders");
		PHALCON_CALL_METHODW(NULL, &module_object, "registerservices", &dependency_injector);
		if (Z_TYPE(events_manager) == IS_OBJECT) {
			phalcon_update_property_zval(getThis(), SL("_moduleObject"), &module_object);

			ZVAL_STRING(&event_name, "console:afterStartModule");

			PHALCON_CALL_METHODW(&status, &events_manager, "fire", &event_name, getThis(), &module_name);
			if (PHALCON_IS_FALSE(&status)) {
				RETURN_FALSE;
			}
		}
	}

	PHALCON_CALL_METHODW(&namespace_name, &router, "getnamespacename");
	PHALCON_CALL_METHODW(&task_name, &router, "gettaskname");
	PHALCON_CALL_METHODW(&action_name, &router, "getactionname");
	PHALCON_CALL_METHODW(&params, &router, "getparams");

	ZVAL_STRING(&service, ISV(dispatcher));

	PHALCON_CALL_METHODW(&dispatcher, &dependency_injector, "getshared", &service);
	PHALCON_VERIFY_INTERFACEW(&dispatcher, phalcon_dispatcherinterface_ce);

	PHALCON_CALL_METHODW(NULL, &dispatcher, "setnamespacename", &namespace_name);
	PHALCON_CALL_METHODW(NULL, &dispatcher, "settaskname", &task_name);
	PHALCON_CALL_METHODW(NULL, &dispatcher, "setactionname", &action_name);
	PHALCON_CALL_METHODW(NULL, &dispatcher, "setparams", &params);
	if (Z_TYPE(events_manager) == IS_OBJECT) {
		ZVAL_STRING(&event_name, "console:beforeHandleTask");

		PHALCON_CALL_METHODW(&status, &events_manager, "fire", &event_name, getThis(), &dispatcher);
		if (PHALCON_IS_FALSE(&status)) {
			RETURN_FALSE;
		}
	}

	PHALCON_CALL_METHODW(&status, &dispatcher, "dispatch");

	if (Z_TYPE(events_manager) == IS_OBJECT) {
		ZVAL_STRING(&event_name, "console:afterHandleTask");
		PHALCON_CALL_METHODW(NULL, &events_manager, "fire", &event_name, getThis(), &status);
	}

	RETURN_CTORW(&status);
}
コード例 #5
0
ファイル: rfc1867.c プロジェクト: 13572293130/php-src
SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
{
	char *boundary, *s = NULL, *boundary_end = NULL, *start_arr = NULL, *array_index = NULL;
	char *lbuf = NULL, *abuf = NULL;
	zend_string *temp_filename = NULL;
	int boundary_len = 0, cancel_upload = 0, is_arr_upload = 0, array_len = 0;
	int64_t total_bytes = 0, max_file_size = 0;
	int skip_upload = 0, anonindex = 0, is_anonymous;
	HashTable *uploaded_files = NULL;
	multipart_buffer *mbuff;
	zval *array_ptr = (zval *) arg;
	int fd = -1;
	zend_llist header;
	void *event_extra_data = NULL;
	unsigned int llen = 0;
	int upload_cnt = INI_INT("max_file_uploads");
	const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding();
	php_rfc1867_getword_t getword;
	php_rfc1867_getword_conf_t getword_conf;
	php_rfc1867_basename_t _basename;
	zend_long count = 0;

	if (php_rfc1867_encoding_translation() && internal_encoding) {
		getword = php_rfc1867_getword;
		getword_conf = php_rfc1867_getword_conf;
		_basename = php_rfc1867_basename;
	} else {
		getword = php_ap_getword;
		getword_conf = php_ap_getword_conf;
		_basename = php_ap_basename;
	}

	if (SG(post_max_size) > 0 && SG(request_info).content_length > SG(post_max_size)) {
		sapi_module.sapi_error(E_WARNING, "POST Content-Length of " ZEND_LONG_FMT " bytes exceeds the limit of " ZEND_LONG_FMT " bytes", SG(request_info).content_length, SG(post_max_size));
		return;
	}

	/* Get the boundary */
	boundary = strstr(content_type_dup, "boundary");
	if (!boundary) {
		int content_type_len = (int)strlen(content_type_dup);
		char *content_type_lcase = estrndup(content_type_dup, content_type_len);

		php_strtolower(content_type_lcase, content_type_len);
		boundary = strstr(content_type_lcase, "boundary");
		if (boundary) {
			boundary = content_type_dup + (boundary - content_type_lcase);
		}
		efree(content_type_lcase);
	}

	if (!boundary || !(boundary = strchr(boundary, '='))) {
		sapi_module.sapi_error(E_WARNING, "Missing boundary in multipart/form-data POST data");
		return;
	}

	boundary++;
	boundary_len = (int)strlen(boundary);

	if (boundary[0] == '"') {
		boundary++;
		boundary_end = strchr(boundary, '"');
		if (!boundary_end) {
			sapi_module.sapi_error(E_WARNING, "Invalid boundary in multipart/form-data POST data");
			return;
		}
	} else {
		/* search for the end of the boundary */
		boundary_end = strpbrk(boundary, ",;");
	}
	if (boundary_end) {
		boundary_end[0] = '\0';
		boundary_len = boundary_end-boundary;
	}

	/* Initialize the buffer */
	if (!(mbuff = multipart_buffer_new(boundary, boundary_len))) {
		sapi_module.sapi_error(E_WARNING, "Unable to initialize the input buffer");
		return;
	}

	/* Initialize $_FILES[] */
	zend_hash_init(&PG(rfc1867_protected_variables), 8, NULL, NULL, 0);

	ALLOC_HASHTABLE(uploaded_files);
	zend_hash_init(uploaded_files, 8, NULL, free_filename, 0);
	SG(rfc1867_uploaded_files) = uploaded_files;

	if (Z_TYPE(PG(http_globals)[TRACK_VARS_FILES]) != IS_ARRAY) {
		/* php_auto_globals_create_files() might have already done that */
		array_init(&PG(http_globals)[TRACK_VARS_FILES]);
	}

	zend_llist_init(&header, sizeof(mime_header_entry), (llist_dtor_func_t) php_free_hdr_entry, 0);

	if (php_rfc1867_callback != NULL) {
		multipart_event_start event_start;

		event_start.content_length = SG(request_info).content_length;
		if (php_rfc1867_callback(MULTIPART_EVENT_START, &event_start, &event_extra_data) == FAILURE) {
			goto fileupload_done;
		}
	}

	while (!multipart_buffer_eof(mbuff))
	{
		char buff[FILLUNIT];
		char *cd = NULL, *param = NULL, *filename = NULL, *tmp = NULL;
		size_t blen = 0, wlen = 0;
		zend_off_t offset;

		zend_llist_clean(&header);

		if (!multipart_buffer_headers(mbuff, &header)) {
			goto fileupload_done;
		}

		if ((cd = php_mime_get_hdr_value(header, "Content-Disposition"))) {
			char *pair = NULL;
			int end = 0;

			while (isspace(*cd)) {
				++cd;
			}

			while (*cd && (pair = getword(mbuff->input_encoding, &cd, ';')))
			{
				char *key = NULL, *word = pair;

				while (isspace(*cd)) {
					++cd;
				}

				if (strchr(pair, '=')) {
					key = getword(mbuff->input_encoding, &pair, '=');

					if (!strcasecmp(key, "name")) {
						if (param) {
							efree(param);
						}
						param = getword_conf(mbuff->input_encoding, pair);
						if (mbuff->input_encoding && internal_encoding) {
							unsigned char *new_param;
							size_t new_param_len;
							if ((size_t)-1 != zend_multibyte_encoding_converter(&new_param, &new_param_len, (unsigned char *)param, strlen(param), internal_encoding, mbuff->input_encoding)) {
								efree(param);
								param = (char *)new_param;
							}
						}
					} else if (!strcasecmp(key, "filename")) {
						if (filename) {
							efree(filename);
						}
						filename = getword_conf(mbuff->input_encoding, pair);
						if (mbuff->input_encoding && internal_encoding) {
							unsigned char *new_filename;
							size_t new_filename_len;
							if ((size_t)-1 != zend_multibyte_encoding_converter(&new_filename, &new_filename_len, (unsigned char *)filename, strlen(filename), internal_encoding, mbuff->input_encoding)) {
								efree(filename);
								filename = (char *)new_filename;
							}
						}
					}
				}
				if (key) {
					efree(key);
				}
				efree(word);
			}

			/* Normal form variable, safe to read all data into memory */
			if (!filename && param) {
				size_t value_len;
				char *value = multipart_buffer_read_body(mbuff, &value_len);
				size_t new_val_len; /* Dummy variable */

				if (!value) {
					value = estrdup("");
					value_len = 0;
				}

				if (mbuff->input_encoding && internal_encoding) {
					unsigned char *new_value;
					size_t new_value_len;
					if ((size_t)-1 != zend_multibyte_encoding_converter(&new_value, &new_value_len, (unsigned char *)value, value_len, internal_encoding, mbuff->input_encoding)) {
						efree(value);
						value = (char *)new_value;
						value_len = new_value_len;
					}
				}

				if (++count <= PG(max_input_vars) && sapi_module.input_filter(PARSE_POST, param, &value, value_len, &new_val_len)) {
					if (php_rfc1867_callback != NULL) {
						multipart_event_formdata event_formdata;
						size_t newlength = new_val_len;

						event_formdata.post_bytes_processed = SG(read_post_bytes);
						event_formdata.name = param;
						event_formdata.value = &value;
						event_formdata.length = new_val_len;
						event_formdata.newlength = &newlength;
						if (php_rfc1867_callback(MULTIPART_EVENT_FORMDATA, &event_formdata, &event_extra_data) == FAILURE) {
							efree(param);
							efree(value);
							continue;
						}
						new_val_len = newlength;
					}
					safe_php_register_variable(param, value, new_val_len, array_ptr, 0);
				} else {
					if (count == PG(max_input_vars) + 1) {
						php_error_docref(NULL, E_WARNING, "Input variables exceeded " ZEND_LONG_FMT ". To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
					}

					if (php_rfc1867_callback != NULL) {
						multipart_event_formdata event_formdata;

						event_formdata.post_bytes_processed = SG(read_post_bytes);
						event_formdata.name = param;
						event_formdata.value = &value;
						event_formdata.length = value_len;
						event_formdata.newlength = NULL;
						php_rfc1867_callback(MULTIPART_EVENT_FORMDATA, &event_formdata, &event_extra_data);
					}
				}

				if (!strcasecmp(param, "MAX_FILE_SIZE")) {
#ifdef HAVE_ATOLL
					max_file_size = atoll(value);
#else
					max_file_size = strtoll(value, NULL, 10);
#endif
				}

				efree(param);
				efree(value);
				continue;
			}

			/* If file_uploads=off, skip the file part */
			if (!PG(file_uploads)) {
				skip_upload = 1;
			} else if (upload_cnt <= 0) {
				skip_upload = 1;
				sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded");
			}

			/* Return with an error if the posted data is garbled */
			if (!param && !filename) {
				sapi_module.sapi_error(E_WARNING, "File Upload Mime headers garbled");
				goto fileupload_done;
			}

			if (!param) {
				is_anonymous = 1;
				param = emalloc(MAX_SIZE_ANONNAME);
				snprintf(param, MAX_SIZE_ANONNAME, "%u", anonindex++);
			} else {
				is_anonymous = 0;
			}

			/* New Rule: never repair potential malicious user input */
			if (!skip_upload) {
				long c = 0;
				tmp = param;

				while (*tmp) {
					if (*tmp == '[') {
						c++;
					} else if (*tmp == ']') {
						c--;
						if (tmp[1] && tmp[1] != '[') {
							skip_upload = 1;
							break;
						}
					}
					if (c < 0) {
						skip_upload = 1;
						break;
					}
					tmp++;
				}
				/* Brackets should always be closed */
				if(c != 0) {
					skip_upload = 1;
				}
			}

			total_bytes = cancel_upload = 0;
			temp_filename = NULL;
			fd = -1;

			if (!skip_upload && php_rfc1867_callback != NULL) {
				multipart_event_file_start event_file_start;

				event_file_start.post_bytes_processed = SG(read_post_bytes);
				event_file_start.name = param;
				event_file_start.filename = &filename;
				if (php_rfc1867_callback(MULTIPART_EVENT_FILE_START, &event_file_start, &event_extra_data) == FAILURE) {
					temp_filename = NULL;
					efree(param);
					efree(filename);
					continue;
				}
			}

			if (skip_upload) {
				efree(param);
				efree(filename);
				continue;
			}

			if (filename[0] == '\0') {
#if DEBUG_FILE_UPLOAD
				sapi_module.sapi_error(E_NOTICE, "No file uploaded");
#endif
				cancel_upload = UPLOAD_ERROR_D;
			}

			offset = 0;
			end = 0;

			if (!cancel_upload) {
				/* only bother to open temp file if we have data */
				blen = multipart_buffer_read(mbuff, buff, sizeof(buff), &end);
#if DEBUG_FILE_UPLOAD
				if (blen > 0) {
#else
				/* in non-debug mode we have no problem with 0-length files */
				{
#endif
					fd = php_open_temporary_fd_ex(PG(upload_tmp_dir), "php", &temp_filename, 1);
					upload_cnt--;
					if (fd == -1) {
						sapi_module.sapi_error(E_WARNING, "File upload error - unable to create a temporary file");
						cancel_upload = UPLOAD_ERROR_E;
					}
				}
			}

			while (!cancel_upload && (blen > 0))
			{
				if (php_rfc1867_callback != NULL) {
					multipart_event_file_data event_file_data;

					event_file_data.post_bytes_processed = SG(read_post_bytes);
					event_file_data.offset = offset;
					event_file_data.data = buff;
					event_file_data.length = blen;
					event_file_data.newlength = &blen;
					if (php_rfc1867_callback(MULTIPART_EVENT_FILE_DATA, &event_file_data, &event_extra_data) == FAILURE) {
						cancel_upload = UPLOAD_ERROR_X;
						continue;
					}
				}

				if (PG(upload_max_filesize) > 0 && (zend_long)(total_bytes+blen) > PG(upload_max_filesize)) {
#if DEBUG_FILE_UPLOAD
					sapi_module.sapi_error(E_NOTICE, "upload_max_filesize of " ZEND_LONG_FMT " bytes exceeded - file [%s=%s] not saved", PG(upload_max_filesize), param, filename);
#endif
					cancel_upload = UPLOAD_ERROR_A;
				} else if (max_file_size && ((zend_long)(total_bytes+blen) > max_file_size)) {
#if DEBUG_FILE_UPLOAD
					sapi_module.sapi_error(E_NOTICE, "MAX_FILE_SIZE of " ZEND_LONG_FMT " bytes exceeded - file [%s=%s] not saved", max_file_size, param, filename);
#endif
					cancel_upload = UPLOAD_ERROR_B;
				} else if (blen > 0) {
#ifdef PHP_WIN32
					wlen = write(fd, buff, (unsigned int)blen);
#else
					wlen = write(fd, buff, blen);
#endif

					if (wlen == -1) {
						/* write failed */
#if DEBUG_FILE_UPLOAD
						sapi_module.sapi_error(E_NOTICE, "write() failed - %s", strerror(errno));
#endif
						cancel_upload = UPLOAD_ERROR_F;
					} else if (wlen < blen) {
#if DEBUG_FILE_UPLOAD
						sapi_module.sapi_error(E_NOTICE, "Only %d bytes were written, expected to write %d", wlen, blen);
#endif
						cancel_upload = UPLOAD_ERROR_F;
					} else {
						total_bytes += wlen;
					}
					offset += wlen;
				}

				/* read data for next iteration */
				blen = multipart_buffer_read(mbuff, buff, sizeof(buff), &end);
			}

			if (fd != -1) { /* may not be initialized if file could not be created */
				close(fd);
			}

			if (!cancel_upload && !end) {
#if DEBUG_FILE_UPLOAD
				sapi_module.sapi_error(E_NOTICE, "Missing mime boundary at the end of the data for file %s", filename[0] != '\0' ? filename : "");
#endif
				cancel_upload = UPLOAD_ERROR_C;
			}
#if DEBUG_FILE_UPLOAD
			if (filename[0] != '\0' && total_bytes == 0 && !cancel_upload) {
				sapi_module.sapi_error(E_WARNING, "Uploaded file size 0 - file [%s=%s] not saved", param, filename);
				cancel_upload = 5;
			}
#endif
			if (php_rfc1867_callback != NULL) {
				multipart_event_file_end event_file_end;

				event_file_end.post_bytes_processed = SG(read_post_bytes);
				event_file_end.temp_filename = ZSTR_VAL(temp_filename);
				event_file_end.cancel_upload = cancel_upload;
				if (php_rfc1867_callback(MULTIPART_EVENT_FILE_END, &event_file_end, &event_extra_data) == FAILURE) {
					cancel_upload = UPLOAD_ERROR_X;
				}
			}

			if (cancel_upload) {
				if (temp_filename) {
					if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */
						unlink(ZSTR_VAL(temp_filename));
					}
					zend_string_release(temp_filename);
				}
				temp_filename = NULL;
			} else {
				zend_hash_add_ptr(SG(rfc1867_uploaded_files), temp_filename, temp_filename);
			}

			/* is_arr_upload is true when name of file upload field
			 * ends in [.*]
			 * start_arr is set to point to 1st [ */
			is_arr_upload =	(start_arr = strchr(param,'[')) && (param[strlen(param)-1] == ']');

			if (is_arr_upload) {
				array_len = (int)strlen(start_arr);
				if (array_index) {
					efree(array_index);
				}
				array_index = estrndup(start_arr + 1, array_len - 2);
			}

			/* Add $foo_name */
			if (llen < strlen(param) + MAX_SIZE_OF_INDEX + 1) {
				llen = (int)strlen(param);
				lbuf = (char *) safe_erealloc(lbuf, llen, 1, MAX_SIZE_OF_INDEX + 1);
				llen += MAX_SIZE_OF_INDEX + 1;
			}

			if (is_arr_upload) {
				if (abuf) efree(abuf);
				abuf = estrndup(param, strlen(param)-array_len);
				snprintf(lbuf, llen, "%s_name[%s]", abuf, array_index);
			} else {
				snprintf(lbuf, llen, "%s_name", param);
			}

			/* The \ check should technically be needed for win32 systems only where
			 * it is a valid path separator. However, IE in all it's wisdom always sends
			 * the full path of the file on the user's filesystem, which means that unless
			 * the user does basename() they get a bogus file name. Until IE's user base drops
			 * to nill or problem is fixed this code must remain enabled for all systems. */
			s = _basename(internal_encoding, filename);
			if (!s) {
				s = filename;
			}

			if (!is_anonymous) {
				safe_php_register_variable(lbuf, s, strlen(s), NULL, 0);
			}

			/* Add $foo[name] */
			if (is_arr_upload) {
				snprintf(lbuf, llen, "%s[name][%s]", abuf, array_index);
			} else {
				snprintf(lbuf, llen, "%s[name]", param);
			}
			register_http_post_files_variable(lbuf, s, &PG(http_globals)[TRACK_VARS_FILES], 0);
			efree(filename);
			s = NULL;

			/* Possible Content-Type: */
			if (cancel_upload || !(cd = php_mime_get_hdr_value(header, "Content-Type"))) {
				cd = "";
			} else {
				/* fix for Opera 6.01 */
				s = strchr(cd, ';');
				if (s != NULL) {
					*s = '\0';
				}
			}

			/* Add $foo_type */
			if (is_arr_upload) {
				snprintf(lbuf, llen, "%s_type[%s]", abuf, array_index);
			} else {
				snprintf(lbuf, llen, "%s_type", param);
			}
			if (!is_anonymous) {
				safe_php_register_variable(lbuf, cd, strlen(cd), NULL, 0);
			}

			/* Add $foo[type] */
			if (is_arr_upload) {
				snprintf(lbuf, llen, "%s[type][%s]", abuf, array_index);
			} else {
				snprintf(lbuf, llen, "%s[type]", param);
			}
			register_http_post_files_variable(lbuf, cd, &PG(http_globals)[TRACK_VARS_FILES], 0);

			/* Restore Content-Type Header */
			if (s != NULL) {
				*s = ';';
			}
			s = "";

			{
				/* store temp_filename as-is (in case upload_tmp_dir
				 * contains escapeable characters. escape only the variable name.) */
				zval zfilename;

				/* Initialize variables */
				add_protected_variable(param);

				/* if param is of form xxx[.*] this will cut it to xxx */
				if (!is_anonymous) {
					if (temp_filename) {
						ZVAL_STR_COPY(&zfilename, temp_filename);
					} else {
						ZVAL_EMPTY_STRING(&zfilename);
					}
					safe_php_register_variable_ex(param, &zfilename, NULL, 1);
				}

				/* Add $foo[tmp_name] */
				if (is_arr_upload) {
					snprintf(lbuf, llen, "%s[tmp_name][%s]", abuf, array_index);
				} else {
					snprintf(lbuf, llen, "%s[tmp_name]", param);
				}
				add_protected_variable(lbuf);
				if (temp_filename) {
					ZVAL_STR_COPY(&zfilename, temp_filename);
				} else {
					ZVAL_EMPTY_STRING(&zfilename);
				}
				register_http_post_files_variable_ex(lbuf, &zfilename, &PG(http_globals)[TRACK_VARS_FILES], 1);
			}

			{
				zval file_size, error_type;
				int size_overflow = 0;
				char file_size_buf[65];

				ZVAL_LONG(&error_type, cancel_upload);

				/* Add $foo[error] */
				if (cancel_upload) {
					ZVAL_LONG(&file_size, 0);
				} else {
					if (total_bytes > ZEND_LONG_MAX) {
#ifdef PHP_WIN32
						if (_i64toa_s(total_bytes, file_size_buf, 65, 10)) {
							file_size_buf[0] = '0';
							file_size_buf[1] = '\0';
						}
#else
						{
							int __len = snprintf(file_size_buf, 65, "%lld", total_bytes);
							file_size_buf[__len] = '\0';
						}
#endif
						size_overflow = 1;

					} else {
						ZVAL_LONG(&file_size, total_bytes);
					}
				}

				if (is_arr_upload) {
					snprintf(lbuf, llen, "%s[error][%s]", abuf, array_index);
				} else {
					snprintf(lbuf, llen, "%s[error]", param);
				}
				register_http_post_files_variable_ex(lbuf, &error_type, &PG(http_globals)[TRACK_VARS_FILES], 0);

				/* Add $foo_size */
				if (is_arr_upload) {
					snprintf(lbuf, llen, "%s_size[%s]", abuf, array_index);
				} else {
					snprintf(lbuf, llen, "%s_size", param);
				}
				if (!is_anonymous) {
					if (size_overflow) {
						ZVAL_STRING(&file_size, file_size_buf);
					}
					safe_php_register_variable_ex(lbuf, &file_size, NULL, size_overflow);
				}

				/* Add $foo[size] */
				if (is_arr_upload) {
					snprintf(lbuf, llen, "%s[size][%s]", abuf, array_index);
				} else {
					snprintf(lbuf, llen, "%s[size]", param);
				}
				if (size_overflow) {
					ZVAL_STRING(&file_size, file_size_buf);
				}
				register_http_post_files_variable_ex(lbuf, &file_size, &PG(http_globals)[TRACK_VARS_FILES], size_overflow);
			}
			efree(param);
		}
	}

fileupload_done:
	if (php_rfc1867_callback != NULL) {
		multipart_event_end event_end;

		event_end.post_bytes_processed = SG(read_post_bytes);
		php_rfc1867_callback(MULTIPART_EVENT_END, &event_end, &event_extra_data);
	}

	if (lbuf) efree(lbuf);
	if (abuf) efree(abuf);
	if (array_index) efree(array_index);
	zend_hash_destroy(&PG(rfc1867_protected_variables));
	zend_llist_destroy(&header);
	if (mbuff->boundary_next) efree(mbuff->boundary_next);
	if (mbuff->boundary) efree(mbuff->boundary);
	if (mbuff->buffer) efree(mbuff->buffer);
	if (mbuff) efree(mbuff);
}
/* }}} */

SAPI_API void php_rfc1867_set_multibyte_callbacks(
					php_rfc1867_encoding_translation_t encoding_translation,
					php_rfc1867_get_detect_order_t get_detect_order,
					php_rfc1867_set_input_encoding_t set_input_encoding,
					php_rfc1867_getword_t getword,
					php_rfc1867_getword_conf_t getword_conf,
					php_rfc1867_basename_t basename) /* {{{ */
{
	php_rfc1867_encoding_translation = encoding_translation;
	php_rfc1867_get_detect_order = get_detect_order;
	php_rfc1867_set_input_encoding = set_input_encoding;
	php_rfc1867_getword = getword;
	php_rfc1867_getword_conf = getword_conf;
	php_rfc1867_basename = basename;
}
コード例 #6
0
ファイル: zend_execute_API.c プロジェクト: Furgas/php-src
void shutdown_executor(void) /* {{{ */
{
	zend_function *func;
	zend_class_entry *ce;

	zend_try {

/* Removed because this can not be safely done, e.g. in this situation:
   Object 1 creates object 2
   Object 3 holds reference to object 2.
   Now when 1 and 2 are destroyed, 3 can still access 2 in its destructor, with
   very problematic results */
/* 		zend_objects_store_call_destructors(&EG(objects_store)); */

/* Moved after symbol table cleaners, because  some of the cleaners can call
   destructors, which would use EG(symtable_cache_ptr) and thus leave leaks */
/*		while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
			zend_hash_destroy(*EG(symtable_cache_ptr));
			efree(*EG(symtable_cache_ptr));
			EG(symtable_cache_ptr)--;
		}
*/
		zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator);

		if (CG(unclean_shutdown)) {
			EG(symbol_table).pDestructor = zend_unclean_zval_ptr_dtor;
		}
		zend_hash_graceful_reverse_destroy(&EG(symbol_table));
	} zend_end_try();
	EG(valid_symbol_table) = 0;

	zend_try {
		zval *zeh;
		/* remove error handlers before destroying classes and functions,
		 * so that if handler used some class, crash would not happen */
		if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
			zeh = &EG(user_error_handler);
			zval_ptr_dtor(zeh);
			ZVAL_UNDEF(&EG(user_error_handler));
		}

		if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
			zeh = &EG(user_exception_handler);
			zval_ptr_dtor(zeh);
			ZVAL_UNDEF(&EG(user_exception_handler));
		}

		zend_stack_clean(&EG(user_error_handlers_error_reporting), NULL, 1);
		zend_stack_clean(&EG(user_error_handlers), (void (*)(void *))ZVAL_DESTRUCTOR, 1);
		zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))ZVAL_DESTRUCTOR, 1);
	} zend_end_try();

	zend_try {
		/* Cleanup static data for functions and arrays.
		 * We need a separate cleanup stage because of the following problem:
		 * Suppose we destroy class X, which destroys the class's function table,
		 * and in the function table we have function foo() that has static $bar.
		 * Now if an object of class X is assigned to $bar, its destructor will be
		 * called and will fail since X's function table is in mid-destruction.
		 * So we want first of all to clean up all data and then move to tables destruction.
		 * Note that only run-time accessed data need to be cleaned up, pre-defined data can
		 * not contain objects and thus are not probelmatic */
		if (EG(full_tables_cleanup)) {
			ZEND_HASH_FOREACH_PTR(EG(function_table), func) {
				if (func->type == ZEND_USER_FUNCTION) {
					zend_cleanup_op_array_data((zend_op_array *) func);
				}
			} ZEND_HASH_FOREACH_END();
			ZEND_HASH_REVERSE_FOREACH_PTR(EG(class_table), ce) {
				if (ce->type == ZEND_USER_CLASS) {
					zend_cleanup_user_class_data(ce);
				} else {
					zend_cleanup_internal_class_data(ce);
				}
			} ZEND_HASH_FOREACH_END();
		} else {
			ZEND_HASH_REVERSE_FOREACH_PTR(EG(function_table), func) {
				if (func->type != ZEND_USER_FUNCTION) {
					break;
				}
				zend_cleanup_op_array_data((zend_op_array *) func);
			} ZEND_HASH_FOREACH_END();
			ZEND_HASH_REVERSE_FOREACH_PTR(EG(class_table), ce) {
				if (ce->type != ZEND_USER_CLASS) {
					break;
				}
				zend_cleanup_user_class_data(ce);
			} ZEND_HASH_FOREACH_END();
			zend_cleanup_internal_classes();
		}
	} zend_end_try();
コード例 #7
0
ファイル: user_filters.c プロジェクト: WarnerBe/php-src
static php_stream_filter *user_filter_factory_create(const char *filtername,
		zval *filterparams, uint8_t persistent)
{
	struct php_user_filter_data *fdat = NULL;
	php_stream_filter *filter;
	zval obj, zfilter;
	zval func_name;
	zval retval;
	size_t len;

	/* some sanity checks */
	if (persistent) {
		php_error_docref(NULL, E_WARNING,
				"cannot use a user-space filter with a persistent stream");
		return NULL;
	}

	len = strlen(filtername);

	/* determine the classname/class entry */
	if (NULL == (fdat = zend_hash_str_find_ptr(BG(user_filter_map), (char*)filtername, len))) {
		char *period;

		/* Userspace Filters using ambiguous wildcards could cause problems.
           i.e.: myfilter.foo.bar will always call into myfilter.foo.*
                 never seeing myfilter.*
           TODO: Allow failed userfilter creations to continue
                 scanning through the list */
		if ((period = strrchr(filtername, '.'))) {
			char *wildcard = safe_emalloc(len, 1, 3);

			/* Search for wildcard matches instead */
			memcpy(wildcard, filtername, len + 1); /* copy \0 */
			period = wildcard + (period - filtername);
			while (period) {
				*period = '\0';
				strncat(wildcard, ".*", 2);
				if (NULL != (fdat = zend_hash_str_find_ptr(BG(user_filter_map), wildcard, strlen(wildcard)))) {
					period = NULL;
				} else {
					*period = '\0';
					period = strrchr(wildcard, '.');
				}
			}
			efree(wildcard);
		}
		if (fdat == NULL) {
			php_error_docref(NULL, E_WARNING,
					"Err, filter \"%s\" is not in the user-filter map, but somehow the user-filter-factory was invoked for it!?", filtername);
			return NULL;
		}
	}

	/* bind the classname to the actual class */
	if (fdat->ce == NULL) {
		if (NULL == (fdat->ce = zend_lookup_class(fdat->classname))) {
			php_error_docref(NULL, E_WARNING,
					"user-filter \"%s\" requires class \"%s\", but that class is not defined",
					filtername, ZSTR_VAL(fdat->classname));
			return NULL;
		}
	}

	filter = php_stream_filter_alloc(&userfilter_ops, NULL, 0);
	if (filter == NULL) {
		return NULL;
	}

	/* create the object */
	object_init_ex(&obj, fdat->ce);

	/* filtername */
	add_property_string(&obj, "filtername", (char*)filtername);

	/* and the parameters, if any */
	if (filterparams) {
		add_property_zval(&obj, "params", filterparams);
	} else {
		add_property_null(&obj, "params");
	}

	/* invoke the constructor */
	ZVAL_STRINGL(&func_name, "oncreate", sizeof("oncreate")-1);

	call_user_function_ex(NULL,
			&obj,
			&func_name,
			&retval,
			0, NULL,
			0, NULL);

	if (Z_TYPE(retval) != IS_UNDEF) {
		if (Z_TYPE(retval) == IS_FALSE) {
			/* User reported filter creation error "return false;" */
			zval_ptr_dtor(&retval);

			/* Kill the filter (safely) */
			ZVAL_UNDEF(&filter->abstract);
			php_stream_filter_free(filter);

			/* Kill the object */
			zval_ptr_dtor(&obj);

			/* Report failure to filter_alloc */
			return NULL;
		}
		zval_ptr_dtor(&retval);
	}
	zval_ptr_dtor(&func_name);

	/* set the filter property, this will be used during cleanup */
	ZVAL_RES(&zfilter, zend_register_resource(filter, le_userfilters));
	ZVAL_COPY_VALUE(&filter->abstract, &obj);
	add_property_zval(&obj, "filter", &zfilter);
	/* add_property_zval increments the refcount which is unwanted here */
	zval_ptr_dtor(&zfilter);

	return filter;
}
コード例 #8
0
U_CFUNC PHP_FUNCTION(intlcal_from_date_time)
{
	zval			*zv_arg,
					zv_tmp,
					*zv_datetime  		= NULL,
					zv_timestamp;
	php_date_obj	*datetime;
	char			*locale_str			= NULL;
	size_t				locale_str_len;
	TimeZone		*timeZone;
	UErrorCode		status				= U_ZERO_ERROR;
	Calendar        *cal;
	intl_error_reset(NULL TSRMLS_CC);

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|s!",
			&zv_arg, &locale_str, &locale_str_len) == FAILURE) {
		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
			"intlcal_from_date_time: bad arguments", 0 TSRMLS_CC);
		RETURN_NULL();
	}

	if (!(Z_TYPE_P(zv_arg) == IS_OBJECT && instanceof_function(
			Z_OBJCE_P(zv_arg), php_date_get_date_ce() TSRMLS_CC))) {
		object_init_ex(&zv_tmp, php_date_get_date_ce());
		zend_call_method_with_1_params(&zv_tmp, NULL, NULL, "__construct", NULL, zv_arg);
		if (EG(exception)) {
			zend_object_store_ctor_failed(Z_OBJ(zv_tmp) TSRMLS_CC);
			goto error;
		}
		zv_datetime = &zv_tmp;
	} else {
		zv_datetime = zv_arg;
	}

	datetime = Z_PHPDATE_P(zv_datetime);
	if (!datetime->time) {
		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
			"intlcal_from_date_time: DateTime object is unconstructed",
			0 TSRMLS_CC);
		goto error;
	}

	zend_call_method_with_0_params(zv_datetime, php_date_get_date_ce(), NULL, "gettimestamp", &zv_timestamp);
	if (Z_TYPE(zv_timestamp) != IS_LONG) {
		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
			"intlcal_from_date_time: bad DateTime; call to "
			"DateTime::getTimestamp() failed", 0 TSRMLS_CC);
		zval_ptr_dtor(&zv_timestamp);
		goto error;
	}

	if (!datetime->time->is_localtime) {
		timeZone = TimeZone::getGMT()->clone();
	} else {
		timeZone = timezone_convert_datetimezone(datetime->time->zone_type,
			datetime, 1, NULL, "intlcal_from_date_time" TSRMLS_CC);
		if (timeZone == NULL) {
			goto error;
		}
	}

	if (!locale_str) {
		locale_str = const_cast<char*>(intl_locale_get_default(TSRMLS_C));
	}

	cal = Calendar::createInstance(timeZone,
		Locale::createFromName(locale_str), status);
	if (cal == NULL) {
		delete timeZone;
		intl_error_set(NULL, status, "intlcal_from_date_time: "
				"error creating ICU Calendar object", 0 TSRMLS_CC);
		goto error;
	}
	cal->setTime(((UDate)Z_LVAL(zv_timestamp)) * 1000., status);
    if (U_FAILURE(status)) {
		/* time zone was adopted by cal; should not be deleted here */
		delete cal;
		intl_error_set(NULL, status, "intlcal_from_date_time: "
				"error creating ICU Calendar::setTime()", 0 TSRMLS_CC);
        goto error;
    }

	calendar_object_create(return_value, cal TSRMLS_CC);

error:
	if (zv_datetime && zv_datetime != zv_arg) {
		zval_ptr_dtor(zv_datetime);
	}
}
コード例 #9
0
U_CFUNC PHP_FUNCTION(intlcal_to_date_time)
{
	zval retval;
	CALENDAR_METHOD_INIT_VARS;

	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
			&object, Calendar_ce_ptr) == FAILURE) {
		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
			"intlcal_to_date_time: bad arguments", 0 TSRMLS_CC);
		RETURN_FALSE;
	}

	CALENDAR_METHOD_FETCH_OBJECT;

	/* There are no exported functions in ext/date to this
	 * in a more native fashion */
	double	date = co->ucal->getTime(CALENDAR_ERROR_CODE(co)) / 1000.;
	int64_t	ts;
	char	ts_str[sizeof("@-9223372036854775808")];
	int		ts_str_len;
	zval	ts_tmp, ts_zval, tmp;

	INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed");

	if (date > (double)U_INT64_MAX || date < (double)U_INT64_MIN) {
		intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
			"intlcal_to_date_time: The calendar date is out of the "
			"range for a 64-bit integer", 0 TSRMLS_CC);
		RETURN_FALSE;
	}
	
	ZVAL_UNDEF(&retval);
	ts = (int64_t)date;

	ts_str_len = slprintf(ts_str, sizeof(ts_str), "@%I64d", ts);
	ZVAL_STRINGL(&ts_zval, ts_str, ts_str_len);

	/* Now get the time zone */
	const TimeZone& tz = co->ucal->getTimeZone();
	zval *timezone_zval = timezone_convert_to_datetimezone(
		&tz, CALENDAR_ERROR_P(co), "intlcal_to_date_time", &tmp TSRMLS_CC);
	if (timezone_zval == NULL) {
		RETURN_FALSE;
	}

	/* resources allocated from now on */

	/* Finally, instantiate object and call constructor */
	object_init_ex(return_value, php_date_get_date_ce());
	zend_call_method_with_2_params(return_value, NULL, NULL, "__construct", NULL, &ts_zval, timezone_zval);
	if (EG(exception)) {
		intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
			"intlcal_to_date_time: DateTime constructor has thrown exception",
			1 TSRMLS_CC);
		zend_object_store_ctor_failed(Z_OBJ_P(return_value) TSRMLS_CC);
		zval_ptr_dtor(return_value);
		zval_ptr_dtor(&ts_zval);

		RETVAL_FALSE;
		goto error;
	}
	zval_ptr_dtor(&ts_zval);

	/* due to bug #40743, we have to set the time zone again */
	zend_call_method_with_1_params(return_value, NULL, NULL, "settimezone",
			&retval, timezone_zval);
	if (Z_ISUNDEF(retval) || Z_TYPE(retval) == IS_FALSE) {
		intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
			"intlcal_to_date_time: call to DateTime::setTimeZone has failed",
			1 TSRMLS_CC);
		zval_ptr_dtor(return_value);
		RETVAL_FALSE;
		goto error;
	}

error:
	zval_ptr_dtor(timezone_zval);
	zval_ptr_dtor(&retval);
}
コード例 #10
0
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;
    HashTable hash;
    zend_string *key = NULL;
    void *checkpoint = zend_arena_checkpoint(ctx->arena);

    if (op_array->last_literal) {
        cache_size = 0;
        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, 1, 1);
                break;
            case ZEND_INIT_FCALL_BY_NAME:
                LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 2);
                break;
            case ZEND_INIT_NS_FCALL_BY_NAME:
                LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 3);
                break;
            case ZEND_INIT_METHOD_CALL:
                if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                    optimizer_literal_obj_info(
                        info,
                        opline->op1_type,
                        opline->op1,
                        opline->op2.constant,
                        LITERAL_METHOD, 2, 2,
                        op_array);
                }
                break;
            case ZEND_INIT_STATIC_METHOD_CALL:
                if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                    LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
                }
                if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                    optimizer_literal_class_info(
                        info,
                        opline->op1_type,
                        opline->op1,
                        opline->op2.constant,
                        LITERAL_STATIC_METHOD, (ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 2,
                        op_array);
                }
                break;
            case ZEND_CATCH:
                LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
                break;
            case ZEND_DEFINED:
                LITERAL_INFO(opline->op1.constant, LITERAL_CONST, 1, 1, 2);
                break;
            case ZEND_FETCH_CONSTANT:
                if (ZEND_OP1_TYPE(opline) == IS_UNUSED) {
                    if ((opline->extended_value & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
                        LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 5);
                    } else {
                        LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 3);
                    }
                } else {
                    if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                        LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
                    }
                    optimizer_literal_class_info(
                        info,
                        opline->op1_type,
                        opline->op1,
                        opline->op2.constant,
                        LITERAL_CLASS_CONST, (ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 1,
                        op_array);
                }
                break;
            case ZEND_FETCH_R:
            case ZEND_FETCH_W:
            case ZEND_FETCH_RW:
            case ZEND_FETCH_IS:
            case ZEND_FETCH_UNSET:
            case ZEND_FETCH_FUNC_ARG:
            case ZEND_UNSET_VAR:
            case ZEND_ISSET_ISEMPTY_VAR:
                if (ZEND_OP2_TYPE(opline) == IS_UNUSED) {
                    if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                        LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
                    }
                } else {
                    if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                        LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
                    }
                    if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                        optimizer_literal_class_info(
                            info,
                            opline->op2_type,
                            opline->op2,
                            opline->op1.constant,
                            LITERAL_STATIC_PROPERTY, 2, 1,
                            op_array);
                    }
                }
                break;
            case ZEND_FETCH_CLASS:
            case ZEND_ADD_INTERFACE:
            case ZEND_ADD_TRAIT:
            case ZEND_INSTANCEOF:
                if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                    LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
                }
                break;
            case ZEND_NEW:
                if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                    LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 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 (ZEND_OP2_TYPE(opline) == IS_CONST) {
                    optimizer_literal_obj_info(
                        info,
                        opline->op1_type,
                        opline->op1,
                        opline->op2.constant,
                        LITERAL_PROPERTY, 2, 1,
                        op_array);
                }
                break;
            case ZEND_ASSIGN_ADD:
            case ZEND_ASSIGN_SUB:
            case ZEND_ASSIGN_MUL:
            case ZEND_ASSIGN_DIV:
            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 (ZEND_OP2_TYPE(opline) == IS_CONST) {
                    if (opline->extended_value == ZEND_ASSIGN_OBJ) {
                        optimizer_literal_obj_info(
                            info,
                            opline->op1_type,
                            opline->op1,
                            opline->op2.constant,
                            LITERAL_PROPERTY, 2, 1,
                            op_array);
                    } else {
                        LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1);
                    }
                }
                break;
            case ZEND_BIND_GLOBAL:
                LITERAL_INFO(opline->op2.constant, LITERAL_GLOBAL, 0, 1, 1);
                break;
            case ZEND_RECV_INIT:
                LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 0, 0, 1);
                if (Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) != -1) {
                    Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = cache_size;
                    cache_size += sizeof(void *);
                }
                break;
            case ZEND_RECV:
            case ZEND_VERIFY_RETURN_TYPE:
                if (opline->op2.num != -1) {
                    opline->op2.num = cache_size;
                    cache_size += sizeof(void *);
                }
            default:
                if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                    LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
                }
                if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                    LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 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_dtor(&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) {
                /* unsed literal */
                zval_dtor(&op_array->literals[i]);
                continue;
            }
            switch (Z_TYPE(op_array->literals[i])) {
            case IS_NULL:
                /* Only checking MAY_MERGE for IS_NULL here
                 * is because only IS_NULL can be default value for class type hinting(RECV_INIT). */
                if ((info[i].flags & LITERAL_MAY_MERGE)) {
                    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;
                } else {
                    map[i] = j;
                    if (i != j) {
                        op_array->literals[j] = op_array->literals[i];
                        info[j] = info[i];
                    }
                    j++;
                }
                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 ((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++;
                }
                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:
            case IS_CONSTANT:
                if (info[i].flags & LITERAL_MAY_MERGE) {
                    if (info[i].flags & LITERAL_EX_OBJ) {
                        int key_len = MAX_LENGTH_OF_LONG + sizeof("->") + Z_STRLEN(op_array->literals[i]);
                        key = zend_string_alloc(key_len, 0);
                        key->len = snprintf(key->val, key->len-1, "%d->%s", info[i].u.num, Z_STRVAL(op_array->literals[i]));
                    } else if (info[i].flags & LITERAL_EX_CLASS) {
                        int key_len;
                        zval *class_name = &op_array->literals[(info[i].u.num < i) ? map[info[i].u.num] : info[i].u.num];
                        key_len = Z_STRLEN_P(class_name) + sizeof("::") + Z_STRLEN(op_array->literals[i]);
                        key = zend_string_alloc(key_len, 0);
                        memcpy(key->val, Z_STRVAL_P(class_name), Z_STRLEN_P(class_name));
                        memcpy(key->val + Z_STRLEN_P(class_name), "::", sizeof("::") - 1);
                        memcpy(key->val + Z_STRLEN_P(class_name) + sizeof("::") - 1,
                               Z_STRVAL(op_array->literals[i]),
                               Z_STRLEN(op_array->literals[i]) + 1);
                    } else {
                        key = zend_string_init(Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]), 0);
                    }
                    key->h = zend_hash_func(key->val, key->len);
                    key->h += info[i].flags;
                }
                if ((info[i].flags & LITERAL_MAY_MERGE) &&
                        (pos = zend_hash_find(&hash, key)) != NULL &&
                        Z_TYPE(op_array->literals[i]) == Z_TYPE(op_array->literals[Z_LVAL_P(pos)]) &&
                        info[i].flags == info[Z_LVAL_P(pos)].flags) {

                    zend_string_release(key);
                    map[i] = Z_LVAL_P(pos);
                    zval_dtor(&op_array->literals[i]);
                    n = LITERAL_NUM_RELATED(info[i].flags);
                    while (n > 1) {
                        i++;
                        zval_dtor(&op_array->literals[i]);
                        n--;
                    }
                } else {
                    map[i] = j;
                    if (info[i].flags & LITERAL_MAY_MERGE) {
                        ZVAL_LONG(&zv, j);
                        zend_hash_add_new(&hash, key, &zv);
                        zend_string_release(key);
                    }
                    if (i != j) {
                        op_array->literals[j] = op_array->literals[i];
                        info[j] = info[i];
                    }
                    if (LITERAL_NUM_SLOTS(info[i].flags)) {
                        Z_CACHE_SLOT(op_array->literals[j]) = cache_size;
                        cache_size += LITERAL_NUM_SLOTS(info[i].flags) * sizeof(void*);
                    }
                    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;
            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_destroy(&hash);
        op_array->last_literal = j;
        op_array->cache_size = cache_size;

        /* Update opcodes to use new literals table */
        opline = op_array->opcodes;
        end = opline + op_array->last;
        while (opline < end) {
            if (ZEND_OP1_TYPE(opline) == IS_CONST) {
                opline->op1.constant = map[opline->op1.constant];
            }
            if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                opline->op2.constant = map[opline->op2.constant];
            }
            opline++;
        }
        zend_arena_release(&ctx->arena, checkpoint);

#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_dtor(&zv);
                }
            }
            fflush(stderr);
        }
#endif
    }
}
コード例 #11
0
ファイル: php_ibase_udf.c プロジェクト: morafabio/php-src
static void call_php(char *name, PARAMDSC *r, int argc, PARAMDSC **argv)
{
	do {
		zval callback, args[4], return_value;
		PARAMVARY *res = (PARAMVARY*)r->dsc_address;
		int i;

		ZVAL_STRING(&callback, name);

		LOCK();

		/* check if the requested function exists */
		if (!zend_is_callable(&callback, 0, NULL)) {
			break;
		}

		UNLOCK();

		/* create the argument array */
		for (i = 0; i < argc; ++i) {

			/* test arg for null */
			if (argv[i]->dsc_flags & DSC_null) {
				ZVAL_NULL(&args[i]);
				continue;
			}

			switch (argv[i]->dsc_dtype) {
				ISC_INT64 l;
				struct tm t;
				char const *fmt;
				char d[64];

				case dtype_cstring:
//???
					ZVAL_STRING(&args[i], (char*)argv[i]->dsc_address);
					break;

				case dtype_text:
//???
					ZVAL_STRINGL(&args[i], (char*)argv[i]->dsc_address, argv[i]->dsc_length);
					break;

				case dtype_varying:
//???
					ZVAL_STRINGL(&args[i], ((PARAMVARY*)argv[i]->dsc_address)->vary_string,
						((PARAMVARY*)argv[i]->dsc_address)->vary_length);
					break;

				case dtype_short:
					if (argv[i]->dsc_scale == 0) {
						ZVAL_LONG(&args[i], *(short*)argv[i]->dsc_address);
					} else {
						ZVAL_DOUBLE(&args[i],
							((double)*(short*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]);
					}
					break;

				case dtype_long:
					if (argv[i]->dsc_scale == 0) {
						ZVAL_LONG(&args[i], *(ISC_LONG*)argv[i]->dsc_address);
					} else {
						ZVAL_DOUBLE(&args[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(&args[i], (long)l);
					} else {
						ZVAL_DOUBLE(&args[i], ((double)l)/scales[-argv[i]->dsc_scale]);
					}
					break;

				case dtype_real:
					ZVAL_DOUBLE(&args[i], *(float*)argv[i]->dsc_address);
					break;

				case dtype_double:
					ZVAL_DOUBLE(&args[i], *(double*)argv[i]->dsc_address);
					break;

				case dtype_sql_date:
					isc_decode_sql_date((ISC_DATE*)argv[i]->dsc_address, &t);
					ZVAL_STRINGL(&args[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(&args[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(&args[i], d, strftime(d, sizeof(d), INI_STR("ibase.timestampformat"), &t));
					break;
			}
		}

		LOCK();

		/* now call the function */
		if (FAILURE == call_user_function(EG(function_table), NULL,
				&callback, &return_value, argc, args)) {
			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(&args[i]);
			}
		}

		zval_dtor(&callback);

		/* 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, E_WARNING, "Error calling function '%s' from database", name);
	UNLOCK();
}
コード例 #12
0
ファイル: lua_closure.c プロジェクト: laruence/php-lua
/** {{{ proto LuaClosure::invoke(mxied $args)
*/
PHP_METHOD(lua_closure, invoke) {
	lua_closure_object *objval = php_lua_closure_object_from_zend_object(Z_OBJ_P(getThis()));
	int bp, sp;
	zval *arguments = NULL;
	lua_State *L  = NULL;
	zval rv;

	if (ZEND_NUM_ARGS()) {
		arguments = emalloc(sizeof(zval*) * ZEND_NUM_ARGS());
		if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) {
			efree(arguments);
			zend_throw_exception_ex(NULL, 0, "cannot get arguments for calling closure");
			return;
		}
	}

	if (Z_TYPE(objval->lua) != IS_OBJECT
			|| !instanceof_function(Z_OBJCE(objval->lua), lua_ce)) {
		zend_throw_exception_ex(NULL, 0, "corrupted Lua object");
		return;
	}

	L = (Z_LUAVAL(objval->lua))->L;

	bp = lua_gettop(L);
	lua_rawgeti(L, LUA_REGISTRYINDEX, objval->closure);
	if (LUA_TFUNCTION != lua_type(L, lua_gettop(L))) {
		lua_pop(L, -1);
		zend_throw_exception_ex(NULL, 0, "call to lua closure failed");
		return;
	}

	if (ZEND_NUM_ARGS()) {
		int i = 0;
		for(;i<ZEND_NUM_ARGS();i++) {
			php_lua_send_zval_to_lua(L, &arguments[i]);
		}
	}

	if (lua_pcall(L, ZEND_NUM_ARGS(), LUA_MULTRET, 0) != 0) {
		if (arguments) {
			efree(arguments);
		}
		lua_pop(L, lua_gettop(L) - bp);
		zend_throw_exception_ex(NULL, 0, 
				"call to lua function %s failed", lua_tostring(L, -1));
		return;
	}

	sp = lua_gettop(L) - bp;

	if (!sp) {
		RETURN_NULL();
	} else if (sp == 1) {
		php_lua_get_zval_from_lua(L, -1, &(objval->lua), return_value);
	} else {
		zval rv;
		int  i = 0;
		array_init(return_value);
		for (i = -sp; i < 0; i++) {
			php_lua_get_zval_from_lua(L, i, &(objval->lua), &rv);
			add_next_index_zval(return_value, &rv);
		}
	}

	lua_pop(L, sp);

	if (arguments) {
		efree(arguments);
	}
}
コード例 #13
0
ファイル: apc_cache.c プロジェクト: Cum6upck/apcu
static APC_HOTSPOT HashTable* my_copy_hashtable(HashTable *source, apc_context_t *ctxt) {
	uint32_t idx;
	HashTable *target;
	apc_pool *pool = ctxt->pool;

	if (ctxt->copy == APC_COPY_IN) {
		target = (HashTable*) pool->palloc(pool, sizeof(HashTable));
	} else ALLOC_HASHTABLE(target);

	GC_REFCOUNT(target) = 1;
	GC_TYPE_INFO(target) = IS_ARRAY;
    zend_hash_index_update_ptr(&ctxt->copied, (uintptr_t) source, target);

	target->nTableSize = source->nTableSize;
	target->pDestructor = source->pDestructor;

	if (source->nNumUsed == 0) {
		target->u.flags = (source->u.flags & ~(HASH_FLAG_INITIALIZED|HASH_FLAG_PACKED|HASH_FLAG_PERSISTENT)) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS;
		target->nTableMask = HT_MIN_MASK;
		target->nNumUsed = 0;
		target->nNumOfElements = 0;
		target->nNextFreeElement = 0;
		target->nInternalPointer = HT_INVALID_IDX;
		HT_SET_DATA_ADDR(target, &uninitialized_bucket);
	} else if (GC_FLAGS(source) & IS_ARRAY_IMMUTABLE) {
		target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
		target->nTableMask = source->nTableMask;
		target->nNumUsed = source->nNumUsed;
		target->nNumOfElements = source->nNumOfElements;
		target->nNextFreeElement = source->nNextFreeElement;
		if (ctxt->copy == APC_COPY_IN) {
			HT_SET_DATA_ADDR(target, pool->palloc(pool, HT_SIZE(target)));
		} else HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
		target->nInternalPointer = source->nInternalPointer;
		memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_USED_SIZE(source));
		if (target->nNumOfElements > 0 &&
			target->nInternalPointer == HT_INVALID_IDX) {
			idx = 0;
			while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
				idx++;
			}
			target->nInternalPointer = idx;
		}
	} else if (source->u.flags & HASH_FLAG_PACKED) {
		target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
		target->nTableMask = source->nTableMask;
		target->nNumUsed = source->nNumUsed;
		target->nNumOfElements = source->nNumOfElements;
		target->nNextFreeElement = source->nNextFreeElement;
		if (ctxt->copy == APC_COPY_IN) {
			HT_SET_DATA_ADDR(target, pool->palloc(pool, HT_SIZE(target)));
		} else	HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
		target->nInternalPointer = source->nInternalPointer;
		HT_HASH_RESET_PACKED(target);

		if (target->nNumUsed == target->nNumOfElements) {
			apc_array_dup_packed_elements(ctxt, source, target, 0);
		} else {
			apc_array_dup_packed_elements(ctxt, source, target, 1);
		}
		if (target->nNumOfElements > 0 &&
			target->nInternalPointer == HT_INVALID_IDX) {
			idx = 0;
			while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
				idx++;
			}
			target->nInternalPointer = idx;
		}
	} else {
		target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
		target->nTableMask = source->nTableMask;
		target->nNextFreeElement = source->nNextFreeElement;
		target->nInternalPointer = HT_INVALID_IDX;
		if (ctxt->copy == APC_COPY_IN) {
			HT_SET_DATA_ADDR(target, pool->palloc(pool, HT_SIZE(target)));
		} else HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
		HT_HASH_RESET(target);

		if (target->u.flags & HASH_FLAG_STATIC_KEYS) {
			if (source->nNumUsed == source->nNumOfElements) {
				idx = apc_array_dup_elements(ctxt, source, target, 1, 0);
			} else {
				idx = apc_array_dup_elements(ctxt, source, target, 1, 1);
			}
		} else {
			if (source->nNumUsed == source->nNumOfElements) {
				idx = apc_array_dup_elements(ctxt, source, target, 0, 0);
			} else {
				idx = apc_array_dup_elements(ctxt, source, target, 0, 1);
			}
		}
		target->nNumUsed = idx;
		target->nNumOfElements = idx;
		if (idx > 0 && target->nInternalPointer == HT_INVALID_IDX) {
			target->nInternalPointer = 0;
		}
	}
	return target;
}
コード例 #14
0
ファイル: apc_cache.c プロジェクト: Cum6upck/apcu
/* {{{ apc_cache_update */
PHP_APCU_API zend_bool apc_cache_update(apc_cache_t* cache, zend_string *key, apc_cache_updater_t updater, void* data)
{
    apc_cache_slot_t** slot;
    apc_cache_entry_t tmp_entry;
	
    zend_bool retval = 0;
    zend_ulong h, s;

    if(apc_cache_busy(cache))
    {
        /* cannot service request right now */ 
        return 0;
    }

    /* calculate hash */
    apc_cache_hash_slot(cache, key, &h, &s);
	
	/* lock header */
	APC_LOCK(cache->header);

	/* find head */
    slot = &cache->slots[s];

    while (*slot) {
		/* check for a match by hash and identifier */
        if ((h == ZSTR_HASH((*slot)->key.str)) &&
            memcmp(ZSTR_VAL((*slot)->key.str), ZSTR_VAL(key), ZSTR_LEN(key)) == SUCCESS) {
			/* attempt to perform update */
            switch(Z_TYPE((*slot)->value->val)) {
                case IS_ARRAY:
                case IS_OBJECT:
                {
                    if(cache->serializer) {
                        retval = 0;
                        break;
                    }
                }

                /* break intentionally omitted */

                default:
                {
					/* executing update */
                    retval = updater(cache, (*slot)->value, data);
					/* set modified time */
                    (*slot)->key.mtime = apc_time();
                }
                break;
            }
			/* unlock header */
			APC_UNLOCK(cache->header);

            return retval;
        }

		/* set next slot */
        slot = &(*slot)->next;
	}

	/* unlock header */
	APC_UNLOCK(cache->header);

	/* failed to find matching entry, create it */
	ZVAL_LONG(&tmp_entry.val, 0);
	updater(cache, &tmp_entry, data);

	if(apc_cache_store(cache, key, &tmp_entry.val, 0, 0)) {
		return 1;
	}

    return 0;
}
コード例 #15
0
ファイル: zend_closures.c プロジェクト: 545191228/php-src
/* {{{ proto mixed Closure::call(object to [, mixed parameter] [, mixed ...] )
   Call closure, binding to a given object with its class as the scope */
ZEND_METHOD(Closure, call)
{
	zval *zclosure, *newthis, closure_result;
	zend_closure *closure;
	zend_fcall_info fci;
	zend_fcall_info_cache fci_cache;
	zval *my_params;
	int my_param_count = 0;
	zend_function my_function;
	zend_object *newobj;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "o*", &newthis, &my_params, &my_param_count) == FAILURE) {
		return;
	}

	zclosure = getThis();
	closure = (zend_closure *) Z_OBJ_P(zclosure);

	newobj = Z_OBJ_P(newthis);

	if (!zend_valid_closure_binding(closure, newthis, Z_OBJCE_P(newthis))) {
		return;
	}

	/* This should never happen as closures will always be callable */
	if (zend_fcall_info_init(zclosure, 0, &fci, &fci_cache, NULL, NULL) != SUCCESS) {
		ZEND_ASSERT(0);
	}

	fci.retval = &closure_result;
	fci.params = my_params;
	fci.param_count = my_param_count;
	fci.object = fci_cache.object = newobj;
	fci_cache.initialized = 1;
	fci_cache.called_scope = Z_OBJCE_P(newthis);

	if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) {
		zval new_closure;
		zend_create_closure(&new_closure, fci_cache.function_handler, Z_OBJCE_P(newthis), closure->called_scope, newthis);
		closure = (zend_closure *) Z_OBJ(new_closure);
		fci_cache.function_handler = &closure->func;
	} else {
		memcpy(&my_function, fci_cache.function_handler, fci_cache.function_handler->type == ZEND_USER_FUNCTION ? sizeof(zend_op_array) : sizeof(zend_internal_function));
		/* use scope of passed object */
		my_function.common.scope = Z_OBJCE_P(newthis);
		fci_cache.function_handler = &my_function;

		/* Runtime cache relies on bound scope to be immutable, hence we need a separate rt cache in case scope changed */
		if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) {
			my_function.op_array.run_time_cache = emalloc(my_function.op_array.cache_size);
			memset(my_function.op_array.run_time_cache, 0, my_function.op_array.cache_size);
		}
	}

	if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(closure_result) != IS_UNDEF) {
		ZVAL_COPY_VALUE(return_value, &closure_result);
	}

	if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) {
		/* copied upon generator creation */
		--GC_REFCOUNT(&closure->std);
	} else if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) {
		efree(my_function.op_array.run_time_cache);
	}
}
コード例 #16
0
U_CFUNC PHP_FUNCTION(intlcal_set)
{
	zend_long	arg1, arg2, arg3, arg4, arg5, arg6;
	zval	args_a[7] = {0},
			*args = args_a;
	int		i;
	int		variant; /* number of args of the set() overload */
	CALENDAR_METHOD_INIT_VARS;

	/* must come before zpp because zpp would convert the args in the stack to 0 */
	if (ZEND_NUM_ARGS() > (getThis() ? 6 : 7) ||
				zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
			"intlcal_set: too many arguments", 0 TSRMLS_CC);
		RETURN_FALSE;
	}
	if (!getThis()) {
		args++;
	}
	variant = ZEND_NUM_ARGS() - (getThis() ? 0 : 1);
	while (variant > 2 && Z_TYPE(args[variant - 1]) == IS_NULL) {
		variant--;
	}

	if (variant == 4 ||
			zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
			"Oll|llll",	&object, Calendar_ce_ptr, &arg1, &arg2, &arg3, &arg4,
			&arg5, &arg6) == FAILURE) {
		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
			"intlcal_set: bad arguments", 0 TSRMLS_CC);
		RETURN_FALSE;
	}
	
	for (i = 0; i < variant; i++) {
		if (Z_LVAL(args[i]) < INT32_MIN || Z_LVAL(args[i]) > INT32_MAX) {
			intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
				"intlcal_set: at least one of the arguments has an absolute "
				"value that is too large", 0 TSRMLS_CC);
			RETURN_FALSE;
		}
	}

	if (variant == 2 && (arg1 < 0 || arg1 >= UCAL_FIELD_COUNT)) {
		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
			"intlcal_set: invalid field", 0 TSRMLS_CC);
		RETURN_FALSE;
	}

	CALENDAR_METHOD_FETCH_OBJECT;

	if (variant == 2) {
		co->ucal->set((UCalendarDateFields)arg1, (int32_t)arg2);
	} else if (variant == 3) {
		co->ucal->set((int32_t)arg1, (int32_t)arg2, (int32_t)arg3);
	} else if (variant == 5) {
		co->ucal->set((int32_t)arg1, (int32_t)arg2, (int32_t)arg3, (int32_t)arg4, (int32_t)arg5);
	} else if (variant == 6) {
		co->ucal->set((int32_t)arg1, (int32_t)arg2, (int32_t)arg3, (int32_t)arg4, (int32_t)arg5, (int32_t)arg6);
	}
	
	RETURN_TRUE;
}
コード例 #17
0
ファイル: zend_highlight.c プロジェクト: AxiosCros/php-src
ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini)
{
	zval token;
	int token_type;
	char *last_color = syntax_highlighter_ini->highlight_html;
	char *next_color;

	zend_printf("<code>");
	zend_printf("<span style=\"color: %s\">\n", last_color);
	/* highlight stuff coming back from zendlex() */
	ZVAL_UNDEF(&token);
	while ((token_type=lex_scan(&token))) {
		switch (token_type) {
			case T_INLINE_HTML:
				next_color = syntax_highlighter_ini->highlight_html;
				break;
			case T_COMMENT:
			case T_DOC_COMMENT:
				next_color = syntax_highlighter_ini->highlight_comment;
				break;
			case T_OPEN_TAG:
			case T_OPEN_TAG_WITH_ECHO:
			case T_CLOSE_TAG:
			case T_LINE:
			case T_FILE:
			case T_DIR:
			case T_TRAIT_C:
			case T_METHOD_C:
			case T_FUNC_C:
			case T_NS_C:
			case T_CLASS_C:
				next_color = syntax_highlighter_ini->highlight_default;
				break;
			case '"':
			case T_ENCAPSED_AND_WHITESPACE:
			case T_CONSTANT_ENCAPSED_STRING:
				next_color = syntax_highlighter_ini->highlight_string;
				break;
			case T_WHITESPACE:
				zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));  /* no color needed */
				ZVAL_UNDEF(&token);
				continue;
				break;
			default:
				if (Z_TYPE(token) == IS_UNDEF) {
					next_color = syntax_highlighter_ini->highlight_keyword;
				} else {
					next_color = syntax_highlighter_ini->highlight_default;
				}
				break;
		}

		if (last_color != next_color) {
			if (last_color != syntax_highlighter_ini->highlight_html) {
				zend_printf("</span>");
			}
			last_color = next_color;
			if (last_color != syntax_highlighter_ini->highlight_html) {
				zend_printf("<span style=\"color: %s\">", last_color);
			}
		}

		zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));

		if (Z_TYPE(token) == IS_STRING) {
			switch (token_type) {
				case T_OPEN_TAG:
				case T_OPEN_TAG_WITH_ECHO:
				case T_CLOSE_TAG:
				case T_WHITESPACE:
				case T_COMMENT:
				case T_DOC_COMMENT:
					break;
				default:
					zend_string_release(Z_STR(token));
					break;
			}
		}
		ZVAL_UNDEF(&token);
	}

	if (last_color != syntax_highlighter_ini->highlight_html) {
		zend_printf("</span>\n");
	}
	zend_printf("</span>\n");
	zend_printf("</code>");

	/* Discard parse errors thrown during tokenization */
	zend_clear_exception();
}
コード例 #18
0
ファイル: php_variables.c プロジェクト: guggemand/php-src
PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array)
{
	char *p = NULL;
	char *ip = NULL;		/* index pointer */
	char *index;
	char *var, *var_orig;
	size_t var_len, index_len;
	zval gpc_element, *gpc_element_p;
	zend_bool is_array = 0;
	HashTable *symtable1 = NULL;
	ALLOCA_FLAG(use_heap)

	assert(var_name != NULL);

	if (track_vars_array && Z_TYPE_P(track_vars_array) == IS_ARRAY) {
		symtable1 = Z_ARRVAL_P(track_vars_array);
	}

	if (!symtable1) {
		/* Nothing to do */
		zval_dtor(val);
		return;
	}


	/* ignore leading spaces in the variable name */
	while (*var_name && *var_name==' ') {
		var_name++;
	}

	/*
	 * Prepare variable name
	 */
	var_len = strlen(var_name);
	var = var_orig = do_alloca(var_len + 1, use_heap);
	memcpy(var_orig, var_name, var_len + 1);

	/* ensure that we don't have spaces or dots in the variable name (not binary safe) */
	for (p = var; *p; p++) {
		if (*p == ' ' || *p == '.') {
			*p='_';
		} else if (*p == '[') {
			is_array = 1;
			ip = p;
			*p = 0;
			break;
		}
	}
	var_len = p - var;

	if (var_len==0) { /* empty variable name, or variable name with a space in it */
		zval_dtor(val);
		free_alloca(var_orig, use_heap);
		return;
	}

	/* GLOBALS hijack attempt, reject parameter */
	if (symtable1 == &EG(symbol_table) &&
		var_len == sizeof("GLOBALS")-1 &&
		!memcmp(var, "GLOBALS", sizeof("GLOBALS")-1)) {
		zval_dtor(val);
		free_alloca(var_orig, use_heap);
		return;
	}

	index = var;
	index_len = var_len;

	if (is_array) {
		int nest_level = 0;
		while (1) {
			char *index_s;
			size_t new_idx_len = 0;

			if(++nest_level > PG(max_input_nesting_level)) {
				HashTable *ht;
				/* too many levels of nesting */

				if (track_vars_array) {
					ht = Z_ARRVAL_P(track_vars_array);
					zend_symtable_str_del(ht, var, var_len);
				}

				zval_dtor(val);

				/* do not output the error message to the screen,
				 this helps us to to avoid "information disclosure" */
				if (!PG(display_errors)) {
					php_error_docref(NULL, E_WARNING, "Input variable nesting level exceeded " ZEND_LONG_FMT ". To increase the limit change max_input_nesting_level in php.ini.", PG(max_input_nesting_level));
				}
				free_alloca(var_orig, use_heap);
				return;
			}

			ip++;
			index_s = ip;
			if (isspace(*ip)) {
				ip++;
			}
			if (*ip==']') {
				index_s = NULL;
			} else {
				ip = strchr(ip, ']');
				if (!ip) {
					/* PHP variables cannot contain '[' in their names, so we replace the character with a '_' */
					*(index_s - 1) = '_';

					index_len = 0;
					if (index) {
						index_len = strlen(index);
					}
					goto plain_var;
					return;
				}
				*ip = 0;
				new_idx_len = strlen(index_s);
			}

			if (!index) {
				array_init(&gpc_element);
				if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) {
					zval_ptr_dtor(&gpc_element);
					zval_dtor(val);
					free_alloca(var_orig, use_heap);
					return;
				}
			} else {
				gpc_element_p = zend_symtable_str_find(symtable1, index, index_len);
				if (!gpc_element_p) {
					zval tmp;
					array_init(&tmp);
					gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &tmp);
				} else {
					if (Z_TYPE_P(gpc_element_p) == IS_INDIRECT) {
						gpc_element_p = Z_INDIRECT_P(gpc_element_p);
					}
					if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) {
						zval_ptr_dtor(gpc_element_p);
						array_init(gpc_element_p);
					}
				}
			}
			symtable1 = Z_ARRVAL_P(gpc_element_p);
			/* ip pointed to the '[' character, now obtain the key */
			index = index_s;
			index_len = new_idx_len;

			ip++;
			if (*ip == '[') {
				is_array = 1;
				*ip = 0;
			} else {
				goto plain_var;
			}
		}
	} else {
plain_var:
		ZVAL_COPY_VALUE(&gpc_element, val);
		if (!index) {
			if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) {
				zval_ptr_dtor(&gpc_element);
			}
		} else {
			/*
			 * According to rfc2965, more specific paths are listed above the less specific ones.
			 * If we encounter a duplicate cookie name, we should skip it, since it is not possible
			 * to have the same (plain text) cookie name for the same path and we should not overwrite
			 * more specific cookies with the less specific ones.
			 */
			if (Z_TYPE(PG(http_globals)[TRACK_VARS_COOKIE]) != IS_UNDEF &&
				symtable1 == Z_ARRVAL(PG(http_globals)[TRACK_VARS_COOKIE]) &&
				zend_symtable_str_exists(symtable1, index, index_len)) {
				zval_ptr_dtor(&gpc_element);
			} else {
				gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &gpc_element);
			}
		}
	}
	free_alloca(var_orig, use_heap);
}
コード例 #19
0
ファイル: user_filters.c プロジェクト: WarnerBe/php-src
php_stream_filter_status_t userfilter_filter(
			php_stream *stream,
			php_stream_filter *thisfilter,
			php_stream_bucket_brigade *buckets_in,
			php_stream_bucket_brigade *buckets_out,
			size_t *bytes_consumed,
			int flags
			)
{
	int ret = PSFS_ERR_FATAL;
	zval *obj = &thisfilter->abstract;
	zval func_name;
	zval retval;
	zval args[4];
	zval zpropname;
	int call_result;

	/* the userfilter object probably doesn't exist anymore */
	if (CG(unclean_shutdown)) {
		return ret;
	}

	if (!zend_hash_str_exists_ind(Z_OBJPROP_P(obj), "stream", sizeof("stream")-1)) {
		zval tmp;

		/* Give the userfilter class a hook back to the stream */
		php_stream_to_zval(stream, &tmp);
		Z_ADDREF(tmp);
		add_property_zval(obj, "stream", &tmp);
		/* add_property_zval increments the refcount which is unwanted here */
		zval_ptr_dtor(&tmp);
	}

	ZVAL_STRINGL(&func_name, "filter", sizeof("filter")-1);

	/* Setup calling arguments */
	ZVAL_RES(&args[0], zend_register_resource(buckets_in, le_bucket_brigade));
	ZVAL_RES(&args[1], zend_register_resource(buckets_out, le_bucket_brigade));

	if (bytes_consumed) {
		ZVAL_LONG(&args[2], *bytes_consumed);
	} else {
		ZVAL_NULL(&args[2]);
	}

	ZVAL_BOOL(&args[3], flags & PSFS_FLAG_FLUSH_CLOSE);

	call_result = call_user_function_ex(NULL,
			obj,
			&func_name,
			&retval,
			4, args,
			0, NULL);

	zval_ptr_dtor(&func_name);

	if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
		convert_to_long(&retval);
		ret = (int)Z_LVAL(retval);
	} else if (call_result == FAILURE) {
		php_error_docref(NULL, E_WARNING, "failed to call filter function");
	}

	if (bytes_consumed) {
		*bytes_consumed = zval_get_long(&args[2]);
	}

	if (buckets_in->head) {
		php_stream_bucket *bucket = buckets_in->head;

		php_error_docref(NULL, E_WARNING, "Unprocessed filter buckets remaining on input brigade");
		while ((bucket = buckets_in->head)) {
			/* Remove unconsumed buckets from the brigade */
			php_stream_bucket_unlink(bucket);
			php_stream_bucket_delref(bucket);
		}
	}
	if (ret != PSFS_PASS_ON) {
		php_stream_bucket *bucket = buckets_out->head;
		while (bucket != NULL) {
			php_stream_bucket_unlink(bucket);
			php_stream_bucket_delref(bucket);
			bucket = buckets_out->head;
		}
	}

	/* filter resources are cleaned up by the stream destructor,
	 * keeping a reference to the stream resource here would prevent it
	 * from being destroyed properly */
	ZVAL_STRINGL(&zpropname, "stream", sizeof("stream")-1);
	Z_OBJ_HANDLER_P(obj, unset_property)(obj, &zpropname, NULL);
	zval_ptr_dtor(&zpropname);

	zval_ptr_dtor(&args[3]);
	zval_ptr_dtor(&args[2]);
	zval_ptr_dtor(&args[1]);
	zval_ptr_dtor(&args[0]);

	return ret;
}
コード例 #20
0
ファイル: file.c プロジェクト: dreamsxin/cphalcon7
/**
 * Executes the validation
 *
 * @param string $file
 * @param int $minsize
 * @param int $maxsize
 * @param array $mimes
 * @param int $minwidth
 * @param int $maxwidth
 * @param int $minheight
 * @param int $maxheight
 * @return boolean
 */
PHP_METHOD(Phalcon_Validation_Validator_File, valid)
{
	zval *value, *minsize = NULL, *maxsize = NULL, *mimes = NULL, *minwidth = NULL, *maxwidth = NULL, *minheight = NULL, *maxheight = NULL;
	zval file = {}, size = {}, *constant, finfo = {}, pathname = {}, mime = {}, image = {}, imageinfo = {}, width = {}, height = {}, valid = {};
	zend_class_entry *imagick_ce;

	phalcon_fetch_params(0, 1, 7, &value, &minsize, &maxsize, &mimes, &minwidth, &maxwidth, &minheight, &maxheight);

	if (Z_TYPE_P(value) == IS_STRING) {
		object_init_ex(&file, spl_ce_SplFileInfo);
		if (phalcon_has_constructor(&file)) {
			PHALCON_CALL_METHODW(NULL, &file, "__construct", value);
		}
	} else if (Z_TYPE_P(value) == IS_OBJECT && instanceof_function_ex(Z_OBJCE_P(value), spl_ce_SplFileInfo, 0)) {
		PHALCON_CPY_WRT(&file, value);
	}

	if (Z_TYPE(file) <= IS_NULL) {
		phalcon_update_property_str(getThis(), SL("_type"), SL("TypeUnknow"));
		RETURN_FALSE;
	}

	if (!minsize) {
		minsize = &PHALCON_GLOBAL(z_null);
	}

	if (!maxsize) {
		maxsize = &PHALCON_GLOBAL(z_null);
	}

	if (!mimes) {
		mimes = &PHALCON_GLOBAL(z_null);
	}

	if (!minwidth) {
		minwidth = &PHALCON_GLOBAL(z_null);
	}

	if (!maxwidth) {
		maxwidth = &PHALCON_GLOBAL(z_null);
	}

	if (!minheight) {
		minheight = &PHALCON_GLOBAL(z_null);
	}

	if (!maxheight) {
		maxheight = &PHALCON_GLOBAL(z_null);
	}

	PHALCON_CALL_METHODW(&valid, &file, "isfile");

	if (!zend_is_true(&valid)) {
		phalcon_update_property_str(getThis(), SL("_type"), SL("FileValid"));
		RETURN_FALSE;
	}

	PHALCON_CALL_METHODW(&size, &file, "getsize");

	if (!PHALCON_IS_EMPTY(minsize)) {
		is_smaller_or_equal_function(&valid, minsize, &size);
		if (!zend_is_true(&valid)) {
			phalcon_update_property_str(getThis(), SL("_type"), SL("TooSmall"));
			RETURN_FALSE;
		}
	}

	if (!PHALCON_IS_EMPTY(maxsize)) {
		is_smaller_or_equal_function(&valid, &size, maxsize);
		if (!zend_is_true(&valid)) {
			phalcon_update_property_str(getThis(), SL("_type"), SL("TooLarge"));
			RETURN_FALSE;
		}
	}

	PHALCON_CALL_METHODW(&pathname, &file, "getpathname");

	if (Z_TYPE_P(mimes) == IS_ARRAY) {
		if ((constant = zend_get_constant_str(SL("FILEINFO_MIME_TYPE"))) == NULL) {
			PHALCON_THROW_EXCEPTION_STRW(phalcon_validation_exception_ce, "Undefined constant `FILEINFO_MIME_TYPE`");
			return;
		}

		PHALCON_CALL_FUNCTIONW(&finfo, "finfo_open", constant);

		if (Z_TYPE(finfo) != IS_RESOURCE) {
			PHALCON_THROW_EXCEPTION_STRW(phalcon_validation_exception_ce, "Opening fileinfo database failed");
			return;
		}		

		PHALCON_CALL_FUNCTIONW(&mime, "finfo_file", &finfo, &pathname);
		PHALCON_CALL_FUNCTIONW(NULL, "finfo_close", &finfo);
		
		if (!phalcon_fast_in_array(&mime, mimes)) {
			phalcon_update_property_str(getThis(), SL("_type"), SL("MimeValid"));
			RETURN_FALSE;
		}
	}

	if (phalcon_class_str_exists(SL("imagick"), 0) != NULL) {
		imagick_ce = phalcon_fetch_str_class(SL("Imagick"), ZEND_FETCH_CLASS_AUTO);

		object_init_ex(&image, imagick_ce);
		PHALCON_CALL_METHODW(NULL, &image, "__construct", &pathname);

		PHALCON_CALL_METHODW(&width, &image, "getImageWidth");
		PHALCON_CALL_METHODW(&height, &image, "getImageHeight");
	} else if (phalcon_function_exists_ex(SL("getimagesize")) != FAILURE) {
		PHALCON_CALL_FUNCTIONW(&imageinfo, "getimagesize", &pathname);
		if (!phalcon_array_isset_fetch_long(&width, &imageinfo, 0)) {
			ZVAL_LONG(&width, -1);
		}

		if (!phalcon_array_isset_fetch_long(&height, &imageinfo, 1)) {
			ZVAL_LONG(&height, -1);
		}
	} else {
		ZVAL_LONG(&width, -1);
		ZVAL_LONG(&height, -1);
	}

	if (!PHALCON_IS_EMPTY(minwidth)) {
		is_smaller_or_equal_function(&valid, minwidth, &width);
		if (!zend_is_true(&valid)) {
			phalcon_update_property_str(getThis(), SL("_type"), SL("TooNarrow"));
			RETURN_FALSE;
		}
	}

	if (!PHALCON_IS_EMPTY(maxwidth)) {
		is_smaller_or_equal_function(&valid, &width, maxwidth);
		if (!zend_is_true(&valid)) {
			phalcon_update_property_str(getThis(), SL("_type"), SL("TooWide"));
			RETURN_FALSE;
		}
	}

	if (!PHALCON_IS_EMPTY(minheight)) {
		is_smaller_or_equal_function(&valid, minheight, &height);
		if (!zend_is_true(&valid)) {
			phalcon_update_property_str(getThis(), SL("_type"), SL("TooShort"));
			RETURN_FALSE;
		}
	}

	if (!PHALCON_IS_EMPTY(maxheight)) {
		is_smaller_or_equal_function(&valid, &height, maxheight);
		if (!zend_is_true(&valid)) {
			phalcon_update_property_str(getThis(), SL("_type"), SL("TooLong"));
			RETURN_FALSE;
		}
	}

	RETURN_TRUE;
}
コード例 #21
0
ファイル: var_unserializer.c プロジェクト: erikjwaxx/php-src
static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
{
	while (elements-- > 0) {
		zval key, *data, d, *old_data;
		zend_ulong idx;

		ZVAL_UNDEF(&key);

		if (!php_var_unserialize_ex(&key, p, max, NULL, classes)) {
			zval_dtor(&key);
			return 0;
		}

		data = NULL;
		ZVAL_UNDEF(&d);

		if (!objprops) {
			if (Z_TYPE(key) == IS_LONG) {
				idx = Z_LVAL(key);
numeric_key:
				if (UNEXPECTED((old_data = zend_hash_index_find(ht, idx)) != NULL)) {
					//??? update hash
					var_push_dtor(var_hash, old_data);
					data = zend_hash_index_update(ht, idx, &d);
				} else {
					data = zend_hash_index_add_new(ht, idx, &d);
				}
			} else if (Z_TYPE(key) == IS_STRING) {
				if (UNEXPECTED(ZEND_HANDLE_NUMERIC(Z_STR(key), idx))) {
					goto numeric_key;
				}
				if (UNEXPECTED((old_data = zend_hash_find(ht, Z_STR(key))) != NULL)) {
					//??? update hash
					var_push_dtor(var_hash, old_data);
					data = zend_hash_update(ht, Z_STR(key), &d);
				} else {
					data = zend_hash_add_new(ht, Z_STR(key), &d);
				}
			} else {
				zval_dtor(&key);
				return 0;
			}
		} else {
			if (EXPECTED(Z_TYPE(key) == IS_STRING)) {
string_key:
				if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) {
					if (Z_TYPE_P(old_data) == IS_INDIRECT) {
						old_data = Z_INDIRECT_P(old_data);
					}
					var_push_dtor(var_hash, old_data);
					data = zend_hash_update_ind(ht, Z_STR(key), &d);
				} else {
					data = zend_hash_add_new(ht, Z_STR(key), &d);
				}
			} else if (Z_TYPE(key) == IS_LONG) {
				/* object properties should include no integers */
				convert_to_string(&key);
				goto string_key;
			} else {
				zval_dtor(&key);
				return 0;
			}
		}

		zval_dtor(&key);

		if (!php_var_unserialize_ex(data, p, max, var_hash, classes)) {
			return 0;
		}

		if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
			(*p)--;
			return 0;
		}
	}

	return 1;
}
コード例 #22
0
ファイル: file.c プロジェクト: dreamsxin/cphalcon7
/**
 * Executes the validation
 *
 * @param Phalcon\Validation $validator
 * @param string $attribute
 * @return boolean
 */
PHP_METHOD(Phalcon_Validation_Validator_File, validate)
{
	zval *validator, *attribute, value = {}, allow_empty = {}, mimes = {}, minsize = {}, maxsize = {}, minwidth = {}, maxwidth = {}, minheight = {}, maxheight = {};
	zval valid = {}, type = {}, code = {}, message_str = {}, message = {}, join_mimes = {}, label = {}, pairs = {}, prepared = {};
	zend_class_entry *ce = Z_OBJCE_P(getThis());

	phalcon_fetch_params(0, 2, 0, &validator, &attribute);

	PHALCON_VERIFY_CLASS_EX(validator, phalcon_validation_ce, phalcon_validation_exception_ce, 0);

	PHALCON_CALL_METHODW(&value, validator, "getvalue", attribute);

	RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&allow_empty, ce, getThis(), ISV(allowEmpty)));
	if (zend_is_true(&allow_empty) && phalcon_validation_validator_isempty_helper(&value)) {
		RETURN_TRUE;
	}

	RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&mimes, ce, getThis(), "mimes"));
	RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&minsize, ce, getThis(), "minsize"));
	RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&maxsize, ce, getThis(), "maxsize"));
	RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&minwidth, ce, getThis(), "minwidth"));
	RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&maxwidth, ce, getThis(), "maxwidth"));
	RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&minheight, ce, getThis(), "minheight"));
	RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&maxheight, ce, getThis(), "maxheight"));

	PHALCON_CALL_SELFW(&valid, "valid", &value, &minsize, &maxsize, &mimes, &minwidth, &maxwidth, &minheight, &maxheight);

	if (PHALCON_IS_FALSE(&valid)) {
		phalcon_return_property(&type, getThis(), SL("_type"));

		RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&label, ce, getThis(), ISV(label)));
		if (!zend_is_true(&label)) {
			PHALCON_CALL_METHODW(&label, validator, "getlabel", attribute);
			if (!zend_is_true(&label)) {
				PHALCON_CPY_WRT_CTOR(&label, attribute);
			}
		}

		RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&code, ce, getThis(), ISV(code)));
		if (Z_TYPE(code) == IS_NULL) {
			ZVAL_LONG(&code, 0);
		}

		array_init(&pairs);
		phalcon_array_update_str(&pairs, SL(":field"), &label, PH_COPY);

		if (phalcon_compare_strict_string(&type, SL("TooLarge"))) {
			phalcon_array_update_str(&pairs, SL(":max"), &maxsize, PH_COPY);

			RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&message_str, ce, getThis(), ISV(message)));
			if (!zend_is_true(&message_str)) {
				RETURN_ON_FAILURE(phalcon_validation_getdefaultmessage_helper(&message_str, Z_OBJCE_P(validator), validator, "FileMaxSize"));
			}

			PHALCON_CALL_FUNCTIONW(&prepared, "strtr", &message_str, &pairs);

			phalcon_validation_message_construct_helper(&message, &prepared, attribute, "TooLarge", &code);
		} else if (phalcon_compare_strict_string(&type, SL("TooSmall"))) {
			phalcon_array_update_str(&pairs, SL(":min"), &minsize, PH_COPY);

			RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&message_str, ce, getThis(), ISV(message)));
			if (!zend_is_true(&message_str)) {
				RETURN_ON_FAILURE(phalcon_validation_getdefaultmessage_helper(&message_str, Z_OBJCE_P(validator), validator, "FileMinSize"));
			}

			PHALCON_CALL_FUNCTIONW(&prepared, "strtr", &message_str, &pairs);

			phalcon_validation_message_construct_helper(&message, &prepared, attribute, "TooSmall", &code);
		} else if (phalcon_compare_strict_string(&type, SL("MimeValid"))) {
			phalcon_fast_join_str(&join_mimes, SL(", "), &mimes);
			phalcon_array_update_str(&pairs, SL(":mimes"), &join_mimes, PH_COPY);

			RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&message_str, ce, getThis(), ISV(message)));
			if (!zend_is_true(&message_str)) {
				RETURN_ON_FAILURE(phalcon_validation_getdefaultmessage_helper(&message_str, Z_OBJCE_P(validator), validator, "FileType"));
			}

			PHALCON_CALL_FUNCTIONW(&prepared, "strtr", &message_str, &pairs);

			phalcon_validation_message_construct_helper(&message, &prepared, attribute, "FileType", &code);
		} else if (phalcon_compare_strict_string(&type, SL("TooLarge"))) {
			phalcon_array_update_str(&pairs, SL(":max"), &maxsize, PH_COPY);

			RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&message_str, ce, getThis(), ISV(message)));
			if (!zend_is_true(&message_str)) {
				RETURN_ON_FAILURE(phalcon_validation_getdefaultmessage_helper(&message_str, Z_OBJCE_P(validator), validator, "FileMaxSize"));
			}

			PHALCON_CALL_FUNCTIONW(&prepared, "strtr", &message_str, &pairs);

			phalcon_validation_message_construct_helper(&message, &prepared, attribute, "TooLarge", &code);
		} else if (phalcon_compare_strict_string(&type, SL("TooNarrow"))) {
			phalcon_array_update_str(&pairs, SL(":min"), &minwidth, PH_COPY);

			RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&message_str, ce, getThis(), ISV(message)));
			if (!zend_is_true(&message_str)) {
				RETURN_ON_FAILURE(phalcon_validation_getdefaultmessage_helper(&message_str, Z_OBJCE_P(validator), validator, "ImageMinWidth"));
			}

			PHALCON_CALL_FUNCTIONW(&prepared, "strtr", &message_str, &pairs);

			phalcon_validation_message_construct_helper(&message, &prepared, attribute, "TooNarrow", &code);
		} else if (phalcon_compare_strict_string(&type, SL("TooWide"))) {
			phalcon_array_update_str(&pairs, SL(":max"), &maxwidth, PH_COPY);

			RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&message_str, ce, getThis(), ISV(message)));
			if (!zend_is_true(&message_str)) {
				RETURN_ON_FAILURE(phalcon_validation_getdefaultmessage_helper(&message_str, Z_OBJCE_P(validator), validator, "ImageMaxWidth"));
			}

			PHALCON_CALL_FUNCTIONW(&prepared, "strtr", &message_str, &pairs);

			phalcon_validation_message_construct_helper(&message, &prepared, attribute, "TooWide", &code);
		}  else if (phalcon_compare_strict_string(&type, SL("TooShort"))) {
			phalcon_array_update_str(&pairs, SL(":min"), &minheight, PH_COPY);

			RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&message_str, ce, getThis(), ISV(message)));
			if (!zend_is_true(&message_str)) {
				RETURN_ON_FAILURE(phalcon_validation_getdefaultmessage_helper(&message_str, Z_OBJCE_P(validator), validator, "ImageMinHeight"));
			}

			PHALCON_CALL_FUNCTIONW(&prepared, "strtr", &message_str, &pairs);

			phalcon_validation_message_construct_helper(&message, &prepared, attribute, "TooShort", &code);
		} else if (phalcon_compare_strict_string(&type, SL("TooLong"))) {
			phalcon_array_update_str(&pairs, SL(":max"), &maxheight, PH_COPY);

			RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&message_str, ce, getThis(), ISV(message)));
			if (!zend_is_true(&message_str)) {
				RETURN_ON_FAILURE(phalcon_validation_getdefaultmessage_helper(&message_str, Z_OBJCE_P(validator), validator, "ImageMaxHeight"));
			}

			PHALCON_CALL_FUNCTIONW(&prepared, "strtr", &message_str, &pairs);

			phalcon_validation_message_construct_helper(&message, &prepared, attribute, "TooLong", &code);
		} else {
			RETURN_ON_FAILURE(phalcon_validation_validator_getoption_helper(&message_str, ce, getThis(), ISV(message)));
			if (!zend_is_true(&message_str)) {
				RETURN_ON_FAILURE(phalcon_validation_getdefaultmessage_helper(&message_str, Z_OBJCE_P(validator), validator, "FileValid"));
			}

			PHALCON_CALL_FUNCTIONW(&prepared, "strtr", &message_str, &pairs);

			phalcon_validation_message_construct_helper(&message, &prepared, attribute, "File", &code);
		}

		PHALCON_CALL_METHODW(NULL, validator, "appendmessage", &message);
		RETURN_FALSE;
	}

	RETURN_TRUE;
}
コード例 #23
0
ファイル: sqlite_driver.c プロジェクト: WhoAmMe/php-src
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;
}
コード例 #24
0
ファイル: zend_optimizer.c プロジェクト: ahamid/php-src
int zend_accel_script_optimize(zend_persistent_script *script)
{
	uint idx, j;
	Bucket *p, *q;
	zend_class_entry *ce;
	zend_op_array *op_array;
	zend_optimizer_ctx ctx;

	ctx.arena = zend_arena_create(64 * 1024);
	ctx.script = script;
	ctx.constants = NULL;

	zend_accel_optimize(&script->main_op_array, &ctx);

	for (idx = 0; idx < script->function_table.nNumUsed; idx++) {
		p = script->function_table.arData + idx;
		if (Z_TYPE(p->val) == IS_UNDEF) continue;
		op_array = (zend_op_array*)Z_PTR(p->val);
		zend_accel_optimize(op_array, &ctx);
	}

	for (idx = 0; idx < script->class_table.nNumUsed; idx++) {
		p = script->class_table.arData + idx;
		if (Z_TYPE(p->val) == IS_UNDEF) continue;
		ce = (zend_class_entry*)Z_PTR(p->val);
		for (j = 0; j < ce->function_table.nNumUsed; j++) {
			q = ce->function_table.arData + j;
			if (Z_TYPE(q->val) == IS_UNDEF) continue;
			op_array = (zend_op_array*)Z_PTR(q->val);
			if (op_array->scope == ce) {
				zend_accel_optimize(op_array, &ctx);
			} else if (op_array->type == ZEND_USER_FUNCTION) {
				zend_op_array *orig_op_array;
				if ((orig_op_array = zend_hash_find_ptr(&op_array->scope->function_table, q->key)) != NULL) {
					HashTable *ht = op_array->static_variables;
					*op_array = *orig_op_array;
					op_array->static_variables = ht;
				}
			}
		}
	}

	if (ZEND_OPTIMIZER_PASS_12 & OPTIMIZATION_LEVEL) {
		zend_accel_adjust_fcall_stack_size(&script->main_op_array, &ctx);

		for (idx = 0; idx < script->function_table.nNumUsed; idx++) {
			p = script->function_table.arData + idx;
			if (Z_TYPE(p->val) == IS_UNDEF) continue;
			op_array = (zend_op_array*)Z_PTR(p->val);
			zend_accel_adjust_fcall_stack_size(op_array, &ctx);
		}

		for (idx = 0; idx < script->class_table.nNumUsed; idx++) {
			p = script->class_table.arData + idx;
			if (Z_TYPE(p->val) == IS_UNDEF) continue;
			ce = (zend_class_entry*)Z_PTR(p->val);
			for (j = 0; j < ce->function_table.nNumUsed; j++) {
				q = ce->function_table.arData + j;
				if (Z_TYPE(q->val) == IS_UNDEF) continue;
				op_array = (zend_op_array*)Z_PTR(q->val);
				if (op_array->scope == ce) {
					zend_accel_adjust_fcall_stack_size(op_array, &ctx);
				} else if (op_array->type == ZEND_USER_FUNCTION) {
					zend_op_array *orig_op_array;
					if ((orig_op_array = zend_hash_find_ptr(&op_array->scope->function_table, q->key)) != NULL) {
						HashTable *ht = op_array->static_variables;
						*op_array = *orig_op_array;
						op_array->static_variables = ht;
					}
				}
			}
		}
	}

	if (ctx.constants) {
		zend_hash_destroy(ctx.constants);
	}
	zend_arena_destroy(ctx.arena);

	return 1;
}
コード例 #25
0
ファイル: xpath.c プロジェクト: AmesianX/php-src
static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) /* {{{ */
{
	zval retval;
	int result, i;
	int error = 0;
	zend_fcall_info fci;
	xmlXPathObjectPtr obj;
	char *str;
	zend_string *callable = NULL;
	dom_xpath_object *intern;
	

	if (! zend_is_executing()) {
		xmlGenericError(xmlGenericErrorContext,
		"xmlExtFunctionTest: Function called from outside of PHP\n");
		error = 1;
	} else {
		intern = (dom_xpath_object *) ctxt->context->userData;
		if (intern == NULL) {
			xmlGenericError(xmlGenericErrorContext,
			"xmlExtFunctionTest: failed to get the internal object\n");
			error = 1;
		}
		else if (intern->registerPhpFunctions == 0) {
			xmlGenericError(xmlGenericErrorContext,
			"xmlExtFunctionTest: PHP Object did not register PHP functions\n");
			error = 1;
		}
	}
	
	if (error == 1) {
		for (i = nargs - 1; i >= 0; i--) {
			obj = valuePop(ctxt);
			xmlXPathFreeObject(obj);
		}
		return;
	}
		
	fci.param_count = nargs - 1;
	if (fci.param_count > 0) {
		fci.params = safe_emalloc(fci.param_count, sizeof(zval), 0);
	}
	/* Reverse order to pop values off ctxt stack */
	for (i = nargs - 2; i >= 0; i--) {
		obj = valuePop(ctxt);
		switch (obj->type) {
			case XPATH_STRING:
				ZVAL_STRING(&fci.params[i],  (char *)obj->stringval);
				break;
			case XPATH_BOOLEAN:
				ZVAL_BOOL(&fci.params[i],  obj->boolval);
				break;
			case XPATH_NUMBER:
				ZVAL_DOUBLE(&fci.params[i], obj->floatval);
				break;
			case XPATH_NODESET:
				if (type == 1) {
					str = (char *)xmlXPathCastToString(obj);
					ZVAL_STRING(&fci.params[i], str);
					xmlFree(str);
				} else if (type == 2) {
					int j;
					array_init(&fci.params[i]);
					if (obj->nodesetval && obj->nodesetval->nodeNr > 0) {
						for (j = 0; j < obj->nodesetval->nodeNr; j++) {
							xmlNodePtr node = obj->nodesetval->nodeTab[j];
							zval child;
							/* not sure, if we need this... it's copied from xpath.c */
							if (node->type == XML_NAMESPACE_DECL) {
								xmlNsPtr curns;
								xmlNodePtr nsparent;
								
								nsparent = node->_private;
								curns = xmlNewNs(NULL, node->name, NULL);
								if (node->children) {
									curns->prefix = xmlStrdup((xmlChar *) node->children);
								}
								if (node->children) {
									node = xmlNewDocNode(node->doc, NULL, (xmlChar *) node->children, node->name);
								} else {
									node = xmlNewDocNode(node->doc, NULL, (xmlChar *) "xmlns", node->name);
								}
								node->type = XML_NAMESPACE_DECL;
								node->parent = nsparent;
								node->ns = curns;
							}
							php_dom_create_object(node, &child, &intern->dom);
							add_next_index_zval(&fci.params[i], &child);
						}
					}
				}
				break;
			default:
			ZVAL_STRING(&fci.params[i], (char *)xmlXPathCastToString(obj));
		}
		xmlXPathFreeObject(obj);
	}
	
	fci.size = sizeof(fci);
	fci.function_table = EG(function_table);
	
	obj = valuePop(ctxt);
	if (obj->stringval == NULL) {
		php_error_docref(NULL, E_WARNING, "Handler name must be a string");
		xmlXPathFreeObject(obj);
		if (fci.param_count > 0) {
			for (i = 0; i < nargs - 1; i++) {
				zval_ptr_dtor(&fci.params[i]);
			}
			efree(fci.params);
		}
		return; 
	}
	ZVAL_STRING(&fci.function_name, (char *) obj->stringval);
	xmlXPathFreeObject(obj);

	fci.symbol_table = NULL;
	fci.object = NULL;
	fci.retval = &retval;
	fci.no_separation = 0;

	if (!zend_make_callable(&fci.function_name, &callable)) {
		php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", callable->val);
	} else if (intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable) == 0) { 
		php_error_docref(NULL, E_WARNING, "Not allowed to call handler '%s()'.", callable->val);
		/* Push an empty string, so that we at least have an xslt result... */
		valuePush(ctxt, xmlXPathNewString((xmlChar *)""));
	} else {
		result = zend_call_function(&fci, NULL);
		if (result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
			if (Z_TYPE(retval) == IS_OBJECT && instanceof_function(Z_OBJCE(retval), dom_node_class_entry)) {
				xmlNode *nodep;
				dom_object *obj;
				if (intern->node_list == NULL) {
					ALLOC_HASHTABLE(intern->node_list);
					zend_hash_init(intern->node_list, 0, NULL, ZVAL_PTR_DTOR, 0);
				}
				GC_REFCOUNT(&retval)++;
				zend_hash_next_index_insert(intern->node_list, &retval);
				obj = Z_DOMOBJ_P(&retval);
				nodep = dom_object_get_node(obj);
				valuePush(ctxt, xmlXPathNewNodeSet(nodep));
			} else if (Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE) {
				valuePush(ctxt, xmlXPathNewBoolean(Z_TYPE(retval) == IS_TRUE));
			} else if (Z_TYPE(retval) == IS_OBJECT) {
				php_error_docref(NULL, E_WARNING, "A PHP Object cannot be converted to a XPath-string");
				valuePush(ctxt, xmlXPathNewString((xmlChar *)""));
			} else {
				zend_string *str = zval_get_string(&retval);
				valuePush(ctxt, xmlXPathNewString((xmlChar *) str->val));
				zend_string_release(str);
			}
			zval_ptr_dtor(&retval);
		}
	}
	zend_string_release(callable);
	zval_dtor(&fci.function_name);
	if (fci.param_count > 0) {
		for (i = 0; i < nargs - 1; i++) {
			zval_ptr_dtor(&fci.params[i]);
		}
		efree(fci.params);
	}
}
コード例 #26
0
ファイル: xsltprocessor.c プロジェクト: EvgeniySpinov/php-src
static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) /* {{{ */
{
	xsltTransformContextPtr tctxt;
	zval *args;
	zval retval;
	int result, i;
	int error = 0;
	zend_fcall_info fci;
	zval handler;
	xmlXPathObjectPtr obj;
	char *str;
	xsl_object *intern;
	zend_string *callable = NULL;


	if (! zend_is_executing()) {
		xsltGenericError(xsltGenericErrorContext,
		"xsltExtFunctionTest: Function called from outside of PHP\n");
		error = 1;
	} else {
		tctxt = xsltXPathGetTransformContext(ctxt);
		if (tctxt == NULL) {
			xsltGenericError(xsltGenericErrorContext,
			"xsltExtFunctionTest: failed to get the transformation context\n");
			error = 1;
		} else {
			intern = (xsl_object*)tctxt->_private;
			if (intern == NULL) {
				xsltGenericError(xsltGenericErrorContext,
				"xsltExtFunctionTest: failed to get the internal object\n");
				error = 1;
			}
			else if (intern->registerPhpFunctions == 0) {
				xsltGenericError(xsltGenericErrorContext,
				"xsltExtFunctionTest: PHP Object did not register PHP functions\n");
				error = 1;
			}
		}
	}

	if (error == 1) {
		for (i = nargs - 1; i >= 0; i--) {
			obj = valuePop(ctxt);
			xmlXPathFreeObject(obj);
		}
		return;
	}

	fci.param_count = nargs - 1;
	if (fci.param_count > 0) {
		args = safe_emalloc(fci.param_count, sizeof(zval), 0);
	}
	/* Reverse order to pop values off ctxt stack */
	for (i = nargs - 2; i >= 0; i--) {
		obj = valuePop(ctxt);
		switch (obj->type) {
			case XPATH_STRING:
				ZVAL_STRING(&args[i], (char *)obj->stringval);
				break;
			case XPATH_BOOLEAN:
				ZVAL_BOOL(&args[i],  obj->boolval);
				break;
			case XPATH_NUMBER:
				ZVAL_DOUBLE(&args[i], obj->floatval);
				break;
			case XPATH_NODESET:
				if (type == 1) {
					str = (char*)xmlXPathCastToString(obj);
					ZVAL_STRING(&args[i], str);
					xmlFree(str);
				} else if (type == 2) {
					int j;
					dom_object *domintern = (dom_object *)intern->doc;
					array_init(&args[i]);
					if (obj->nodesetval && obj->nodesetval->nodeNr > 0) {
						for (j = 0; j < obj->nodesetval->nodeNr; j++) {
							xmlNodePtr node = obj->nodesetval->nodeTab[j];
							zval child;
							/* not sure, if we need this... it's copied from xpath.c */
							if (node->type == XML_NAMESPACE_DECL) {
								xmlNsPtr curns;
								xmlNodePtr nsparent;

								nsparent = node->_private;
								curns = xmlNewNs(NULL, node->name, NULL);
								if (node->children) {
									curns->prefix = xmlStrdup((char *)node->children);
								}
								if (node->children) {
									node = xmlNewDocNode(node->doc, NULL, (char *) node->children, node->name);
								} else {
									node = xmlNewDocNode(node->doc, NULL, "xmlns", node->name);
								}
								node->type = XML_NAMESPACE_DECL;
								node->parent = nsparent;
								node->ns = curns;
							} else {
								node = xmlDocCopyNodeList(domintern->document->ptr, node);
							}

							php_dom_create_object(node, &child, domintern);
							add_next_index_zval(&args[i], &child);
						}
					}
				}
				break;
			default:
				str = xmlXPathCastToString(obj);
				ZVAL_STRING(&args[i], str);
				xmlFree(str);
		}
		xmlXPathFreeObject(obj);
	}

	fci.size = sizeof(fci);
	fci.function_table = EG(function_table);
	if (fci.param_count > 0) {
		fci.params = args;
	} else {
		fci.params = NULL;
	}


	obj = valuePop(ctxt);
	if (obj->stringval == NULL) {
		php_error_docref(NULL, E_WARNING, "Handler name must be a string");
		xmlXPathFreeObject(obj);
		valuePush(ctxt, xmlXPathNewString(""));
		if (fci.param_count > 0) {
			for (i = 0; i < nargs - 1; i++) {
				zval_ptr_dtor(&args[i]);
			}
			efree(args);
		}
		return;
	}
	ZVAL_STRING(&handler, obj->stringval);
	xmlXPathFreeObject(obj);

	ZVAL_COPY_VALUE(&fci.function_name, &handler);
	fci.symbol_table = NULL;
	fci.object = NULL;
	fci.retval = &retval;
	fci.no_separation = 0;
	/*fci.function_handler_cache = &function_ptr;*/
	if (!zend_make_callable(&handler, &callable)) {
		php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", callable->val);
		valuePush(ctxt, xmlXPathNewString(""));
	} else if ( intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable) == 0) {
		php_error_docref(NULL, E_WARNING, "Not allowed to call handler '%s()'", callable->val);
		/* Push an empty string, so that we at least have an xslt result... */
		valuePush(ctxt, xmlXPathNewString(""));
	} else {
		result = zend_call_function(&fci, NULL);
		if (result == FAILURE) {
			if (Z_TYPE(handler) == IS_STRING) {
				php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", Z_STRVAL(handler));
				valuePush(ctxt, xmlXPathNewString(""));
			}
		/* retval is == NULL, when an exception occurred, don't report anything, because PHP itself will handle that */
		} else if (Z_ISUNDEF(retval)) {
		} else {
			if (Z_TYPE(retval) == IS_OBJECT && instanceof_function(Z_OBJCE(retval), dom_node_class_entry)) {
				xmlNode *nodep;
				dom_object *obj;
				if (intern->node_list == NULL) {
					ALLOC_HASHTABLE(intern->node_list);
					zend_hash_init(intern->node_list, 0, NULL, ZVAL_PTR_DTOR, 0);
				}
				Z_ADDREF(retval);
				zend_hash_next_index_insert(intern->node_list, &retval);
				obj = Z_DOMOBJ_P(&retval);
				nodep = dom_object_get_node(obj);
				valuePush(ctxt, xmlXPathNewNodeSet(nodep));
			} else if (Z_TYPE(retval) == IS_TRUE || Z_TYPE(retval) == IS_FALSE) {
				valuePush(ctxt, xmlXPathNewBoolean(Z_LVAL(retval)));
			} else if (Z_TYPE(retval) == IS_OBJECT) {
				php_error_docref(NULL, E_WARNING, "A PHP Object cannot be converted to a XPath-string");
				valuePush(ctxt, xmlXPathNewString(""));
			} else {
				convert_to_string_ex(&retval);
				valuePush(ctxt, xmlXPathNewString(Z_STRVAL(retval)));
			}
			zval_ptr_dtor(&retval);
		}
	}
	zend_string_release(callable);
	zval_ptr_dtor(&handler);
	if (fci.param_count > 0) {
		for (i = 0; i < nargs - 1; i++) {
			zval_ptr_dtor(&args[i]);
		}
		efree(args);
	}
}
コード例 #27
0
ファイル: where.c プロジェクト: dreamsxin/cphalcon7
/**
 * Gets the type of PHQL queries
 *
 *
 * @return int
 */
PHP_METHOD(Phalcon_Mvc_Model_Query_Builder_Where, setConditions){

	zval *conditions, *bind_params = NULL, *bind_types = NULL, *type = NULL, merge = {}, merged_conditions = {}, merged_bind_params = {}, merged_bind_types;
	zval joind_condition = {}, *single_condition_array = NULL, current_conditions = {}, new_conditions = {};
	zend_string *str_key;
	ulong idx;

	phalcon_fetch_params(0, 1, 3, &conditions, &bind_params, &bind_types, &type);

	if (!bind_params) {
		bind_params = &PHALCON_GLOBAL(z_null);
	}

	if (!bind_types) {
		bind_types = &PHALCON_GLOBAL(z_null);
	}

	if (!type) {
		type = &PHALCON_GLOBAL(z_null);
	}

	ZVAL_BOOL(&merge, Z_TYPE_P(type) != IS_NULL ? 1 : 0);

	if (Z_TYPE_P(conditions) == IS_ARRAY) {
		/* ----------- INITIALIZING LOOP VARIABLES ----------- */

		/*
		 * array containing single condition for example:
		 * array(
		 *      array(
		 *           'status = :status:',
		 *           array('status' => 5),
		 *           array('status' => PDO::PARAM_INT),
		 *      ),
		 *      'name' => 'Dreamsxin',
		 * )
		 */
		array_init(&merged_conditions);
		array_init(&merged_bind_params);
		array_init(&merged_bind_types);

		ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(conditions), idx, str_key, single_condition_array) {
			zval single_condition_key = {}, condition_string = {}, tmp_bind_params = {}, tmp_bind_types = {};
			if (str_key) {
				ZVAL_STR(&single_condition_key, str_key);
			} else {
				ZVAL_LONG(&single_condition_key, idx);
			}
			if (Z_TYPE_P(single_condition_array) == IS_ARRAY
				&& phalcon_array_isset_fetch_long(&condition_string, single_condition_array, 0)
				&& phalcon_array_isset_fetch_long(&tmp_bind_params, single_condition_array, 1)
				&& Z_TYPE(condition_string) == IS_STRING
				&& Z_TYPE(tmp_bind_params) == IS_ARRAY
			) {	
				phalcon_array_update_zval(&merged_conditions, &condition_string, &condition_string, PH_COPY);
				phalcon_array_merge_recursive_n(&merged_bind_params, &tmp_bind_params);

				if (phalcon_array_isset_fetch_long(&tmp_bind_types, single_condition_array, 2) && Z_TYPE(tmp_bind_types) == IS_ARRAY) {
					phalcon_array_merge_recursive_n(&merged_bind_types, &tmp_bind_types);
				}
			} else if (Z_TYPE(single_condition_key) == IS_STRING) {
				PHALCON_CONCAT_VSVS(&condition_string, &single_condition_key, " = :", &single_condition_key, ":");

				phalcon_array_update_zval(&merged_conditions, &single_condition_key, &condition_string, PH_COPY);

				if (Z_TYPE_P(single_condition_array) == IS_ARRAY) {
					phalcon_array_merge_recursive_n(&merged_bind_params, single_condition_array);
				} else {
					phalcon_array_update_zval(&merged_bind_params, &single_condition_key, single_condition_array, PH_COPY);
				}
			}
		} ZEND_HASH_FOREACH_END();
コード例 #28
0
ファイル: db.c プロジェクト: crodas/mongo-php-driver
PHP_METHOD(MongoDB, command) {
  zval limit, *temp, *cmd, *cursor, *ns, *options = 0;
  mongo_db *db;
  mongo_link *link;
  char *cmd_ns;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &cmd, &options) == FAILURE) {
    return;
  }
  if (IS_SCALAR_P(cmd)) {
    zend_error(E_WARNING, "MongoDB::command() expects parameter 1 to be an array or object");
    return;
  }

  PHP_MONGO_GET_DB(getThis());

  // create db.$cmd
  MAKE_STD_ZVAL(ns);
  cmd_ns = get_cmd_ns(Z_STRVAL_P(db->name), Z_STRLEN_P(db->name));
  ZVAL_STRING(ns, cmd_ns, 0);

  // create cursor
  MAKE_STD_ZVAL(cursor);
  object_init_ex(cursor, mongo_ce_Cursor);
  MAKE_STD_ZVAL(temp);
  ZVAL_NULL(temp);

  MONGO_METHOD3(MongoCursor, __construct, temp, cursor, db->link, ns, cmd);

  zval_ptr_dtor(&ns);
  zval_ptr_dtor(&temp);
  MAKE_STD_ZVAL(temp);
  ZVAL_NULL(temp);

  // limit
  Z_TYPE(limit) = IS_LONG;
  Z_LVAL(limit) = -1;
  MONGO_METHOD1(MongoCursor, limit, temp, cursor, &limit);

  zval_ptr_dtor(&temp);

  if (options) {
    zval **timeout;
    if (zend_hash_find(HASH_P(options), "timeout", strlen("timeout")+1, (void**)&timeout) == SUCCESS) {
      MAKE_STD_ZVAL(temp);
      ZVAL_NULL(temp);
      MONGO_METHOD1(MongoCursor, timeout, temp, cursor, *timeout);
      zval_ptr_dtor(&temp);
    }
  }

  // make sure commands aren't be sent to slaves
  PHP_MONGO_GET_LINK(db->link);
  if (link->rs) {
    zval slave_okay;
    Z_TYPE(slave_okay) = IS_BOOL;
    Z_LVAL(slave_okay) = 0;

    MAKE_STD_ZVAL(temp);
    ZVAL_NULL(temp);
    MONGO_METHOD1(MongoCursor, slaveOkay, temp, cursor, &slave_okay);
    zval_ptr_dtor(&temp);
  }

  // query
  MONGO_METHOD(MongoCursor, getNext, return_value, cursor);
  clear_exception(return_value TSRMLS_CC);

  zend_objects_store_del_ref(cursor TSRMLS_CC);
  zval_ptr_dtor(&cursor);
}
コード例 #29
0
static void nop_removal(zend_op_array *op_array)
{
    zend_op *end, *opline;
    zend_uint new_count, i, shift;
    int j;
    zend_uint *shiftlist;
    ALLOCA_FLAG(use_heap);

    shiftlist = (zend_uint *)DO_ALLOCA(sizeof(zend_uint) * op_array->last);
    i = new_count = shift = 0;
    end = op_array->opcodes+op_array->last;
    for (opline = op_array->opcodes; opline < end; opline++) {

#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
        /* GOTO target is unresolved yet. We can't optimize. */
        if (opline->opcode == ZEND_GOTO &&
                Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) {
            /* TODO: in general we can avoid this restriction */
            FREE_ALLOCA(shiftlist);
            return;
        }
#endif

        /* Kill JMP-over-NOP-s */
        if (opline->opcode == ZEND_JMP && ZEND_OP1(opline).opline_num > i) {
            /* check if there are only NOPs under the branch */
            zend_op *target = op_array->opcodes + ZEND_OP1(opline).opline_num - 1;

            while (target->opcode == ZEND_NOP) {
                target--;
            }
            if (target == opline) {
                /* only NOPs */
                opline->opcode = ZEND_NOP;
            }
        }

        shiftlist[i++] = shift;
        if (opline->opcode == ZEND_NOP) {
            shift++;
        } else {
            if (shift) {
                op_array->opcodes[new_count] = *opline;
            }
            new_count++;
        }
    }

    if (shift) {
        op_array->last = new_count;
        end = op_array->opcodes + op_array->last;

        /* update JMPs */
        for (opline = op_array->opcodes; opline<end; opline++) {
            switch (opline->opcode) {
            case ZEND_JMP:
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
            case ZEND_GOTO:
#endif
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
            case ZEND_FAST_CALL:
#endif
                ZEND_OP1(opline).opline_num -= shiftlist[ZEND_OP1(opline).opline_num];
                break;
            case ZEND_JMPZ:
            case ZEND_JMPNZ:
            case ZEND_JMPZ_EX:
            case ZEND_JMPNZ_EX:
            case ZEND_FE_FETCH:
            case ZEND_FE_RESET:
            case ZEND_NEW:
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
            case ZEND_JMP_SET:
#endif
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
            case ZEND_JMP_SET_VAR:
#endif
                ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num];
                break;
            case ZEND_JMPZNZ:
                ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num];
                opline->extended_value -= shiftlist[opline->extended_value];
                break;
            case ZEND_CATCH:
                opline->extended_value -= shiftlist[opline->extended_value];
                break;
            }
        }

        /* update brk/cont array */
        for (j = 0; j < op_array->last_brk_cont; j++) {
            op_array->brk_cont_array[j].brk -= shiftlist[op_array->brk_cont_array[j].brk];
            op_array->brk_cont_array[j].cont -= shiftlist[op_array->brk_cont_array[j].cont];
            op_array->brk_cont_array[j].start -= shiftlist[op_array->brk_cont_array[j].start];
        }

        /* update try/catch array */
        for (j = 0; j < op_array->last_try_catch; j++) {
            op_array->try_catch_array[j].try_op -= shiftlist[op_array->try_catch_array[j].try_op];
            op_array->try_catch_array[j].catch_op -= shiftlist[op_array->try_catch_array[j].catch_op];
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
            if (op_array->try_catch_array[j].finally_op) {
                op_array->try_catch_array[j].finally_op -= shiftlist[op_array->try_catch_array[j].finally_op];
                op_array->try_catch_array[j].finally_end -= shiftlist[op_array->try_catch_array[j].finally_end];
            }
#endif
        }

#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
        /* update early binding list */
        if (op_array->early_binding != (zend_uint)-1) {
            zend_uint *opline_num = &op_array->early_binding;

            do {
                *opline_num -= shiftlist[*opline_num];
                opline_num = &ZEND_RESULT(&op_array->opcodes[*opline_num]).opline_num;
            } while (*opline_num != (zend_uint)-1);
        }
#endif
    }
    FREE_ALLOCA(shiftlist);
}
コード例 #30
0
ファイル: com_typeinfo.c プロジェクト: Neha55/php-src
/* Given a type-library, merge it into the current engine state */
PHP_COM_DOTNET_API int php_com_import_typelib(ITypeLib *TL, int mode, int codepage TSRMLS_DC)
{
	int i, j, interfaces;
	TYPEKIND pTKind;
	ITypeInfo *TypeInfo;
	VARDESC *pVarDesc;
	UINT NameCount;
	BSTR bstr_ids;
	zend_constant c;
	zval *exists, results, value;
	char *const_name;
	size_t len;

	if (TL == NULL) {
		return FAILURE;
	}

	interfaces = ITypeLib_GetTypeInfoCount(TL);
	for (i = 0; i < interfaces; i++) {
		ITypeLib_GetTypeInfoType(TL, i, &pTKind);
		if (pTKind == TKIND_ENUM) {
			ITypeLib_GetTypeInfo(TL, i, &TypeInfo);
			for (j = 0; ; j++) {
				if (FAILED(ITypeInfo_GetVarDesc(TypeInfo, j, &pVarDesc))) {
					break;
				}
				ITypeInfo_GetNames(TypeInfo, pVarDesc->memid, &bstr_ids, 1, &NameCount);
				if (NameCount != 1) {
					ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
					continue;
				}

				const_name = php_com_olestring_to_string(bstr_ids, &len, codepage TSRMLS_CC);
				c.name = zend_string_init(const_name, len, 1);
				// TODO: avoid reallocation???
				efree(const_name);
				if(c.name == NULL) {
					ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
					continue;
				}
//???				c.name_len++; /* include NUL */
				SysFreeString(bstr_ids);

				/* sanity check for the case where the constant is already defined */
				if ((exists = zend_get_constant(c.name TSRMLS_CC)) != NULL) {
					if (COMG(autoreg_verbose) && !compare_function(&results, &c.value, exists TSRMLS_CC)) {
						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type library constant %s is already defined", c.name);
					}
					zend_string_release(c.name);
					ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
					continue;
				}

				/* register the constant */
				php_com_zval_from_variant(&value, pVarDesc->lpvarValue, codepage TSRMLS_CC);
				if (Z_TYPE(value) == IS_LONG) {
					c.flags = mode;
					ZVAL_LONG(&c.value, Z_LVAL(value));
					c.module_number = 0;
					zend_register_constant(&c TSRMLS_CC);
				}
				ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
			}
			ITypeInfo_Release(TypeInfo);
		}
	}
	return SUCCESS;
}