From 2d2765cd13910cbcaba5fdc78fd5601b6eb44fd3 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 5 May 2026 08:10:46 +0200 Subject: [PATCH 01/11] feat: expose attachment types Expose attachment type setters together with well-known type constants so downstream SDKs can mark attachments such as view hierarchy payloads as "event.view_hierarchy". Co-Authored-By: OpenAI Codex --- CHANGELOG.md | 1 + include/sentry.h | 18 ++++++++++ src/backends/native/sentry_crash_daemon.c | 43 ++++++++++++++++------- src/backends/sentry_backend_breakpad.cpp | 4 +-- src/backends/sentry_backend_crashpad.cpp | 5 +-- src/backends/sentry_backend_native.c | 4 +++ src/sentry_attachment.c | 38 ++++++++++++++++---- src/sentry_attachment.h | 15 ++------ src/sentry_core.c | 6 ++-- src/sentry_database.c | 2 +- src/sentry_envelope.c | 31 ++++------------ src/sentry_envelope.h | 2 +- src/sentry_hint.c | 8 ++--- src/sentry_options.c | 15 ++++---- src/sentry_scope.c | 8 ++--- tests/unit/test_attachments.c | 18 +++++----- tests/unit/test_envelopes.c | 9 +++-- 17 files changed, 134 insertions(+), 93 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8193411534..01926f54a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Crashpad: add error log for oversized envelopes (HTTP 413 Content Too Large). ([#1706](https://github.com/getsentry/sentry-native/pull/1706), [crashpad#155](https://github.com/getsentry/crashpad/pull/155)) - Crashpad: support modifying attachments after `sentry_init` on macOS. ([#1705](https://github.com/getsentry/sentry-native/pull/1705), [crashpad#153](https://github.com/getsentry/crashpad/pull/153)) - Add `cache_dir` envelope header for external crash reporters. ([#1698](https://github.com/getsentry/sentry-native/pull/1698)) +- Add `sentry_attachment_set_type` and `SENTRY_ATTACHMENT_TYPE_*` for common envelope attachment types. ([#TODO](https://github.com/getsentry/sentry-native/pull/TODO)) **Fixes**: diff --git a/include/sentry.h b/include/sentry.h index 3af07fc4b5..f9188cb9a0 100644 --- a/include/sentry.h +++ b/include/sentry.h @@ -2757,6 +2757,24 @@ SENTRY_API sentry_attachment_t *sentry_scope_attach_bytesw_n( const wchar_t *filename, size_t filename_len); #endif +#define SENTRY_ATTACHMENT_TYPE_GENERIC "event.attachment" +#define SENTRY_ATTACHMENT_TYPE_MINIDUMP "event.minidump" +#define SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY "event.view_hierarchy" + +/** + * Sets the attachment type. + * + * Well-known attachment types are exposed as `SENTRY_ATTACHMENT_TYPE_*` + * macros. Pass `NULL` or an empty string to clear the attachment type. + * + * See: + * https://develop.sentry.dev/sdk/telemetry/attachments/#attachment-types + */ +SENTRY_API void sentry_attachment_set_type( + sentry_attachment_t *attachment, const char *type); +SENTRY_API void sentry_attachment_set_type_n( + sentry_attachment_t *attachment, const char *type, size_t type_len); + /** * Sets the content type of attachment. */ diff --git a/src/backends/native/sentry_crash_daemon.c b/src/backends/native/sentry_crash_daemon.c index c06a50154d..ba2f7fc945 100644 --- a/src/backends/native/sentry_crash_daemon.c +++ b/src/backends/native/sentry_crash_daemon.c @@ -79,7 +79,7 @@ __asan_default_options(void) */ static bool write_attachment_to_envelope(int fd, const char *file_path, - const char *filename, const char *content_type) + const char *filename, const char *attachment_type, const char *content_type) { #if defined(SENTRY_PLATFORM_UNIX) int attach_fd = open(file_path, O_RDONLY); @@ -118,16 +118,20 @@ write_attachment_to_envelope(int fd, const char *file_path, if (content_type) { header_written = snprintf(header, sizeof(header), "{\"type\":\"attachment\",\"length\":%lld," - "\"attachment_type\":\"event.attachment\"," + "\"attachment_type\":\"%s\"," "\"content_type\":\"%s\"," "\"filename\":\"%s\"}\n", - file_size, content_type, filename ? filename : "attachment"); + file_size, + attachment_type ? attachment_type : SENTRY_ATTACHMENT_TYPE_GENERIC, + content_type, filename ? filename : "attachment"); } else { header_written = snprintf(header, sizeof(header), "{\"type\":\"attachment\",\"length\":%lld," - "\"attachment_type\":\"event.attachment\"," + "\"attachment_type\":\"%s\"," "\"filename\":\"%s\"}\n", - file_size, filename ? filename : "attachment"); + file_size, + attachment_type ? attachment_type : SENTRY_ATTACHMENT_TYPE_GENERIC, + filename ? filename : "attachment"); } if (header_written < 0 || header_written >= (int)sizeof(header)) { @@ -204,7 +208,6 @@ attachment_is_placeholder(const sentry_options_t *options, const char *path) if (!attachment.path) { return false; } - attachment.type = ATTACHMENT; bool is_placeholder = sentry__attachment_is_placeholder(&attachment, options); sentry__path_free(attachment.path); @@ -252,6 +255,8 @@ add_attachment_refs(sentry_envelope_t *envelope, = sentry_value_as_string(sentry_value_get_by_key(info, "path")); const char *filename = sentry_value_as_string(sentry_value_get_by_key(info, "filename")); + const char *attachment_type = sentry_value_as_string( + sentry_value_get_by_key(info, "attachment_type")); const char *content_type = sentry_value_as_string( sentry_value_get_by_key(info, "content_type")); if (sentry__string_empty(path) || sentry__string_empty(filename)) { @@ -267,7 +272,9 @@ add_attachment_refs(sentry_envelope_t *envelope, sentry__path_free(attachment.filename); continue; } - attachment.type = ATTACHMENT; + attachment.type + = (char *)((attachment_type && *attachment_type) ? attachment_type + : NULL); attachment.content_type = sentry__string_empty(content_type) ? NULL : (char *)content_type; if (!sentry__attachment_is_placeholder(&attachment, options)) { @@ -2472,6 +2479,9 @@ write_envelope_with_native_stacktrace(const sentry_options_t *options, = sentry_value_get_by_key(attach_info, "path"); sentry_value_t filename_val = sentry_value_get_by_key(attach_info, "filename"); + sentry_value_t attachment_type_val + = sentry_value_get_by_key( + attach_info, "attachment_type"); sentry_value_t content_type_val = sentry_value_get_by_key( attach_info, "content_type"); @@ -2479,13 +2489,15 @@ write_envelope_with_native_stacktrace(const sentry_options_t *options, const char *path = sentry_value_as_string(path_val); const char *filename = sentry_value_as_string(filename_val); + const char *attachment_type + = sentry_value_as_string(attachment_type_val); const char *content_type = sentry_value_as_string(content_type_val); if (path && filename && !attachment_is_placeholder(options, path)) { - write_attachment_to_envelope( - fd, path, filename, content_type); + write_attachment_to_envelope(fd, path, filename, + attachment_type, content_type); } } sentry_value_decref(attach_list); @@ -2500,7 +2512,7 @@ write_envelope_with_native_stacktrace(const sentry_options_t *options, = sentry__path_join_str(run_folder, "screenshot.png"); if (screenshot_path) { write_attachment_to_envelope( - fd, screenshot_path->path, "screenshot.png", "image/png"); + fd, screenshot_path->path, "screenshot.png", NULL, "image/png"); sentry__path_free(screenshot_path); } } @@ -2719,6 +2731,9 @@ write_envelope_with_minidump(const sentry_options_t *options, = sentry_value_get_by_key(attach_info, "path"); sentry_value_t filename_val = sentry_value_get_by_key(attach_info, "filename"); + sentry_value_t attachment_type_val + = sentry_value_get_by_key( + attach_info, "attachment_type"); sentry_value_t content_type_val = sentry_value_get_by_key( attach_info, "content_type"); @@ -2726,13 +2741,15 @@ write_envelope_with_minidump(const sentry_options_t *options, const char *path = sentry_value_as_string(path_val); const char *filename = sentry_value_as_string(filename_val); + const char *attachment_type + = sentry_value_as_string(attachment_type_val); const char *content_type = sentry_value_as_string(content_type_val); if (path && filename && !attachment_is_placeholder(options, path)) { - write_attachment_to_envelope( - fd, path, filename, content_type); + write_attachment_to_envelope(fd, path, filename, + attachment_type, content_type); } } sentry_value_decref(attach_list); @@ -2747,7 +2764,7 @@ write_envelope_with_minidump(const sentry_options_t *options, = sentry__path_join_str(run_folder, "screenshot.png"); if (screenshot_path) { write_attachment_to_envelope( - fd, screenshot_path->path, "screenshot.png", "image/png"); + fd, screenshot_path->path, "screenshot.png", NULL, "image/png"); sentry__path_free(screenshot_path); } } diff --git a/src/backends/sentry_backend_breakpad.cpp b/src/backends/sentry_backend_breakpad.cpp index 63aa5c5b66..d2aec1a3d4 100644 --- a/src/backends/sentry_backend_breakpad.cpp +++ b/src/backends/sentry_backend_breakpad.cpp @@ -195,14 +195,14 @@ breakpad_backend_callback(const google_breakpad::MinidumpDescriptor &descriptor, envelope, dump_path, "attachment"); if (item) { sentry__envelope_item_set_header(item, "attachment_type", - sentry_value_new_string("event.minidump")); + sentry_value_new_string(SENTRY_ATTACHMENT_TYPE_MINIDUMP)); sentry__envelope_item_set_header(item, "filename", sentry_value_new_string(sentry__path_filename(dump_path))); } else if (options->enable_large_attachments) { sentry_attachment_t tmp = {}; tmp.path = dump_path; - tmp.type = MINIDUMP; + tmp.type = SENTRY_ATTACHMENT_TYPE_MINIDUMP; if (!sentry__cache_attachment_ref( envelope, &tmp, options->run->cache_path, nullptr)) { SENTRY_SIGNAL_SAFE_LOG( diff --git a/src/backends/sentry_backend_crashpad.cpp b/src/backends/sentry_backend_crashpad.cpp index 5e2b9c3181..098156c054 100644 --- a/src/backends/sentry_backend_crashpad.cpp +++ b/src/backends/sentry_backend_crashpad.cpp @@ -522,7 +522,7 @@ report_to_envelope(const crashpad::CrashReportDatabase::Report &report, breadcrumbs2 = read_msgpack_file(path); } else { sentry__attachments_add_path(&attachments, - sentry__path_clone(path), ATTACHMENT, nullptr); + sentry__path_clone(path), nullptr, nullptr); } } sentry__pathiter_free(iter); @@ -542,7 +542,8 @@ report_to_envelope(const crashpad::CrashReportDatabase::Report &report, sentry__value_merge_breadcrumbs( breadcrumbs1, breadcrumbs2, options->max_breadcrumbs)); sentry__attachments_add_path( - &attachments, minidump_path, MINIDUMP, nullptr); + &attachments, minidump_path, SENTRY_ATTACHMENT_TYPE_MINIDUMP, + nullptr); if (sentry__envelope_add_event(envelope, event)) { sentry__envelope_add_attachments(envelope, attachments, options); diff --git a/src/backends/sentry_backend_native.c b/src/backends/sentry_backend_native.c index 9d5e67c707..f6b7c758ed 100644 --- a/src/backends/sentry_backend_native.c +++ b/src/backends/sentry_backend_native.c @@ -735,6 +735,10 @@ native_backend_write_attachments(const sentry_path_t *event_path) it->filename ? it->filename : it->path); sentry_value_set_by_key( attach_info, "filename", sentry_value_new_string(filename)); + if (it->type && *it->type) { + sentry_value_set_by_key(attach_info, "attachment_type", + sentry_value_new_string(it->type)); + } if (it->content_type) { sentry_value_set_by_key(attach_info, "content_type", sentry_value_new_string(it->content_type)); diff --git a/src/sentry_attachment.c b/src/sentry_attachment.c index 3537d9cf3b..37741c7827 100644 --- a/src/sentry_attachment.c +++ b/src/sentry_attachment.c @@ -7,6 +7,26 @@ #include +void +sentry_attachment_set_type(sentry_attachment_t *attachment, const char *type) +{ + sentry_attachment_set_type_n( + attachment, type, sentry__guarded_strlen(type)); +} + +void +sentry_attachment_set_type_n( + sentry_attachment_t *attachment, const char *type, size_t type_len) +{ + if (!attachment) { + return; + } + + sentry_free(attachment->type); + attachment->type + = type && type_len > 0 ? sentry__string_clone_n(type, type_len) : NULL; +} + void sentry_attachment_set_content_type( sentry_attachment_t *attachment, const char *content_type) @@ -117,6 +137,7 @@ sentry__attachment_free(sentry_attachment_t *attachment) sentry__path_free(attachment->path); sentry__path_free(attachment->filename); sentry_free(attachment->buf); + sentry_free(attachment->type); sentry_free(attachment->content_type); sentry_free(attachment); } @@ -141,7 +162,6 @@ sentry__attachment_is_placeholder( const sentry_attachment_t *att, const sentry_options_t *options) { return options && options->enable_large_attachments && att - && att->type == ATTACHMENT && sentry__attachment_get_size(att) >= SENTRY_LARGE_ATTACHMENT_SIZE; } @@ -170,7 +190,12 @@ attachment_eq(const sentry_attachment_t *a, const sentry_attachment_t *b) if (a == b) { return true; } - if (!a || !b || a->buf || b->buf || a->type != b->type) { + if (!a || !b || a->buf || b->buf) { + return false; + } + const char *a_type = a->type ? a->type : ""; + const char *b_type = b->type ? b->type : ""; + if (!sentry__string_eq(a_type, b_type)) { return false; } return sentry__path_eq(a->path, b->path); @@ -178,7 +203,7 @@ attachment_eq(const sentry_attachment_t *a, const sentry_attachment_t *b) sentry_attachment_t * sentry__attachments_add(sentry_attachment_t **attachments_ptr, - sentry_attachment_t *attachment, sentry_attachment_type_t attachment_type, + sentry_attachment_t *attachment, const char *attachment_type, const char *content_type) { if (!attachment) { @@ -196,8 +221,8 @@ sentry__attachments_add(sentry_attachment_t **attachments_ptr, SENTRY_INFOF("added large attachment \"%s\" (%zu MiB)", sentry__attachment_get_filename(attachment), size / (1024 * 1024)); } - attachment->type = attachment_type; - attachment->content_type = sentry__string_clone(content_type); + sentry_attachment_set_type(attachment, attachment_type); + sentry_attachment_set_content_type(attachment, content_type); sentry_attachment_t **next_ptr = attachments_ptr; @@ -216,8 +241,7 @@ sentry__attachments_add(sentry_attachment_t **attachments_ptr, sentry_attachment_t * sentry__attachments_add_path(sentry_attachment_t **attachments_ptr, - sentry_path_t *path, sentry_attachment_type_t attachment_type, - const char *content_type) + sentry_path_t *path, const char *attachment_type, const char *content_type) { sentry_attachment_t *attachment = sentry__attachment_from_path(path); return sentry__attachments_add( diff --git a/src/sentry_attachment.h b/src/sentry_attachment.h index 306ff66def..8a77eda994 100644 --- a/src/sentry_attachment.h +++ b/src/sentry_attachment.h @@ -8,15 +8,6 @@ #define SENTRY_LARGE_ATTACHMENT_SIZE (100 * 1024 * 1024) // 100 MiB #define SENTRY_MAX_ATTACHMENT_SIZE (1024 * 1024 * 1024) // 1 GiB -/** - * The attachment_type. - */ -typedef enum { - ATTACHMENT, - MINIDUMP, - VIEW_HIERARCHY, -} sentry_attachment_type_t; - /** * This is a linked list of all the attachments registered via * `sentry_options_add_attachment`. @@ -38,7 +29,7 @@ struct sentry_attachment_s { // Common fields for both attachment types sentry_path_t *filename; // Attachment name in envelope (can be NULL) - sentry_attachment_type_t type; + char *type; char *content_type; sentry_attachment_t *next; // Linked list pointer }; @@ -89,14 +80,14 @@ void sentry__attachments_free(sentry_attachment_t *attachments); */ sentry_attachment_t *sentry__attachments_add( sentry_attachment_t **attachments_ptr, sentry_attachment_t *attachment, - sentry_attachment_type_t attachment_type, const char *content_type); + const char *attachment_type, const char *content_type); /** * Adds a file attachment to the attachments list at `attachments_ptr`. */ sentry_attachment_t *sentry__attachments_add_path( sentry_attachment_t **attachments_ptr, sentry_path_t *path, - sentry_attachment_type_t attachment_type, const char *content_type); + const char *attachment_type, const char *content_type); /** * Removes an attachment from the attachments list at `attachments_ptr`. diff --git a/src/sentry_core.c b/src/sentry_core.c index 815aa2b71f..ec3f1750cb 100644 --- a/src/sentry_core.c +++ b/src/sentry_core.c @@ -1781,7 +1781,7 @@ sentry_capture_minidump_n(const char *path, size_t path_len) >= SENTRY_LARGE_ATTACHMENT_SIZE) { sentry_attachment_t tmp = { 0 }; tmp.path = dump_path; - tmp.type = MINIDUMP; + tmp.type = SENTRY_ATTACHMENT_TYPE_MINIDUMP; if (!sentry__cache_attachment_ref( envelope, &tmp, options->run->cache_path, NULL)) { SENTRY_WARN("failed to cache minidump attachment-ref"); @@ -1810,7 +1810,7 @@ sentry_capture_minidump_n(const char *path, size_t path_len) sentry_envelope_free(envelope); } else { sentry__envelope_item_set_header(item, "attachment_type", - sentry_value_new_string("event.minidump")); + sentry_value_new_string(SENTRY_ATTACHMENT_TYPE_MINIDUMP)); sentry__envelope_item_set_header(item, "filename", sentry_value_new_string(sentry__path_filename(dump_path))); @@ -1843,7 +1843,7 @@ add_attachment(sentry_attachment_t *attachment) } SENTRY_WITH_SCOPE_MUT (scope) { attachment = sentry__attachments_add( - &scope->attachments, attachment, ATTACHMENT, NULL); + &scope->attachments, attachment, NULL, NULL); } return attachment; } diff --git a/src/sentry_database.c b/src/sentry_database.c index 84078bda7f..ced802ebfc 100644 --- a/src/sentry_database.c +++ b/src/sentry_database.c @@ -290,7 +290,7 @@ static sentry_path_t * build_sibling_path(const sentry_path_t *cache_path, const char *uuid_str, const sentry_attachment_t *att) { - if (att->type == MINIDUMP) { + if (att->type && strcmp(att->type, SENTRY_ATTACHMENT_TYPE_MINIDUMP) == 0) { char buf[41]; snprintf(buf, sizeof(buf), "%s.dmp", uuid_str); return sentry__path_unique(cache_path, buf); diff --git a/src/sentry_envelope.c b/src/sentry_envelope.c index 3214ff86a3..6ca84cf67a 100644 --- a/src/sentry_envelope.c +++ b/src/sentry_envelope.c @@ -637,22 +637,6 @@ sentry__envelope_add_session( envelope, payload, payload_len, "session"); } -static const char * -str_from_attachment_type(sentry_attachment_type_t attachment_type) -{ - switch (attachment_type) { - case ATTACHMENT: - return "event.attachment"; - case MINIDUMP: - return "event.minidump"; - case VIEW_HIERARCHY: - return "event.view_hierarchy"; - default: - UNREACHABLE("Unknown attachment type"); - return "event.attachment"; - } -} - static bool attachment_ref_has_payload(const sentry_attachment_ref_t *ref) { @@ -689,7 +673,7 @@ attachment_ref_payload_to_string( sentry_envelope_item_t * sentry__envelope_add_attachment_ref(sentry_envelope_t *envelope, const sentry_attachment_ref_t *ref, const char *filename, - sentry_attachment_type_t attachment_type, size_t attachment_length) + const char *attachment_type, size_t attachment_length) { if (!envelope) { return NULL; @@ -719,9 +703,9 @@ sentry__envelope_add_attachment_ref(sentry_envelope_t *envelope, sentry__envelope_item_set_header( item, "filename", sentry_value_new_string(filename)); } - if (attachment_type != ATTACHMENT) { - sentry__envelope_item_set_header(item, "attachment_type", - sentry_value_new_string(str_from_attachment_type(attachment_type))); + if (attachment_type && *attachment_type) { + sentry__envelope_item_set_header( + item, "attachment_type", sentry_value_new_string(attachment_type)); } sentry__envelope_item_set_header(item, "attachment_length", sentry_value_new_uint64((uint64_t)attachment_length)); @@ -755,10 +739,9 @@ sentry__envelope_add_attachment( if (!item) { return NULL; } - if (attachment->type != ATTACHMENT) { // don't need to set the default - sentry__envelope_item_set_header(item, "attachment_type", - sentry_value_new_string( - str_from_attachment_type(attachment->type))); + if (attachment->type && *attachment->type) { + sentry__envelope_item_set_header( + item, "attachment_type", sentry_value_new_string(attachment->type)); } if (attachment->content_type) { sentry__envelope_item_set_header(item, "content_type", diff --git a/src/sentry_envelope.h b/src/sentry_envelope.h index fac42b418d..08d7213d42 100644 --- a/src/sentry_envelope.h +++ b/src/sentry_envelope.h @@ -112,7 +112,7 @@ void sentry__envelope_add_attachments(sentry_envelope_t *envelope, */ sentry_envelope_item_t *sentry__envelope_add_attachment_ref( sentry_envelope_t *envelope, const sentry_attachment_ref_t *ref, - const char *filename, sentry_attachment_type_t attachment_type, + const char *filename, const char *attachment_type, size_t attachment_length); /** diff --git a/src/sentry_hint.c b/src/sentry_hint.c index 13d9a0e6e6..a67b7dafd8 100644 --- a/src/sentry_hint.c +++ b/src/sentry_hint.c @@ -41,7 +41,7 @@ sentry_hint_attach_file_n( return NULL; } return sentry__attachments_add_path(&hint->attachments, - sentry__path_from_str_n(path, path_len), ATTACHMENT, NULL); + sentry__path_from_str_n(path, path_len), NULL, NULL); } sentry_attachment_t * @@ -62,7 +62,7 @@ sentry_hint_attach_bytes_n(sentry_hint_t *hint, const char *buf, size_t buf_len, return sentry__attachments_add(&hint->attachments, sentry__attachment_from_buffer( buf, buf_len, sentry__path_from_str_n(filename, filename_len)), - ATTACHMENT, NULL); + NULL, NULL); } #ifdef SENTRY_PLATFORM_WINDOWS @@ -81,7 +81,7 @@ sentry_hint_attach_filew_n( return NULL; } return sentry__attachments_add_path(&hint->attachments, - sentry__path_from_wstr_n(path, path_len), ATTACHMENT, NULL); + sentry__path_from_wstr_n(path, path_len), NULL, NULL); } sentry_attachment_t * @@ -103,6 +103,6 @@ sentry_hint_attach_bytesw_n(sentry_hint_t *hint, const char *buf, return sentry__attachments_add(&hint->attachments, sentry__attachment_from_buffer( buf, buf_len, sentry__path_from_wstr_n(filename, filename_len)), - ATTACHMENT, NULL); + NULL, NULL); } #endif diff --git a/src/sentry_options.c b/src/sentry_options.c index 33554b5729..60c1fea221 100644 --- a/src/sentry_options.c +++ b/src/sentry_options.c @@ -617,7 +617,7 @@ void sentry_options_add_attachment(sentry_options_t *opts, const char *path) { sentry__attachments_add_path( - &opts->attachments, sentry__path_from_str(path), ATTACHMENT, NULL); + &opts->attachments, sentry__path_from_str(path), NULL, NULL); } void @@ -625,14 +625,15 @@ sentry_options_add_attachment_n( sentry_options_t *opts, const char *path, size_t path_len) { sentry__attachments_add_path(&opts->attachments, - sentry__path_from_str_n(path, path_len), ATTACHMENT, NULL); + sentry__path_from_str_n(path, path_len), NULL, NULL); } void sentry_options_add_view_hierarchy(sentry_options_t *opts, const char *path) { sentry__attachments_add_path(&opts->attachments, - sentry__path_from_str(path), VIEW_HIERARCHY, "application/json"); + sentry__path_from_str(path), SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY, + "application/json"); } void @@ -640,7 +641,8 @@ sentry_options_add_view_hierarchy_n( sentry_options_t *opts, const char *path, size_t path_len) { sentry__attachments_add_path(&opts->attachments, - sentry__path_from_str_n(path, path_len), VIEW_HIERARCHY, + sentry__path_from_str_n(path, path_len), + SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY, "application/json"); } @@ -723,7 +725,7 @@ sentry_options_add_attachmentw_n( sentry_options_t *opts, const wchar_t *path, size_t path_len) { sentry__attachments_add_path(&opts->attachments, - sentry__path_from_wstr_n(path, path_len), ATTACHMENT, NULL); + sentry__path_from_wstr_n(path, path_len), NULL, NULL); } void @@ -744,7 +746,8 @@ sentry_options_add_view_hierarchyw_n( sentry_options_t *opts, const wchar_t *path, size_t path_len) { sentry__attachments_add_path(&opts->attachments, - sentry__path_from_wstr_n(path, path_len), VIEW_HIERARCHY, + sentry__path_from_wstr_n(path, path_len), + SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY, "application/json"); } diff --git a/src/sentry_scope.c b/src/sentry_scope.c index f5d0d288f8..87728be4d3 100644 --- a/src/sentry_scope.c +++ b/src/sentry_scope.c @@ -629,7 +629,7 @@ sentry_scope_attach_file_n( sentry_scope_t *scope, const char *path, size_t path_len) { return sentry__attachments_add_path(&scope->attachments, - sentry__path_from_str_n(path, path_len), ATTACHMENT, NULL); + sentry__path_from_str_n(path, path_len), NULL, NULL); } sentry_attachment_t * @@ -647,7 +647,7 @@ sentry_scope_attach_bytes_n(sentry_scope_t *scope, const char *buf, return sentry__attachments_add(&scope->attachments, sentry__attachment_from_buffer( buf, buf_len, sentry__path_from_str_n(filename, filename_len)), - ATTACHMENT, NULL); + NULL, NULL); } #ifdef SENTRY_PLATFORM_WINDOWS @@ -663,7 +663,7 @@ sentry_scope_attach_filew_n( sentry_scope_t *scope, const wchar_t *path, size_t path_len) { return sentry__attachments_add_path(&scope->attachments, - sentry__path_from_wstr_n(path, path_len), ATTACHMENT, NULL); + sentry__path_from_wstr_n(path, path_len), NULL, NULL); } sentry_attachment_t * @@ -682,7 +682,7 @@ sentry_scope_attach_bytesw_n(sentry_scope_t *scope, const char *buf, return sentry__attachments_add(&scope->attachments, sentry__attachment_from_buffer( buf, buf_len, sentry__path_from_wstr_n(filename, filename_len)), - ATTACHMENT, NULL); + NULL, NULL); } #endif diff --git a/tests/unit/test_attachments.c b/tests/unit/test_attachments.c index f1ea3e45f1..16586e907e 100644 --- a/tests/unit/test_attachments.c +++ b/tests/unit/test_attachments.c @@ -16,7 +16,6 @@ SENTRY_TEST(attachment_placeholder) char data[] = "x"; sentry_attachment_t attachment = { 0 }; - attachment.type = ATTACHMENT; attachment.buf = data; attachment.buf_len = SENTRY_LARGE_ATTACHMENT_SIZE; @@ -29,9 +28,10 @@ SENTRY_TEST(attachment_placeholder) attachment.buf_len = SENTRY_LARGE_ATTACHMENT_SIZE; TEST_CHECK(sentry__attachment_is_placeholder(&attachment, options)); - attachment.type = MINIDUMP; - TEST_CHECK(!sentry__attachment_is_placeholder(&attachment, options)); + sentry_attachment_set_type(&attachment, SENTRY_ATTACHMENT_TYPE_MINIDUMP); + TEST_CHECK(sentry__attachment_is_placeholder(&attachment, options)); + sentry_free(attachment.type); sentry_options_free(options); } @@ -269,19 +269,19 @@ SENTRY_TEST(attachments_extend) sentry_attachment_t *attachments_abc = NULL; sentry__attachments_add_path( - &attachments_abc, sentry__path_clone(path_a), ATTACHMENT, NULL); + &attachments_abc, sentry__path_clone(path_a), NULL, NULL); sentry__attachments_add_path( - &attachments_abc, sentry__path_clone(path_b), ATTACHMENT, NULL); + &attachments_abc, sentry__path_clone(path_b), NULL, NULL); sentry__attachments_add_path( - &attachments_abc, sentry__path_clone(path_c), ATTACHMENT, NULL); + &attachments_abc, sentry__path_clone(path_c), NULL, NULL); sentry_attachment_t *attachments_bcd = NULL; sentry__attachments_add_path( - &attachments_bcd, sentry__path_clone(path_b), ATTACHMENT, NULL); + &attachments_bcd, sentry__path_clone(path_b), NULL, NULL); sentry__attachments_add_path( - &attachments_bcd, sentry__path_clone(path_c), ATTACHMENT, NULL); + &attachments_bcd, sentry__path_clone(path_c), NULL, NULL); sentry__attachments_add_path( - &attachments_bcd, sentry__path_clone(path_d), ATTACHMENT, NULL); + &attachments_bcd, sentry__path_clone(path_d), NULL, NULL); sentry_attachment_t *all_attachments = NULL; sentry__attachments_extend(&all_attachments, attachments_abc); diff --git a/tests/unit/test_envelopes.c b/tests/unit/test_envelopes.c index 843dfb9d95..d80a5bc741 100644 --- a/tests/unit/test_envelopes.c +++ b/tests/unit/test_envelopes.c @@ -922,7 +922,7 @@ SENTRY_TEST(attachment_ref_copy) sentry_attachment_t *attachment = sentry__attachment_from_path(sentry__path_clone(test_file_path)); - attachment->type = MINIDUMP; + sentry_attachment_set_type(attachment, SENTRY_ATTACHMENT_TYPE_MINIDUMP); sentry_attachment_set_content_type(attachment, "application/x-dmp"); sentry_envelope_t *envelope = sentry__envelope_new(); @@ -948,8 +948,8 @@ SENTRY_TEST(attachment_ref_copy) // envelope carries an attachment-ref item with the expected headers TEST_ASSERT(sentry__envelope_get_item_count(envelope) == 1); check_attachment_ref_item(envelope, 0, "sentry_test_minidump.dmp", - "application/x-dmp", "event.minidump", strlen("minidump_data"), - "c993afb6-b4ac-48a6-b61b-2558e601d65d.dmp"); + "application/x-dmp", SENTRY_ATTACHMENT_TYPE_MINIDUMP, + strlen("minidump_data"), "c993afb6-b4ac-48a6-b61b-2558e601d65d.dmp"); sentry_envelope_free(envelope); sentry__path_remove(cached); @@ -992,7 +992,6 @@ SENTRY_TEST(attachment_ref_move) sentry_attachment_t *attachment = sentry__attachment_from_path(sentry__path_clone(src_path)); - attachment->type = ATTACHMENT; sentry_envelope_t *envelope = sentry__envelope_new(); sentry__envelope_set_event_id(envelope, &event_id); @@ -1113,7 +1112,7 @@ SENTRY_TEST(attachment_ref_roundtrip) ref.path = "abc-crashlog.bin"; ref.content_type = "application/octet-stream"; sentry__envelope_add_attachment_ref( - envelope, &ref, "crashlog.bin", ATTACHMENT, 12345); + envelope, &ref, "crashlog.bin", NULL, 12345); size_t buf_len = 0; char *buf = sentry_envelope_serialize(envelope, &buf_len); From dc80e364b600830eb1cec988a53a69da631bb2f6 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 5 May 2026 13:05:21 +0200 Subject: [PATCH 02/11] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01926f54a2..a3436c383f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ - Crashpad: add error log for oversized envelopes (HTTP 413 Content Too Large). ([#1706](https://github.com/getsentry/sentry-native/pull/1706), [crashpad#155](https://github.com/getsentry/crashpad/pull/155)) - Crashpad: support modifying attachments after `sentry_init` on macOS. ([#1705](https://github.com/getsentry/sentry-native/pull/1705), [crashpad#153](https://github.com/getsentry/crashpad/pull/153)) - Add `cache_dir` envelope header for external crash reporters. ([#1698](https://github.com/getsentry/sentry-native/pull/1698)) -- Add `sentry_attachment_set_type` and `SENTRY_ATTACHMENT_TYPE_*` for common envelope attachment types. ([#TODO](https://github.com/getsentry/sentry-native/pull/TODO)) +- Add `sentry_attachment_set_type` and `SENTRY_ATTACHMENT_TYPE_*` macros for standard Sentry attachment types. ([#1700](https://github.com/getsentry/sentry-native/pull/1700)) **Fixes**: From 790645bdf7d89f2e3e454bffa94cc23e99bc87b8 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 5 May 2026 13:09:31 +0200 Subject: [PATCH 03/11] Fix formatting --- src/backends/sentry_backend_crashpad.cpp | 9 ++++----- src/sentry_options.c | 6 ++---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/backends/sentry_backend_crashpad.cpp b/src/backends/sentry_backend_crashpad.cpp index 098156c054..bdfd50a9c7 100644 --- a/src/backends/sentry_backend_crashpad.cpp +++ b/src/backends/sentry_backend_crashpad.cpp @@ -521,8 +521,8 @@ report_to_envelope(const crashpad::CrashReportDatabase::Report &report, } else if (strcmp(filename, "__sentry-breadcrumb2") == 0) { breadcrumbs2 = read_msgpack_file(path); } else { - sentry__attachments_add_path(&attachments, - sentry__path_clone(path), nullptr, nullptr); + sentry__attachments_add_path( + &attachments, sentry__path_clone(path), nullptr, nullptr); } } sentry__pathiter_free(iter); @@ -541,9 +541,8 @@ report_to_envelope(const crashpad::CrashReportDatabase::Report &report, sentry_value_set_by_key(event, "breadcrumbs", sentry__value_merge_breadcrumbs( breadcrumbs1, breadcrumbs2, options->max_breadcrumbs)); - sentry__attachments_add_path( - &attachments, minidump_path, SENTRY_ATTACHMENT_TYPE_MINIDUMP, - nullptr); + sentry__attachments_add_path(&attachments, minidump_path, + SENTRY_ATTACHMENT_TYPE_MINIDUMP, nullptr); if (sentry__envelope_add_event(envelope, event)) { sentry__envelope_add_attachments(envelope, attachments, options); diff --git a/src/sentry_options.c b/src/sentry_options.c index 60c1fea221..db75e66483 100644 --- a/src/sentry_options.c +++ b/src/sentry_options.c @@ -642,8 +642,7 @@ sentry_options_add_view_hierarchy_n( { sentry__attachments_add_path(&opts->attachments, sentry__path_from_str_n(path, path_len), - SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY, - "application/json"); + SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY, "application/json"); } void @@ -747,8 +746,7 @@ sentry_options_add_view_hierarchyw_n( { sentry__attachments_add_path(&opts->attachments, sentry__path_from_wstr_n(path, path_len), - SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY, - "application/json"); + SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY, "application/json"); } void From 2372c1e167dfadb468cd945736f0df8a2e5177f7 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 5 May 2026 13:26:38 +0200 Subject: [PATCH 04/11] Cast --- src/backends/sentry_backend_breakpad.cpp | 2 +- src/sentry_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/sentry_backend_breakpad.cpp b/src/backends/sentry_backend_breakpad.cpp index d2aec1a3d4..2929d3ce8a 100644 --- a/src/backends/sentry_backend_breakpad.cpp +++ b/src/backends/sentry_backend_breakpad.cpp @@ -202,7 +202,7 @@ breakpad_backend_callback(const google_breakpad::MinidumpDescriptor &descriptor, } else if (options->enable_large_attachments) { sentry_attachment_t tmp = {}; tmp.path = dump_path; - tmp.type = SENTRY_ATTACHMENT_TYPE_MINIDUMP; + tmp.type = (char *)SENTRY_ATTACHMENT_TYPE_MINIDUMP; if (!sentry__cache_attachment_ref( envelope, &tmp, options->run->cache_path, nullptr)) { SENTRY_SIGNAL_SAFE_LOG( diff --git a/src/sentry_core.c b/src/sentry_core.c index ec3f1750cb..d7923190da 100644 --- a/src/sentry_core.c +++ b/src/sentry_core.c @@ -1781,7 +1781,7 @@ sentry_capture_minidump_n(const char *path, size_t path_len) >= SENTRY_LARGE_ATTACHMENT_SIZE) { sentry_attachment_t tmp = { 0 }; tmp.path = dump_path; - tmp.type = SENTRY_ATTACHMENT_TYPE_MINIDUMP; + tmp.type = (char *)SENTRY_ATTACHMENT_TYPE_MINIDUMP; if (!sentry__cache_attachment_ref( envelope, &tmp, options->run->cache_path, NULL)) { SENTRY_WARN("failed to cache minidump attachment-ref"); From 6308a8db31b46283b580d347e920f47a8a0c87d5 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 7 May 2026 10:39:59 +0200 Subject: [PATCH 05/11] Use sentry__string_empty --- src/backends/native/sentry_crash_daemon.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/backends/native/sentry_crash_daemon.c b/src/backends/native/sentry_crash_daemon.c index ba2f7fc945..0438134f74 100644 --- a/src/backends/native/sentry_crash_daemon.c +++ b/src/backends/native/sentry_crash_daemon.c @@ -122,7 +122,9 @@ write_attachment_to_envelope(int fd, const char *file_path, "\"content_type\":\"%s\"," "\"filename\":\"%s\"}\n", file_size, - attachment_type ? attachment_type : SENTRY_ATTACHMENT_TYPE_GENERIC, + sentry__string_empty(attachment_type) + ? SENTRY_ATTACHMENT_TYPE_GENERIC + : attachment_type, content_type, filename ? filename : "attachment"); } else { header_written = snprintf(header, sizeof(header), @@ -130,7 +132,9 @@ write_attachment_to_envelope(int fd, const char *file_path, "\"attachment_type\":\"%s\"," "\"filename\":\"%s\"}\n", file_size, - attachment_type ? attachment_type : SENTRY_ATTACHMENT_TYPE_GENERIC, + sentry__string_empty(attachment_type) + ? SENTRY_ATTACHMENT_TYPE_GENERIC + : attachment_type, filename ? filename : "attachment"); } From ebbe27a57218a25e3d217cf2e54756d4a3db6810 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 12 May 2026 09:13:55 +0200 Subject: [PATCH 06/11] Deprecate sentry_options_add_view_hierarchy --- CHANGELOG.md | 1 + examples/example.c | 15 +++++++++------ include/sentry.h | 8 ++++++++ src/sentry_options.c | 5 ++++- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3436c383f..ad182827bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Crashpad: support modifying attachments after `sentry_init` on macOS. ([#1705](https://github.com/getsentry/sentry-native/pull/1705), [crashpad#153](https://github.com/getsentry/crashpad/pull/153)) - Add `cache_dir` envelope header for external crash reporters. ([#1698](https://github.com/getsentry/sentry-native/pull/1698)) - Add `sentry_attachment_set_type` and `SENTRY_ATTACHMENT_TYPE_*` macros for standard Sentry attachment types. ([#1700](https://github.com/getsentry/sentry-native/pull/1700)) + - Deprecate `sentry_options_add_view_hierarchy*` in favor of `sentry_attach_file*` with `sentry_attachment_set_type`. **Fixes**: diff --git a/examples/example.c b/examples/example.c index 3a88b8a46b..764079a675 100644 --- a/examples/example.c +++ b/examples/example.c @@ -683,12 +683,6 @@ main(int argc, char **argv) sentry_options_set_crashpad_wait_for_upload(options, true); } - if (has_arg(argc, argv, "attach-view-hierarchy")) { - // assuming the example / test is run directly from the cmake build - // directory - sentry_options_add_view_hierarchy(options, "./view-hierarchy.json"); - } - if (has_arg(argc, argv, "test-logger")) { // Set up the test logger for integration tests sentry_options_set_logger(options, test_logger_callback, NULL); @@ -862,6 +856,15 @@ main(int argc, char **argv) = sentry_attach_bytes("\xc0\xff\xee", 3, "bytes.bin"); sentry_attachment_set_content_type(bytes, "application/octet-stream"); } + if (has_arg(argc, argv, "attach-view-hierarchy")) { + // assuming the example / test is run directly from the cmake build + // directory + sentry_attachment_t *view_hierarchy + = sentry_attach_file("./view-hierarchy.json"); + sentry_attachment_set_type( + view_hierarchy, SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY); + sentry_attachment_set_content_type(view_hierarchy, "application/json"); + } if (sentry_options_get_enable_logs(options)) { if (has_arg(argc, argv, "capture-log")) { diff --git a/include/sentry.h b/include/sentry.h index f9188cb9a0..1b288cc376 100644 --- a/include/sentry.h +++ b/include/sentry.h @@ -1603,8 +1603,12 @@ SENTRY_API void sentry_options_add_attachment_n( * API Users on windows are encouraged to use * `sentry_options_add_view_hierarchyw` instead. */ +SENTRY_DEPRECATED("Use `sentry_attach_*` with `sentry_attachment_set_type` and " + "`SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY` instead") SENTRY_API void sentry_options_add_view_hierarchy( sentry_options_t *opts, const char *path); +SENTRY_DEPRECATED("Use `sentry_attach_*` with `sentry_attachment_set_type` and " + "`SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY` instead") SENTRY_API void sentry_options_add_view_hierarchy_n( sentry_options_t *opts, const char *path, size_t path_len); @@ -1771,8 +1775,12 @@ SENTRY_API void sentry_options_add_attachmentw_n( /** * Wide char version of `sentry_options_add_view_hierarchy`. */ +SENTRY_DEPRECATED("Use `sentry_attach_*` with `sentry_attachment_set_type` and " + "`SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY` instead") SENTRY_API void sentry_options_add_view_hierarchyw( sentry_options_t *opts, const wchar_t *path); +SENTRY_DEPRECATED("Use `sentry_attach_*` with `sentry_attachment_set_type` and " + "`SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY` instead") SENTRY_API void sentry_options_add_view_hierarchyw_n( sentry_options_t *opts, const wchar_t *path, size_t path_len); diff --git a/src/sentry_options.c b/src/sentry_options.c index db75e66483..9521f2e82a 100644 --- a/src/sentry_options.c +++ b/src/sentry_options.c @@ -738,8 +738,11 @@ void sentry_options_add_view_hierarchyw(sentry_options_t *opts, const wchar_t *path) { size_t path_len = path ? wcslen(path) : 0; - sentry_options_add_view_hierarchyw_n(opts, path, path_len); + sentry__attachments_add_path(&opts->attachments, + sentry__path_from_wstr_n(path, path_len), + SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY, "application/json"); } + void sentry_options_add_view_hierarchyw_n( sentry_options_t *opts, const wchar_t *path, size_t path_len) From 8d77f759b0c09000e31f0f1d7ed259da4f5b1bac Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 12 May 2026 09:38:39 +0200 Subject: [PATCH 07/11] Adapt session replay mp4's --- src/backends/native/sentry_crash_daemon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/native/sentry_crash_daemon.c b/src/backends/native/sentry_crash_daemon.c index 0438134f74..d8355ed4a1 100644 --- a/src/backends/native/sentry_crash_daemon.c +++ b/src/backends/native/sentry_crash_daemon.c @@ -2527,7 +2527,7 @@ write_envelope_with_native_stacktrace(const sentry_options_t *options, = sentry__path_join_str(run_folder, "session-replay.mp4"); if (replay_path) { write_attachment_to_envelope( - fd, replay_path->path, "session-replay.mp4", "video/mp4"); + fd, replay_path->path, "session-replay.mp4", NULL, "video/mp4"); sentry__path_free(replay_path); } } @@ -2779,7 +2779,7 @@ write_envelope_with_minidump(const sentry_options_t *options, = sentry__path_join_str(run_folder, "session-replay.mp4"); if (replay_path) { write_attachment_to_envelope( - fd, replay_path->path, "session-replay.mp4", "video/mp4"); + fd, replay_path->path, "session-replay.mp4", NULL, "video/mp4"); sentry__path_free(replay_path); } } From 4f35c4541571313d60b165926060a7a6453f7e5f Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 12 May 2026 10:46:59 +0200 Subject: [PATCH 08/11] infer content type from attachment type unless explicitly set --- examples/example.c | 1 - src/sentry_attachment.c | 15 ++++++++++++++- tests/unit/test_attachments.c | 15 +++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/examples/example.c b/examples/example.c index 764079a675..4e2aa3c3b8 100644 --- a/examples/example.c +++ b/examples/example.c @@ -863,7 +863,6 @@ main(int argc, char **argv) = sentry_attach_file("./view-hierarchy.json"); sentry_attachment_set_type( view_hierarchy, SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY); - sentry_attachment_set_content_type(view_hierarchy, "application/json"); } if (sentry_options_get_enable_logs(options)) { diff --git a/src/sentry_attachment.c b/src/sentry_attachment.c index 37741c7827..ed8c4e4a2b 100644 --- a/src/sentry_attachment.c +++ b/src/sentry_attachment.c @@ -25,6 +25,17 @@ sentry_attachment_set_type_n( sentry_free(attachment->type); attachment->type = type && type_len > 0 ? sentry__string_clone_n(type, type_len) : NULL; + + if (attachment->type && !attachment->content_type) { + if (sentry__string_eq( + attachment->type, SENTRY_ATTACHMENT_TYPE_MINIDUMP)) { + attachment->content_type + = sentry__string_clone("application/octet-stream"); + } else if (sentry__string_eq(attachment->type, + SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY)) { + attachment->content_type = sentry__string_clone("application/json"); + } + } } void @@ -222,7 +233,9 @@ sentry__attachments_add(sentry_attachment_t **attachments_ptr, sentry__attachment_get_filename(attachment), size / (1024 * 1024)); } sentry_attachment_set_type(attachment, attachment_type); - sentry_attachment_set_content_type(attachment, content_type); + if (content_type || !attachment->content_type) { + sentry_attachment_set_content_type(attachment, content_type); + } sentry_attachment_t **next_ptr = attachments_ptr; diff --git a/tests/unit/test_attachments.c b/tests/unit/test_attachments.c index 16586e907e..e76e2af6a1 100644 --- a/tests/unit/test_attachments.c +++ b/tests/unit/test_attachments.c @@ -352,6 +352,21 @@ SENTRY_TEST(attachment_properties) SENTRY_TEST_OPTIONS_NEW(options); sentry_init(options); + sentry_attachment_t attachment = { 0 }; + sentry_attachment_set_type(&attachment, SENTRY_ATTACHMENT_TYPE_MINIDUMP); + TEST_CHECK_STRING_EQUAL( + attachment.content_type, "application/octet-stream"); + sentry_attachment_set_content_type(&attachment, "application/x-dmp"); + sentry_attachment_set_type( + &attachment, SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY); + TEST_CHECK_STRING_EQUAL(attachment.content_type, "application/x-dmp"); + sentry_attachment_set_content_type(&attachment, NULL); + sentry_attachment_set_type( + &attachment, SENTRY_ATTACHMENT_TYPE_VIEW_HIERARCHY); + TEST_CHECK_STRING_EQUAL(attachment.content_type, "application/json"); + sentry_free(attachment.type); + sentry_free(attachment.content_type); + sentry_path_t *path_txt = sentry__path_from_str(SENTRY_TEST_PATH_PREFIX ".a.txt"); sentry_path_t *path_html From 811474e88e1c812853db1944f4fd46d517c2fed5 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 12 May 2026 11:05:50 +0200 Subject: [PATCH 09/11] fix test leak --- tests/unit/test_attachments.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/test_attachments.c b/tests/unit/test_attachments.c index e76e2af6a1..30d5b8d90b 100644 --- a/tests/unit/test_attachments.c +++ b/tests/unit/test_attachments.c @@ -32,6 +32,7 @@ SENTRY_TEST(attachment_placeholder) TEST_CHECK(sentry__attachment_is_placeholder(&attachment, options)); sentry_free(attachment.type); + sentry_free(attachment.content_type); sentry_options_free(options); } From 1e6b9e1582267d44ada1a67dff1078e61be2c35a Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 12 May 2026 12:59:45 +0200 Subject: [PATCH 10/11] ref(attachments): Simplify attachment add helper Keep sentry__attachments_add focused on inserting already-configured attachments. Configure type and content type in the path helper, and preserve those fields when cloning attachments. Co-Authored-By: OpenAI Codex --- src/sentry_attachment.c | 34 +++++++++++++++++++++++----------- src/sentry_attachment.h | 3 +-- src/sentry_core.c | 3 +-- src/sentry_hint.c | 6 ++---- src/sentry_scope.c | 6 ++---- 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/sentry_attachment.c b/src/sentry_attachment.c index ed8c4e4a2b..57d11bb4bc 100644 --- a/src/sentry_attachment.c +++ b/src/sentry_attachment.c @@ -213,9 +213,8 @@ attachment_eq(const sentry_attachment_t *a, const sentry_attachment_t *b) } sentry_attachment_t * -sentry__attachments_add(sentry_attachment_t **attachments_ptr, - sentry_attachment_t *attachment, const char *attachment_type, - const char *content_type) +sentry__attachments_add( + sentry_attachment_t **attachments_ptr, sentry_attachment_t *attachment) { if (!attachment) { return NULL; @@ -232,10 +231,6 @@ sentry__attachments_add(sentry_attachment_t **attachments_ptr, SENTRY_INFOF("added large attachment \"%s\" (%zu MiB)", sentry__attachment_get_filename(attachment), size / (1024 * 1024)); } - sentry_attachment_set_type(attachment, attachment_type); - if (content_type || !attachment->content_type) { - sentry_attachment_set_content_type(attachment, content_type); - } sentry_attachment_t **next_ptr = attachments_ptr; @@ -257,8 +252,14 @@ sentry__attachments_add_path(sentry_attachment_t **attachments_ptr, sentry_path_t *path, const char *attachment_type, const char *content_type) { sentry_attachment_t *attachment = sentry__attachment_from_path(path); - return sentry__attachments_add( - attachments_ptr, attachment, attachment_type, content_type); + if (!attachment) { + return NULL; + } + sentry_attachment_set_type(attachment, attachment_type); + if (content_type || !attachment->content_type) { + sentry_attachment_set_content_type(attachment, content_type); + } + return sentry__attachments_add(attachments_ptr, attachment); } void @@ -314,6 +315,18 @@ attachment_clone(const sentry_attachment_t *attachment) } memcpy(clone->buf, attachment->buf, attachment->buf_len * sizeof(char)); } + if (attachment->type) { + clone->type = sentry__string_clone(attachment->type); + if (!clone->type) { + goto fail; + } + } + if (attachment->content_type) { + clone->content_type = sentry__string_clone(attachment->content_type); + if (!clone->content_type) { + goto fail; + } + } return clone; fail: @@ -326,7 +339,6 @@ sentry__attachments_extend( sentry_attachment_t **attachments_ptr, sentry_attachment_t *attachments) { for (sentry_attachment_t *it = attachments; it; it = it->next) { - sentry__attachments_add( - attachments_ptr, attachment_clone(it), it->type, it->content_type); + sentry__attachments_add(attachments_ptr, attachment_clone(it)); } } diff --git a/src/sentry_attachment.h b/src/sentry_attachment.h index 8a77eda994..0004164e76 100644 --- a/src/sentry_attachment.h +++ b/src/sentry_attachment.h @@ -79,8 +79,7 @@ void sentry__attachments_free(sentry_attachment_t *attachments); * Adds an attachment to the attachments list at `attachments_ptr`. */ sentry_attachment_t *sentry__attachments_add( - sentry_attachment_t **attachments_ptr, sentry_attachment_t *attachment, - const char *attachment_type, const char *content_type); + sentry_attachment_t **attachments_ptr, sentry_attachment_t *attachment); /** * Adds a file attachment to the attachments list at `attachments_ptr`. diff --git a/src/sentry_core.c b/src/sentry_core.c index d7923190da..5e24e19dd4 100644 --- a/src/sentry_core.c +++ b/src/sentry_core.c @@ -1842,8 +1842,7 @@ add_attachment(sentry_attachment_t *attachment) } } SENTRY_WITH_SCOPE_MUT (scope) { - attachment = sentry__attachments_add( - &scope->attachments, attachment, NULL, NULL); + attachment = sentry__attachments_add(&scope->attachments, attachment); } return attachment; } diff --git a/src/sentry_hint.c b/src/sentry_hint.c index a67b7dafd8..7b13e5218a 100644 --- a/src/sentry_hint.c +++ b/src/sentry_hint.c @@ -61,8 +61,7 @@ sentry_hint_attach_bytes_n(sentry_hint_t *hint, const char *buf, size_t buf_len, } return sentry__attachments_add(&hint->attachments, sentry__attachment_from_buffer( - buf, buf_len, sentry__path_from_str_n(filename, filename_len)), - NULL, NULL); + buf, buf_len, sentry__path_from_str_n(filename, filename_len))); } #ifdef SENTRY_PLATFORM_WINDOWS @@ -102,7 +101,6 @@ sentry_hint_attach_bytesw_n(sentry_hint_t *hint, const char *buf, } return sentry__attachments_add(&hint->attachments, sentry__attachment_from_buffer( - buf, buf_len, sentry__path_from_wstr_n(filename, filename_len)), - NULL, NULL); + buf, buf_len, sentry__path_from_wstr_n(filename, filename_len))); } #endif diff --git a/src/sentry_scope.c b/src/sentry_scope.c index 87728be4d3..6369d81a1a 100644 --- a/src/sentry_scope.c +++ b/src/sentry_scope.c @@ -646,8 +646,7 @@ sentry_scope_attach_bytes_n(sentry_scope_t *scope, const char *buf, { return sentry__attachments_add(&scope->attachments, sentry__attachment_from_buffer( - buf, buf_len, sentry__path_from_str_n(filename, filename_len)), - NULL, NULL); + buf, buf_len, sentry__path_from_str_n(filename, filename_len))); } #ifdef SENTRY_PLATFORM_WINDOWS @@ -681,8 +680,7 @@ sentry_scope_attach_bytesw_n(sentry_scope_t *scope, const char *buf, { return sentry__attachments_add(&scope->attachments, sentry__attachment_from_buffer( - buf, buf_len, sentry__path_from_wstr_n(filename, filename_len)), - NULL, NULL); + buf, buf_len, sentry__path_from_wstr_n(filename, filename_len))); } #endif From 6c3add4e5d9f50edf3deb283f0071ce8572a0e97 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 12 May 2026 13:31:07 +0200 Subject: [PATCH 11/11] add note --- include/sentry.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/sentry.h b/include/sentry.h index 1b288cc376..fe61ce5ffc 100644 --- a/include/sentry.h +++ b/include/sentry.h @@ -2775,6 +2775,8 @@ SENTRY_API sentry_attachment_t *sentry_scope_attach_bytesw_n( * Well-known attachment types are exposed as `SENTRY_ATTACHMENT_TYPE_*` * macros. Pass `NULL` or an empty string to clear the attachment type. * + * Also sets the content type for known attachment types unless explicitly set. + * * See: * https://develop.sentry.dev/sdk/telemetry/attachments/#attachment-types */