Skip to content
Open
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
16 changes: 15 additions & 1 deletion ext/serializer.c
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,14 @@ static void dd_set_entrypoint_root_span_props(struct superglob_equiv *data, ddtr
}
}

// Detects a zval that is flagged as refcounted but carries a NULL counted
// pointer. Copying such a zval with ZVAL_COPY_DEREF dereferences NULL inside
// GC_ADDREF and crashes the process.
static zend_always_inline bool dd_zval_is_broken_refcounted(zval *zv) {
ZVAL_DEREF(zv);
return Z_REFCOUNTED_P(zv) && Z_COUNTED_P(zv) == NULL;
}

void ddtrace_inherit_span_properties(ddtrace_span_data *span, ddtrace_span_data *parent) {
zval *prop_service = &span->property_service;
zval_ptr_dtor(prop_service);
Expand All @@ -733,7 +741,13 @@ void ddtrace_inherit_span_properties(ddtrace_span_data *span, ddtrace_span_data

zval *prop_baggage = &span->property_baggage, *prop_parent_baggage = &parent->property_baggage;
zval_ptr_dtor(prop_baggage);
ZVAL_COPY_DEREF(prop_baggage, prop_parent_baggage);
if (UNEXPECTED(dd_zval_is_broken_refcounted(prop_parent_baggage))) {
// Fall back to the property's declared default instead of dereferencing
// a NULL refcounted pointer; baggage stays a valid array downstream.
ZVAL_EMPTY_ARRAY(prop_baggage);
} else {
ZVAL_COPY_DEREF(prop_baggage, prop_parent_baggage);
}

zend_array *parent_meta = ddtrace_property_array(&parent->property_meta);

Expand Down