in prod/native/extension/code/InternalFunctionInstrumentation.cpp [75:143]
void argsPostProcessing(AutoZval &functionArgs, AutoZval &returnValue) {
if (!returnValue.isArray()) {
return;
}
if (zend_is_identical(returnValue.get(), functionArgs.get())) {
return;
}
zend_ulong argIndex = 0;
zend_string *argStrKey = nullptr;
zval *argValue = nullptr;
zend_execute_data *execute_data = EG(current_execute_data);
uint32_t requiredArgsCount = execute_data->func->type == ZEND_INTERNAL_FUNCTION ? ZEND_CALL_NUM_ARGS(execute_data) : execute_data->func->op_array.last_var;
uint32_t initalCallNumArgs = ZEND_CALL_NUM_ARGS(execute_data);
ELOGF_DEBUG(EAPM_GL(logger_), INSTRUMENTATION, "argsPostProcessing requiredArgsCount: %d initialCallNumArgs: %d", requiredArgsCount, initalCallNumArgs);
uint32_t highestArgIdx = 0;
ZEND_HASH_FOREACH_KEY_VAL(Z_ARR_P(returnValue.get()), argIndex, argStrKey, argValue) {
if (!argStrKey) {
highestArgIdx = std::max(highestArgIdx, (uint32_t)argIndex);
}
} ZEND_HASH_FOREACH_END();
ELOGF_DEBUG(EAPM_GL(logger_), INSTRUMENTATION, "argsPostProcessing highestArgIdx: %d vm_stack free: %d", highestArgIdx, EG(vm_stack_end) - EG(vm_stack_top));
// extending stack and undefining potential gaps
if (highestArgIdx + 1 > initalCallNumArgs) {
uint32_t howManyArgsToAdd = highestArgIdx + 1 - initalCallNumArgs;
ELOGF_DEBUG(EAPM_GL(logger_), INSTRUMENTATION, "postProcessing trying extend stack frame with %d arguments", howManyArgsToAdd);
zend_vm_stack_extend_call_frame(&execute_data, initalCallNumArgs, howManyArgsToAdd);
for (uint32_t idx = 0; idx < howManyArgsToAdd; ++idx) {
zval *target = ZEND_CALL_ARG(execute_data, execute_data->func->type == ZEND_INTERNAL_FUNCTION ? initalCallNumArgs + idx + 1 : initalCallNumArgs + idx + 1 + execute_data->func->op_array.T);
ZVAL_UNDEF(target);
}
ZEND_CALL_NUM_ARGS(execute_data) += howManyArgsToAdd;
ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS);
ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_MAY_HAVE_UNDEF);
}
ZEND_HASH_FOREACH_KEY_VAL(Z_ARR_P(returnValue.get()), argIndex, argStrKey, argValue) {
if (argStrKey) {
ELOGF_DEBUG(EAPM_GL(logger_), INSTRUMENTATION, "argsPostProcessing str: %s", ZSTR_VAL(argStrKey));
try {
argIndex = getFunctionArgumentIndex(argStrKey, execute_data->func);
} catch (std::exception const &e) {
ELOGF_WARNING(EAPM_GL(logger_), INSTRUMENTATION, "postProcessing argument index not found for: '%s'", ZSTR_VAL(argStrKey));
continue;
}
}
ELOGF_DEBUG(EAPM_GL(logger_), INSTRUMENTATION, "argsPostProcessing idx: %d", argIndex);
zval *target = nullptr;
if (argIndex < requiredArgsCount) {
target = ZEND_CALL_ARG(execute_data, argIndex + 1);
} else {
target = ZEND_CALL_ARG(execute_data, execute_data->func->type == ZEND_INTERNAL_FUNCTION ? argIndex + 1 : argIndex + 1 + execute_data->func->op_array.T);
}
//TODO consider refs
zval_ptr_dtor(target);
ZVAL_COPY(target, argValue);
} ZEND_HASH_FOREACH_END();
}