Skip to content
Draft
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
14 changes: 7 additions & 7 deletions build/cmake/FindLibdatadog.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ endif()

include(FetchContent)

set(LIBDATADOG_VERSION "v20.0.0" CACHE STRING "libdatadog version")
set(LIBDATADOG_VERSION "v22.1.0" CACHE STRING "libdatadog version")

if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# For Darwin, we'll download both architectures and combine them
set(SHA256_LIBDATADOG_ARM64 "916a207ea1343744062ff44f421f198bc9d79ae2be7624f4ba355542ff03b7ec" CACHE STRING "libdatadog arm64 sha256")
set(SHA256_LIBDATADOG_X86_64 "879d213a5cbf982500833323828c862a5efc824afdb03628daa8f363e70cbfe9" CACHE STRING "libdatadog x86_64 sha256")
set(SHA256_LIBDATADOG_ARM64 "2ace4fe2299638fdc32845359c10da02a58db458dd86c8c542deaf99a90e4c78" CACHE STRING "libdatadog arm64 sha256")
set(SHA256_LIBDATADOG_X86_64 "682fafc37dd17c8e3970efc798657f18dc5d8f07d277a577ef71e6a712c91a96" CACHE STRING "libdatadog x86_64 sha256")
set(FILE_TO_DOWNLOAD_ARM64 libdatadog-aarch64-apple-darwin.tar.gz)
set(FILE_TO_DOWNLOAD_X86_64 libdatadog-x86_64-apple-darwin.tar.gz)

Expand Down Expand Up @@ -62,18 +62,18 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
else()
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
if(DEFINED ENV{IsAlpine} AND "$ENV{IsAlpine}" MATCHES "true")
set(SHA256_LIBDATADOG "12791239d3d0bfeab8fc659d10dd64e8ccf9ad87aa3f293c3f509a57bf2b3ade" CACHE STRING "libdatadog sha256")
set(SHA256_LIBDATADOG "74be28884a318a3d8c3b37d4e2e2821f803917680464c18bae3f9a57f9827d1b" CACHE STRING "libdatadog sha256")
set(FILE_TO_DOWNLOAD libdatadog-aarch64-alpine-linux-musl.tar.gz)
else()
set(SHA256_LIBDATADOG "368903a0a73b700ba2a6a8aee91b2be49af9ef6077b684b9f1aace408f8917b1" CACHE STRING "libdatadog sha256")
set(SHA256_LIBDATADOG "cec1c38503d96ae0991a7e914aaf40e16ce23444bd3fda99532954ab8bb562ff" CACHE STRING "libdatadog sha256")
set(FILE_TO_DOWNLOAD libdatadog-aarch64-unknown-linux-gnu.tar.gz)
endif()
else()
if(DEFINED ENV{IsAlpine} AND "$ENV{IsAlpine}" MATCHES "true")
set(SHA256_LIBDATADOG "bcf85135fea719aa192d176b08bb62056beff5d96ddbd114dfc28e50fcfea08c" CACHE STRING "libdatadog sha256")
set(SHA256_LIBDATADOG "3f1815af29b6223357ca1961d18f3efada5be264e9034255c439de27e130e4b9" CACHE STRING "libdatadog sha256")
set(FILE_TO_DOWNLOAD libdatadog-${CMAKE_SYSTEM_PROCESSOR}-alpine-linux-musl.tar.gz)
else()
set(SHA256_LIBDATADOG "84b779bdaa3da7668795e264a5ac4b015185044d147a142727349026eb49d428" CACHE STRING "libdatadog sha256")
set(SHA256_LIBDATADOG "e1d878e894ed6a60d12e60c71281dac0567cde56147cc6d76ac4b98b6849bdae" CACHE STRING "libdatadog sha256")
set(FILE_TO_DOWNLOAD libdatadog-${CMAKE_SYSTEM_PROCESSOR}-unknown-linux-gnu.tar.gz)
endif()
endif()
Expand Down
4 changes: 2 additions & 2 deletions build/vcpkg_local_ports/libdatadog/portfile.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ set(LIBDATADOG_VERSION ${VERSION})
if(TARGET_TRIPLET STREQUAL "x64-windows" OR
TARGET_TRIPLET STREQUAL "x64-windows-static")
set(PLATFORM "x64")
set(LIBDATADOG_HASH "f43b4e0a41a4f1d20995e13bc43b7d3502120c2809aefa177f3eea73db1f430e9de350f6f54bdadae09820ad7a492b7f054ec0180d94c33e44fb9a462ab3153a")
set(LIBDATADOG_HASH "dcf282c7fba93e25eb41bde9671e6893b1faf2d57599ac75a37d32195a606bbeaf6b4af8c269cb622508ebd98770facba25b1c05efcc1a01d023c82d3800e9df")
elseif(TARGET_TRIPLET STREQUAL "x86-windows" OR
TARGET_TRIPLET STREQUAL "x86-windows-static")
set(PLATFORM "x86")
set(LIBDATADOG_HASH "9cdc780f52edcccf272098f46ee2200e2fa3d56b29be21b5bfc1bcf7943f9a0efd7b7d9e84ca6340e618ec92c4b19d7625d6907592027d4ca67241b08b9063a6")
set(LIBDATADOG_HASH "afacd4320ed4f1c736a7301cee5e1f4064624283087870a7dd94768ba6d23854800fd0968bf8f845d400a2969dd5dcef91c4c7fe79e8295ec0ed7bac7d5b9d10")
else()
message(FATAL_ERROR "Unsupported triplet: ${TARGET_TRIPLET}")
endif()
Expand Down
2 changes: 1 addition & 1 deletion build/vcpkg_local_ports/libdatadog/vcpkg.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "libdatadog",
"version-string": "20.0.0",
"version-string": "22.1.0",
"description": "Package providing libdatadog prebuilt binaries for Windows only.",
"dependencies": []
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

// from dotnet coreclr includes

// TO REMOVE: only to trigger profiler tests
//
#include "cor.h"
#include "corprof.h"
// end
Expand Down
15 changes: 13 additions & 2 deletions tracer/src/Datadog.Trace/LibDatadog/CString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,30 @@ internal CString(string? str)
{
var encoding = StringEncoding.UTF8;
var maxBytesCount = encoding.GetMaxByteCount(str.Length);
Ptr = Marshal.AllocHGlobal(maxBytesCount);
Ptr = Marshal.AllocHGlobal(maxBytesCount + 1); // +1 for null terminator
unsafe
{
fixed (char* strPtr = str)
{
try
{
Length = (nuint)encoding.GetBytes(strPtr, str.Length, (byte*)Ptr, maxBytesCount);
int bytesWritten = (nuint)encoding.GetBytes(strPtr, str.Length, (byte*)Ptr, maxBytesCount);
if (bytesWritten < 0 || bytesWritten > maxBytesCount)
{
Marshal.FreeHGlobal(Ptr);
Ptr = IntPtr.Zero;
Length = 0;
return;
}

Length = (nuint)bytesWritten
*((byte*)Ptr + Length) = 0; // Add null terminator

Check failure

Code scanning / CodeQL

Unvalidated local pointer arithmetic Critical

Unvalidated pointer arithmetic from virtual method
GetBytes
.

Copilot Autofix

AI 2 days ago

To fix this problem, the result from the virtual method call (encoding.GetBytes) must be validated to ensure it is both non-negative and does not exceed the allocated buffer size (maxBytesCount), before using it in pointer arithmetic or memory access operations. In this instance, we should check that Length >= 0 && Length <= (nuint)maxBytesCount before writing the null terminator at *((byte*)Ptr + Length). If the value is outside this range, we should fail by freeing the allocation and setting Ptr and Length appropriately so the struct is left in a valid state and does not attempt an out-of-bounds write. All code changes need to be inside the CString(string? str) constructor in tracer/src/Datadog.Trace/LibDatadog/CString.cs.


Suggested changeset 1
tracer/src/Datadog.Trace/LibDatadog/CString.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/tracer/src/Datadog.Trace/LibDatadog/CString.cs b/tracer/src/Datadog.Trace/LibDatadog/CString.cs
--- a/tracer/src/Datadog.Trace/LibDatadog/CString.cs
+++ b/tracer/src/Datadog.Trace/LibDatadog/CString.cs
@@ -36,7 +36,17 @@
                     try
                     {
                         Length = (nuint)encoding.GetBytes(strPtr, str.Length, (byte*)Ptr, maxBytesCount);
-                        *((byte*)Ptr + Length) = 0; // Add null terminator
+                        if (Length > (nuint)maxBytesCount)
+                        {
+                            // Prevent out-of-bounds write (should never happen with correct/built-in encoding)
+                            Marshal.FreeHGlobal(Ptr);
+                            Ptr = IntPtr.Zero;
+                            Length = UIntPtr.Zero;
+                        }
+                        else
+                        {
+                            *((byte*)Ptr + Length) = 0; // Add null terminator
+                        }
                     }
                     catch
                     {
EOF
@@ -36,7 +36,17 @@
try
{
Length = (nuint)encoding.GetBytes(strPtr, str.Length, (byte*)Ptr, maxBytesCount);
*((byte*)Ptr + Length) = 0; // Add null terminator
if (Length > (nuint)maxBytesCount)
{
// Prevent out-of-bounds write (should never happen with correct/built-in encoding)
Marshal.FreeHGlobal(Ptr);
Ptr = IntPtr.Zero;
Length = UIntPtr.Zero;
}
else
{
*((byte*)Ptr + Length) = 0; // Add null terminator
}
}
catch
{
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
}
catch
{
Marshal.FreeHGlobal(Ptr);
Ptr = IntPtr.Zero;
Length = 0;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ internal static ConfigurationResult GetConfiguration(string? handsOffLocalConfig
CString? localPath = null;
CString? fleetPath = null;
var configHandle = IntPtr.Zero;
Error? resultError = null;
LibraryConfigs? libraryConfigs = null;
LibraryConfigResult? configurationResult = null;
try
{
languageCs = new CharSlice(TracerConstants.Language);
Expand All @@ -55,26 +54,26 @@ internal static ConfigurationResult GetConfiguration(string? handsOffLocalConfig
NativeInterop.LibraryConfig.ConfiguratorWithFleetPath(configHandle, fleetPath.Value);
}

var configurationResult = NativeInterop.LibraryConfig.ConfiguratorGet(configHandle);
var result = configurationResult.Result;
configurationResult = NativeInterop.LibraryConfig.ConfiguratorGet(configHandle);
var result = configurationResult.Value.Result;

if (configurationResult.Tag == ResultTag.Err)
if (configurationResult.Value.Tag == ResultTag.Err)
{
resultError = result.Error;
var error = resultError.Value.Message.ToUtf8String();
var resultError = result.Error;
var error = resultError.Message.ToUtf8String();
return new ConfigurationResult(null, error, Result.LibDatadogCallError);
}

libraryConfigs = result.Ok;
var configsLength = (int)libraryConfigs.Value.Length;
var libraryConfigs = result.Ok;
var configsLength = (int)libraryConfigs.Length;
var configEntriesLocal = new Dictionary<string, string>();
var configEntriesRemote = new Dictionary<string, string>();
var structSize = Marshal.SizeOf<LibraryConfig>();
for (var i = 0; i < configsLength; i++)
{
unsafe
{
var ptr = new IntPtr(libraryConfigs.Value.Ptr + (structSize * i));
var ptr = new IntPtr(libraryConfigs.Ptr + (structSize * i));
var libraryConfig = (LibraryConfig*)ptr;
var name = libraryConfig->Name.ToUtf8String();
var value = libraryConfig->Value.ToUtf8String();
Expand All @@ -100,15 +99,10 @@ internal static ConfigurationResult GetConfiguration(string? handsOffLocalConfig
languageCs?.Dispose();
localPath?.Dispose();
fleetPath?.Dispose();
if (resultError.HasValue)
{
var resultErrorValue = resultError.Value;
NativeInterop.Common.DropError(ref resultErrorValue);
}

if (libraryConfigs.HasValue)
if (configurationResult.HasValue)
{
NativeInterop.LibraryConfig.LibraryConfigDrop(libraryConfigs.Value);
NativeInterop.LibraryConfig.LibraryConfigDrop(configurationResult.Value);
}

if (configHandle != IntPtr.Zero)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ internal struct LibraryConfigs
public nint Ptr; // const LibraryConfig*
public nuint Length;
public nuint Capacity;
public CString Logs; // ffi::CString
}
23 changes: 12 additions & 11 deletions tracer/src/Datadog.Trace/LibDatadog/NativeInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,17 @@ internal static class Common

internal static class LibraryConfig
{
[DllImport(DllName, EntryPoint = "ddog_store_tracer_metadata")]
internal static extern TracerMemfdHandleResult StoreTracerMetadata(
byte schemaVersion,
CharSlice runtimeId,
CharSlice tracerLanguage,
CharSlice tracerVersion,
CharSlice hostname,
CharSlice serviceName,
CharSlice serviceEnv,
CharSlice serviceVersion);
[DllImport(DllName, EntryPoint = "ddog_tracer_metadata_new")]
internal static extern IntPtr TracerMetadataNew();

[DllImport(DllName, EntryPoint = "ddog_tracer_metadata_free")]
internal static extern void TracerMetadataFree(IntPtr metadata);

[DllImport(DllName, EntryPoint = "ddog_tracer_metadata_set")]
internal static extern void TracerMetadataSet(IntPtr metadata, MetadataKind kind, CString value);

[DllImport(DllName, EntryPoint = "ddog_tracer_metadata_store")]
internal static extern TracerMemfdHandleResult StoreTracerMetadata(IntPtr metadata);

[DllImport(DllName, EntryPoint = "ddog_library_configurator_new")]
internal static extern IntPtr ConfiguratorNew(byte debugLogs, CharSlice language);
Expand All @@ -143,6 +144,6 @@ internal static extern TracerMemfdHandleResult StoreTracerMetadata(
internal static extern void ConfiguratorDrop(IntPtr configurator);

[DllImport(DllName, EntryPoint = "ddog_library_config_drop")]
internal static extern void LibraryConfigDrop(LibraryConfigs configs);
internal static extern void LibraryConfigDrop(LibraryConfigResult configs);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// <copyright file="MetadataKind.cs" company="Datadog">
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

#nullable enable
using System;

namespace Datadog.Trace.LibDatadog.ServiceDiscovery;

internal enum MetadataKind : int
{
RuntimeId = 0,
TracerLanguage = 1,
TracerVersion = 2,
Hostname = 3,
ServiceName = 4,
ServiceEnvironment = 5,
ServiceVersion = 6,
ProcessTags = 7,
ContainerId = 8,
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ internal static StoreMetadataResult StoreTracerMetadata(TracerSettings tracerSet
try
{
var result = StoreTracerMetadata(
1,
Tracer.RuntimeId,
TracerConstants.Language,
TracerConstants.ThreePartVersion,
Expand Down Expand Up @@ -66,7 +65,6 @@ internal static StoreMetadataResult StoreTracerMetadata(TracerSettings tracerSet
}

private static TracerMemfdHandleResult StoreTracerMetadata(
byte schemaVersion,
string runtimeId,
string tracerLanguage,
string tracerVersion,
Expand All @@ -75,14 +73,32 @@ private static TracerMemfdHandleResult StoreTracerMetadata(
string? serviceEnv,
string? serviceVersion)
{
using var runtimeIdCharSlice = new CharSlice(runtimeId);
using var tracerLanguageCharSlice = new CharSlice(tracerLanguage);
using var tracerVersionCharSlice = new CharSlice(tracerVersion);
using var hostnameCharSlice = new CharSlice(hostname);
using var serviceNameCharSlice = new CharSlice(serviceName);
using var serviceEnvCharSlice = new CharSlice(serviceEnv);
using var serviceVersionCharSlice = new CharSlice(serviceVersion);
IntPtr ptr = IntPtr.Zero;
try
{
ptr = NativeInterop.LibraryConfig.TracerMetadataNew();
SetMetadata(ptr, MetadataKind.RuntimeId, runtimeId);
SetMetadata(ptr, MetadataKind.TracerLanguage, tracerLanguage);
SetMetadata(ptr, MetadataKind.TracerVersion, tracerVersion);
SetMetadata(ptr, MetadataKind.Hostname, hostname);
SetMetadata(ptr, MetadataKind.ServiceName, serviceName);
SetMetadata(ptr, MetadataKind.ServiceEnvironment, serviceEnv);
SetMetadata(ptr, MetadataKind.ServiceVersion, serviceVersion);

return NativeInterop.LibraryConfig.StoreTracerMetadata(schemaVersion, runtimeIdCharSlice, tracerLanguageCharSlice, tracerVersionCharSlice, hostnameCharSlice, serviceNameCharSlice, serviceEnvCharSlice, serviceVersionCharSlice);
return NativeInterop.LibraryConfig.StoreTracerMetadata(ptr);
}
finally
{
if (ptr != IntPtr.Zero)
{
NativeInterop.LibraryConfig.TracerMetadataFree(ptr);
}
}

void SetMetadata(IntPtr ptr, MetadataKind kind, string? value)
{
using var valueCharSlice = new CString(value);
NativeInterop.LibraryConfig.TracerMetadataSet(ptr, kind, valueCharSlice);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ public async Task SendsTracesUsingDataPipeline(TestTransports transport)
.And.AllSatisfy(rates => rates.Should().BeEquivalentTo(expectedRates));
sampleRateResponses.Should().ContainSingle();

// Assert telemetry payloads were sent
await agent.WaitForLatestTelemetryAsync(t => t != null);
agent.Telemetry.Should().NotBeNull();

Dictionary<string, object> GetSettings()
{
var settingsMap = new Dictionary<string, object>
Expand Down Expand Up @@ -175,11 +179,11 @@ Dictionary<string, object> GetSettings()
MockTracerAgent GetAgent()
=> transport switch
{
TestTransports.Tcp => MockTracerAgent.Create(null),
TestTransports.WindowsNamedPipe => MockTracerAgent.Create(null, new WindowsPipesConfig(pipeName, null)),
TestTransports.Tcp => MockTracerAgent.Create(null, useTelemetry: true),
TestTransports.WindowsNamedPipe => MockTracerAgent.Create(null, new WindowsPipesConfig(pipeName, null) { UseTelemetry = true }),
#if NETCOREAPP3_1_OR_GREATER
TestTransports.Uds
=> MockTracerAgent.Create(null, new UnixDomainSocketConfig(udsPath, null)),
=> MockTracerAgent.Create(null, new UnixDomainSocketConfig(udsPath, null) { UseTelemetry = true }),
#endif
_ => throw new InvalidOperationException("Unsupported transport type " + transport),
};
Expand Down
Loading