Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions ext/hook/uhook.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ typedef struct {

typedef struct {
dd_hook_data *hook_data;
zend_class_entry *called_scope;
} dd_uhook_dynamic;

#if PHP_VERSION_ID < 70400
Expand Down Expand Up @@ -234,14 +235,14 @@ void dd_uhook_report_sandbox_error(zend_execute_data *execute_data, zend_object
})
}

static bool dd_uhook_call_hook(zend_execute_data *execute_data, dd_uhook_callback *callback, dd_hook_data *hook_data) {
static bool dd_uhook_call_hook(zend_execute_data *execute_data, dd_uhook_callback *callback, dd_hook_data *hook_data, zend_class_entry *scope) {
zval hook_data_zv;
ZVAL_OBJ(&hook_data_zv, &hook_data->std);

zval rv;
zai_sandbox sandbox;
zai_sandbox_open(&sandbox);
dd_uhook_callback_ensure_scope(callback, execute_data);
dd_uhook_callback_ensure_scope(callback, execute_data, scope);
zend_fcall_info fci = dd_fcall_info(1, &hook_data_zv, &rv);
bool success = zai_sandbox_call(&sandbox, &fci, &callback->fcc);
if (!success || PG(last_error_message)) {
Expand Down Expand Up @@ -321,6 +322,7 @@ static bool dd_uhook_begin(zend_ulong invocation, zend_execute_data *execute_dat
return true;
}

dyn->called_scope = zend_get_called_scope(execute_data);
dyn->hook_data = (dd_hook_data *)dd_hook_data_create(ddtrace_hook_data_ce);
dyn->hook_data->returns_reference = execute_data->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE;
dyn->hook_data->vm_stack_top = EG(vm_stack_top);
Expand Down Expand Up @@ -356,7 +358,7 @@ static bool dd_uhook_begin(zend_ulong invocation, zend_execute_data *execute_dat
LOGEV(HOOK_TRACE, dd_uhook_log_invocation(log, execute_data, "begin", def->begin.closure););

def->running = true;
dd_uhook_call_hook(execute_data, &def->begin, dyn->hook_data);
dd_uhook_call_hook(execute_data, &def->begin, dyn->hook_data, dyn->called_scope);
def->running = false;
dyn->hook_data->retval_ptr = NULL;
}
Expand Down Expand Up @@ -480,7 +482,7 @@ static void dd_uhook_end(zend_ulong invocation, zend_execute_data *execute_data,
def->running = true;
dyn->hook_data->retval_ptr = retval;
dyn->hook_data->execute_data = execute_data;
keep_span = dd_uhook_call_hook(execute_data, &def->end, dyn->hook_data);
keep_span = dd_uhook_call_hook(execute_data, &def->end, dyn->hook_data, dyn->called_scope);
dyn->hook_data->execute_data = NULL;
dyn->hook_data->retval_ptr = NULL;
def->running = false;
Expand Down
6 changes: 2 additions & 4 deletions ext/hook/uhook.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,12 @@ void zai_uhook_minit(int module_number);
void zai_uhook_mshutdown();

void dd_uhook_callback_apply_scope(dd_uhook_callback *cb, zend_class_entry *scope);
static inline void dd_uhook_callback_ensure_scope(dd_uhook_callback *cb, zend_execute_data *execute_data) {
zend_class_entry *scope;
// Note that we cannot access zend_get_called_scope(execute_data) here - we need to have it provided from earlier, it might have been invalidated by now, e.g. in ZEND_NAMED_FUNCTION(zend_closure_internal_handler).
static inline void dd_uhook_callback_ensure_scope(dd_uhook_callback *cb, zend_execute_data *execute_data, zend_class_entry *scope) {
if (!cb->fcc.function_handler) {
scope = zend_get_called_scope(execute_data);
goto apply_scope;
} else if (!cb->is_static) {
bool has_this;
scope = zend_get_called_scope(execute_data);
if (scope != cb->fcc.called_scope) {
apply_scope:
dd_uhook_callback_apply_scope(cb, scope);
Expand Down
9 changes: 5 additions & 4 deletions ext/hook/uhook_legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ typedef struct {
typedef struct {
zend_array *args;
ddtrace_span_data *span;
zend_class_entry *called_scope;
bool skipped;
bool dropped_span;
bool was_primed;
Expand All @@ -35,7 +36,7 @@ static bool dd_uhook_call(dd_uhook_callback *callback, bool tracing, dd_uhook_dy

#define ZVAL_EXCEPTION(zv) do { if (EG(exception)) ZVAL_OBJ(zv, EG(exception)); else ZVAL_NULL(zv); } while (0)
if (tracing) {
dd_uhook_callback_ensure_scope(callback, execute_data);
dd_uhook_callback_ensure_scope(callback, execute_data, dyn->called_scope);

ZVAL_OBJ(&params[0], &dyn->span->std);
ZVAL_ARR(&params[1], dyn->args);
Expand All @@ -62,9 +63,8 @@ static bool dd_uhook_call(dd_uhook_callback *callback, bool tracing, dd_uhook_dy
ZVAL_COPY_VALUE(&params[0], This);
callback->fcc.object = Z_OBJ_P(This);
}
zend_class_entry *scope_ce = zend_get_called_scope(execute_data);
if (scope_ce) {
ZVAL_STR(&params[1], scope_ce->name);
if (dyn->called_scope) {
ZVAL_STR(&params[1], dyn->called_scope->name);
} else {
ZVAL_NULL(&params[1]);
}
Expand Down Expand Up @@ -108,6 +108,7 @@ static bool dd_uhook_begin(zend_ulong invocation, zend_execute_data *execute_dat
dyn->skipped = false;
dyn->was_primed = false;
dyn->dropped_span = false;
dyn->called_scope = zend_get_called_scope(execute_data);
dyn->args = dd_uhook_collect_args(execute_data);

if (def->tracing) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--TEST--
ASAN repro: internal fake closure + forced eval parse error
--SKIPIF--
<?php
if (PHP_VERSION_ID < 80000) {
die('skip: test requires PHP 8+');
}
?>
--INI--
datadog.trace.generate_root_span=0
datadog.trace.auto_flush_enabled=0
--FILE--
<?php
$closure = (new ReflectionFunction("intval"))->getClosure();

\DDTrace\install_hook(
$closure,
null,
function () {
eval('throw new \\Exception("boom");');
},
\DDTrace\HOOK_INSTANCE
);

try {
$closure(1);
} catch (Throwable $e) {
// ignore
}

echo "ok\n";
?>
--EXPECT--
ok

Loading