From bb4012d886144027166065ad621d2704b596933b Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Tue, 11 Aug 2026 16:57:25 +0000 Subject: [PATCH] fix(ffe): isolate malformed flag configurations --- Cargo.lock | 64 ++++++++++++-------- Cargo.toml | 16 +++++ Makefile | 2 +- components-rs/Cargo.toml | 2 +- components-rs/remote_config.rs | 10 +-- components-rs/telemetry.rs | 8 ++- libdatadog | 2 +- tests/FeatureFlags/ffe-system-test-data | 2 +- tests/ext/ffe/system_test_data_evaluate.phpt | 13 ++++ 9 files changed, 83 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d190dfa02..60108f9c6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1208,30 +1208,6 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" -[[package]] -name = "datadog-ffe" -version = "1.0.0" -dependencies = [ - "chrono", - "derive_more", - "faststr", - "libdd-common", - "libdd-remote-config", - "libdd-trace-protobuf", - "log", - "lru", - "md5", - "prost", - "pyo3", - "semver", - "serde", - "serde-bool", - "serde_json", - "serde_with", - "thiserror 2.0.18", - "url", -] - [[package]] name = "datadog-ipc" version = "0.1.0" @@ -1293,6 +1269,8 @@ dependencies = [ "serde", "serde_json", "smallvec", + "strum", + "strum_macros", "sys-info", "tokio", "uuid", @@ -1322,7 +1300,6 @@ dependencies = [ "bincode", "cbindgen 0.27.0", "const-str", - "datadog-ffe", "datadog-ipc", "datadog-live-debugger", "datadog-live-debugger-ffi", @@ -1339,6 +1316,7 @@ dependencies = [ "libdd-crashtracker", "libdd-crashtracker-ffi", "libdd-data-pipeline", + "libdd-ffe", "libdd-library-config-ffi", "libdd-remote-config", "libdd-telemetry", @@ -1411,7 +1389,6 @@ dependencies = [ "bincode", "chrono", "console-subscriber", - "datadog-ffe", "datadog-ipc", "datadog-ipc-macros", "datadog-live-debugger", @@ -1429,6 +1406,7 @@ dependencies = [ "libdd-crashtracker-ffi", "libdd-data-pipeline", "libdd-dogstatsd-client", + "libdd-ffe", "libdd-remote-config", "libdd-telemetry", "libdd-tinybytes", @@ -2820,6 +2798,7 @@ dependencies = [ "multer", "nix 0.29.0", "pin-project", + "proptest", "rand 0.8.5", "regex", "regex-lite", @@ -2956,6 +2935,7 @@ dependencies = [ "tracing", "uuid", "web-time", + "zstd", ] [[package]] @@ -2985,6 +2965,36 @@ dependencies = [ "tracing", ] +[[package]] +name = "libdd-ffe" +version = "0.1.0" +dependencies = [ + "bincode", + "chrono", + "derive_more", + "faststr", + "http", + "httpmock", + "libdd-capabilities", + "libdd-capabilities-impl", + "libdd-common", + "libdd-remote-config", + "libdd-trace-protobuf", + "log", + "lru", + "md5", + "prost", + "pyo3", + "semver", + "serde", + "serde-bool", + "serde_json", + "serde_with", + "thiserror 2.0.18", + "tokio", + "url", +] + [[package]] name = "libdd-library-config" version = "3.0.0" @@ -3164,6 +3174,8 @@ dependencies = [ "libdd-shared-runtime", "serde", "serde_json", + "strum", + "strum_macros", "sys-info", "tokio", "tokio-util", diff --git a/Cargo.toml b/Cargo.toml index ed73244658..6a626d2baf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,8 +41,16 @@ inherits = "release" # #2253 consolidated `anyhow`, `serde`, `tokio` and `tracing` to the workspace # level, so they are mirrored here too. [workspace.dependencies] +allocator-api2 = { version = "0.2.21", default-features = false } anyhow = { version = "1.0", default-features = false } arc-swap = "1.7.1" +bolero = { version = "0.13.4", default-features = false } +chrono = { version = "0.4.38", default-features = false } +clap = { version = "4.3.21", default-features = false } +criterion = { version = "0.5.1", default-features = true } +cxx-build = { version = "1.0", default-features = false } +elf = { version = "0.7", default-features = false } +futures = { version = "0.3", default-features = false } hyper = { version = "1.6", features = [ "http1", "client", @@ -52,12 +60,20 @@ hyper-util = { version = "0.1.10", features = [ "client", "client-legacy", ] } +io-lifetimes = { version = "1.0", default-features = false } +libc = { version = "0.2", default-features = true } prost-build = { version = "0.14.1", default-features = false } protoc-bin-vendored = { version = "3.0.0", default-features = false } +rustls = { version = "0.23", default-features = false } serde = { version = "1.0", default-features = false } serde_json = { version = "1.0", default-features = false, features = ["alloc"] } +syn = { version = "^2", default-features = false } +tempfile = { version = "3.13", default-features = false, features = [ + "getrandom", +] } tokio = { version = "1.36", default-features = false } tracing = { version = "0.1", default-features = false } +uuid = { version = "1.7.0", default-features = false } [workspace.lints] # empty for compat with libdatadog diff --git a/Makefile b/Makefile index aa1ba9dad6..e4b4006401 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ RUN_TESTS_CMD := DD_SERVICE= DD_ENV= REPORT_EXIT_STATUS=1 TEST_PHP_SRCDIR=$(PROJ C_FILES = $(shell find components components-rs ext src/dogstatsd tracer zend_abstract_interface -name '*.c' -o -name '*.h' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' ) TEST_FILES = $(shell find tests/ext -name '*.php*' -o -name '*.inc' -o -name '*.json' -o -name '*.yaml' -o -name 'CONFLICTS' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' ) -RUST_FILES = $(BUILD_DIR)/Cargo.toml $(BUILD_DIR)/Cargo.lock $(shell find components-rs -name '*.c' -o -name '*.rs' -o -name 'Cargo.toml' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' ) $(shell find libdatadog/{build-common,datadog-ffe,datadog-ipc,datadog-ipc-macros,datadog-live-debugger,datadog-live-debugger-ffi,libdd-remote-config,datadog-sidecar,datadog-sidecar-ffi,datadog-sidecar-macros,libdd-alloc,libdd-capabilities,libdd-capabilities-impl,libdd-common,libdd-common-ffi,libdd-crashtracker,libdd-crashtracker-ffi,libdd-data-pipeline,libdd-ddsketch,libdd-dogstatsd-client,libdd-library-config,libdd-library-config-ffi,libdd-log,libdd-shared-runtime,libdd-telemetry,libdd-telemetry-ffi,libdd-tinybytes,libdd-trace-*,spawn_worker,tools/{cc_utils,sidecar_mockgen},libdd-trace-*,Cargo.toml} \( -type l -o -type f \) \( -path "*/src*" -o -path "*/examples*" -o -path "*Cargo.toml" -o -path "*/build.rs" -o -path "*/tests/dataservice.rs" -o -path "*/tests/service_functional.rs" \) -not -path "*/datadog-ipc/build.rs" -not -path "*/datadog-sidecar-ffi/build.rs") +RUST_FILES = $(BUILD_DIR)/Cargo.toml $(BUILD_DIR)/Cargo.lock $(shell find components-rs -name '*.c' -o -name '*.rs' -o -name 'Cargo.toml' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' ) $(shell find libdatadog/{build-common,libdd-ffe,datadog-ipc,datadog-ipc-macros,datadog-live-debugger,datadog-live-debugger-ffi,libdd-remote-config,datadog-sidecar,datadog-sidecar-ffi,datadog-sidecar-macros,libdd-alloc,libdd-capabilities,libdd-capabilities-impl,libdd-common,libdd-common-ffi,libdd-crashtracker,libdd-crashtracker-ffi,libdd-data-pipeline,libdd-ddsketch,libdd-dogstatsd-client,libdd-library-config,libdd-library-config-ffi,libdd-log,libdd-shared-runtime,libdd-telemetry,libdd-telemetry-ffi,libdd-tinybytes,libdd-trace-*,spawn_worker,tools/{cc_utils,sidecar_mockgen},libdd-trace-*,Cargo.toml} \( -type l -o -type f \) \( -path "*/src*" -o -path "*/examples*" -o -path "*Cargo.toml" -o -path "*/build.rs" -o -path "*/tests/dataservice.rs" -o -path "*/tests/service_functional.rs" \) -not -path "*/datadog-ipc/build.rs" -not -path "*/datadog-sidecar-ffi/build.rs") ALL_OBJECT_FILES = $(C_FILES) $(RUST_FILES) $(BUILD_DIR)/Makefile TEST_OPCACHE_FILES = $(shell find tests/opcache -name '*.php*' -o -name '.gitkeep' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' ) TEST_STUB_FILES = $(shell find tests/ext -type d -name 'stubs' -exec find '{}' -type f \; | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' ) diff --git a/components-rs/Cargo.toml b/components-rs/Cargo.toml index 7c78ff2cad..86a8f8bd68 100644 --- a/components-rs/Cargo.toml +++ b/components-rs/Cargo.toml @@ -15,7 +15,7 @@ libdd-telemetry-ffi = { path = "../libdatadog/libdd-telemetry-ffi", default-feat datadog-live-debugger = { path = "../libdatadog/datadog-live-debugger" } datadog-live-debugger-ffi = { path = "../libdatadog/datadog-live-debugger-ffi", default-features = false } datadog-ipc = { path = "../libdatadog/datadog-ipc" } -datadog-ffe = { path = "../libdatadog/datadog-ffe" } +datadog-ffe = { package = "libdd-ffe", path = "../libdatadog/libdd-ffe" } libdd-remote-config = { path = "../libdatadog/libdd-remote-config" } datadog-sidecar = { path = "../libdatadog/datadog-sidecar" } datadog-sidecar-ffi = { path = "../libdatadog/datadog-sidecar-ffi" } diff --git a/components-rs/remote_config.rs b/components-rs/remote_config.rs index 6e085848f6..7bbddf0d97 100644 --- a/components-rs/remote_config.rs +++ b/components-rs/remote_config.rs @@ -164,12 +164,12 @@ pub unsafe extern "C" fn ddog_init_remote_config(flags: RemoteConfigFlags) { } if live_debugging_enabled { - DATADOG_REMOTE_CONFIG_PRODUCTS.push(RemoteConfigProduct::LiveDebugger) + DATADOG_REMOTE_CONFIG_PRODUCTS.push(RemoteConfigProduct::LiveDebugging) } if appsec_config { DATADOG_REMOTE_CONFIG_PRODUCTS.push(RemoteConfigProduct::AsmData); - DATADOG_REMOTE_CONFIG_PRODUCTS.push(RemoteConfigProduct::AsmDD); + DATADOG_REMOTE_CONFIG_PRODUCTS.push(RemoteConfigProduct::AsmDd); DATADOG_REMOTE_CONFIG_PRODUCTS.push(RemoteConfigProduct::Asm); [ RemoteConfigCapabilities::AsmIpBlocking, @@ -390,7 +390,7 @@ pub extern "C" fn ddog_process_remote_configs(remote_config: &mut RemoteConfigSt } => { if let Some(data) = value.data { match value.product { - RemoteConfigProduct::LiveDebugger => { + RemoteConfigProduct::LiveDebugging => { let val = Box::new((data, MaybeShmLimiter::open(limiter_index))); let rc_ref: &mut RemoteConfigState = unsafe { mem::transmute(remote_config as *mut _) }; // sigh, borrow checker let config_id = value.config_id.clone(); @@ -439,7 +439,7 @@ pub extern "C" fn ddog_process_remote_configs(remote_config: &mut RemoteConfigSt } } RemoteConfigUpdate::Remove(path) => match path.product { - RemoteConfigProduct::LiveDebugger => { + RemoteConfigProduct::LiveDebugging => { if let Some(boxed) = remote_config.live_debugger.active.remove(&path.config_id) { if let Some(debugger) = boxed.0.downcast::() { remove_config(remote_config, &path.config_id, debugger); @@ -755,7 +755,7 @@ pub extern "C" fn ddog_rshutdown_remote_config(remote_config: &mut RemoteConfigS remote_config.dynamic_config.merged_configs.clear(); remote_config.manager.unload_configs(&[ RemoteConfigProduct::ApmTracing, - RemoteConfigProduct::LiveDebugger, + RemoteConfigProduct::LiveDebugging, ]); } diff --git a/components-rs/telemetry.rs b/components-rs/telemetry.rs index 2c55aa53f7..e0c1dc47a8 100644 --- a/components-rs/telemetry.rs +++ b/components-rs/telemetry.rs @@ -105,6 +105,7 @@ pub unsafe extern "C" fn ddog_sidecar_telemetry_addIntegration_buffer( version, compatible: None, auto_enabled: None, + error: None, }); buffer.buffer.push(SidecarAction::Telemetry(action)); } @@ -121,6 +122,8 @@ pub unsafe extern "C" fn ddog_sidecar_telemetry_addDependency_buffer( let action = TelemetryActions::AddDependency(Dependency { name: dependency_name.to_utf8_lossy().into_owned(), version, + hash: None, + metadata: None, }); buffer.buffer.push(SidecarAction::Telemetry(action)); } @@ -139,6 +142,9 @@ pub unsafe extern "C" fn ddog_sidecar_telemetry_addEndpoint_buffer( path: Some(path.to_utf8_lossy().into_owned()), operation_name: operation_name.to_utf8_lossy().into_owned(), resource_name: resource_name.to_utf8_lossy().into_owned(), + request_body_type: None, + response_body_type: None, + response_code: None, }); buffer.buffer.push(SidecarAction::Telemetry(action)); } @@ -158,7 +164,7 @@ pub unsafe extern "C" fn ddog_sidecar_telemetry_enqueueConfig_buffer( }; let action = TelemetryActions::AddConfig(data::Configuration { name: config_key.to_utf8_lossy().into_owned(), - value: config_value.to_utf8_lossy().into_owned(), + value: Some(config_value.to_utf8_lossy().into_owned()), origin, config_id, seq_id: None, diff --git a/libdatadog b/libdatadog index 95610de06a..d20319f8a1 160000 --- a/libdatadog +++ b/libdatadog @@ -1 +1 @@ -Subproject commit 95610de06a776b8d645fe77ad8b8e1848ecd53b7 +Subproject commit d20319f8a108b9ee738af41e7f49f1875ce3c245 diff --git a/tests/FeatureFlags/ffe-system-test-data b/tests/FeatureFlags/ffe-system-test-data index 4446371bc1..ea8b5cc5ce 160000 --- a/tests/FeatureFlags/ffe-system-test-data +++ b/tests/FeatureFlags/ffe-system-test-data @@ -1 +1 @@ -Subproject commit 4446371bc1ca52bd526356927ef42d380145b118 +Subproject commit ea8b5cc5ce335109f11f3efbc5fd608f98a3ca54 diff --git a/tests/ext/ffe/system_test_data_evaluate.phpt b/tests/ext/ffe/system_test_data_evaluate.phpt index 0354581a76..bfea6db56c 100644 --- a/tests/ext/ffe/system_test_data_evaluate.phpt +++ b/tests/ext/ffe/system_test_data_evaluate.phpt @@ -175,6 +175,19 @@ function run_fixture_case($client, $fileName, $index, array $case, array &$failu . ': value got=' . encode_value($details->getValue()) . ' want=' . encode_value($case['result']['value']); } + + if ($details->getReason() !== $case['result']['reason']) { + $failures[] = $fileName . '#' . $index + . ': reason got=' . encode_value($details->getReason()) + . ' want=' . encode_value($case['result']['reason']); + } + + if (array_key_exists('errorCode', $case['result']) + && $details->getErrorCode() !== $case['result']['errorCode']) { + $failures[] = $fileName . '#' . $index + . ': errorCode got=' . encode_value($details->getErrorCode()) + . ' want=' . encode_value($case['result']['errorCode']); + } } function evaluate_fixture_case($client, $variationType, $flag, $defaultValue, array $context)