diff --git a/CHANGELOG.md b/CHANGELOG.md index b51fcab261..21acb0c907 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## 5.18.0 (2022-01-05) + +### Enhancements + +* Improve the memory use and performance overhead when handling the delivery response status codes + [#1558](https://github.com/bugsnag/bugsnag-android/pull/1558) + +* Harden ndk layer through use of const keyword + [#1566](https://github.com/bugsnag/bugsnag-android/pull/1566) + +### Bug fixes + +* Delete persisted NDK events earlier in delivery process + [#1562](https://github.com/bugsnag/bugsnag-android/pull/1562) + +* Add null checks for strlen() + [#1563](https://github.com/bugsnag/bugsnag-android/pull/1563) + +* Catch IOException when logging response status code + [#1567](https://github.com/bugsnag/bugsnag-android/pull/1567) + ## 5.17.0 (2021-12-08) ### Enhancements diff --git a/Gemfile b/Gemfile index ce9b553ab1..91a918faaf 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,7 @@ source "https://rubygems.org" #gem 'bugsnag-maze-runner', path: '../maze-runner' # Or a specific release: -gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v6.3.0' +gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v6.8.0' # Or follow master: #gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner' diff --git a/Gemfile.lock b/Gemfile.lock index be2062e81e..4c7cb46dea 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,20 +1,20 @@ GIT remote: https://github.com/bugsnag/maze-runner - revision: c9d5240f9ccbc5a3440e8aa72330f52cbdc6a082 - tag: v6.3.0 + revision: fe12189f83aad154f54221ee0fcd41b483d3c0d1 + tag: v6.8.0 specs: - bugsnag-maze-runner (6.3.0) + bugsnag-maze-runner (6.8.0) appium_lib (~> 11.2.0) + bugsnag (~> 6.24) cucumber (~> 7.1) cucumber-expressions (~> 6.0.0) curb (~> 0.9.6) - minitest (~> 5.0) optimist (~> 3.0.1) os (~> 1.0.0) rake (~> 12.3.3) rubyzip (~> 2.3.2) selenium-webdriver (~> 3.11) - test-unit (~> 3.3.0) + test-unit (~> 3.5.2) webrick (~> 1.7.0) GEM @@ -27,8 +27,11 @@ GEM appium_lib_core (4.7.1) faye-websocket (~> 0.11.0) selenium-webdriver (~> 3.14, >= 3.14.1) + bugsnag (6.24.1) + concurrent-ruby (~> 1.0) builder (3.2.4) childprocess (3.0.0) + concurrent-ruby (1.1.9) cucumber (7.1.0) builder (~> 3.2, >= 3.2.4) cucumber-core (~> 10.1, >= 10.1.0) @@ -46,7 +49,7 @@ GEM cucumber-gherkin (~> 22.0, >= 22.0.0) cucumber-messages (~> 17.1, >= 17.1.1) cucumber-tag-expressions (~> 4.0, >= 4.0.2) - cucumber-create-meta (6.0.2) + cucumber-create-meta (6.0.4) cucumber-messages (~> 17.1, >= 17.1.1) sys-uname (~> 1.2, >= 1.2.2) cucumber-cucumber-expressions (14.0.0) @@ -68,17 +71,16 @@ GEM eventmachine (>= 0.12.0) websocket-driver (>= 0.5.1) ffi (1.15.4) - license_finder (6.14.1) + license_finder (6.15.0) bundler rubyzip (>= 1, < 3) thor (~> 1.0.1) tomlrb (>= 1.3, < 2.1) with_env (= 1.1.0) xml-simple (~> 1.1.5) - mime-types (3.3.1) + mime-types (3.4.1) mime-types-data (~> 3.2015) - mime-types-data (3.2021.0901) - minitest (5.14.4) + mime-types-data (3.2021.1115) multi_test (0.1.2) nokogiri (1.12.5-x86_64-darwin) racc (~> 1.4) @@ -94,7 +96,7 @@ GEM rubyzip (>= 1.2.2) sys-uname (1.2.2) ffi (~> 1.1) - test-unit (3.3.9) + test-unit (3.5.3) power_assert thor (1.0.1) tomlrb (1.3.0) @@ -114,4 +116,4 @@ DEPENDENCIES license_finder (~> 6.13) BUNDLED WITH - 2.2.20 + 2.2.33 diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/DefaultDelivery.kt b/bugsnag-android-core/src/main/java/com/bugsnag/android/DefaultDelivery.kt index 5587ba7491..0ce2eec8c4 100644 --- a/bugsnag-android-core/src/main/java/com/bugsnag/android/DefaultDelivery.kt +++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/DefaultDelivery.kt @@ -105,32 +105,38 @@ internal class DefaultDelivery( } private fun logRequestInfo(code: Int, conn: HttpURLConnection, status: DeliveryStatus) { - logger.i( - "Request completed with code $code, " + - "message: ${conn.responseMessage}, " + - "headers: ${conn.headerFields}" - ) - - conn.inputStream.bufferedReader().use { - logger.d("Received request response: ${it.readText()}") + runCatching { + logger.i( + "Request completed with code $code, " + + "message: ${conn.responseMessage}, " + + "headers: ${conn.headerFields}" + ) + } + runCatching { + conn.inputStream.bufferedReader().use { + logger.d("Received request response: ${it.readText()}") + } } - if (status != DeliveryStatus.DELIVERED) { - conn.errorStream.bufferedReader().use { - logger.w("Request error details: ${it.readText()}") + runCatching { + if (status != DeliveryStatus.DELIVERED) { + conn.errorStream.bufferedReader().use { + logger.w("Request error details: ${it.readText()}") + } } } } internal fun getDeliveryStatus(responseCode: Int): DeliveryStatus { - val unrecoverableCodes = IntRange(HTTP_BAD_REQUEST, 499).filter { - it != HTTP_CLIENT_TIMEOUT && it != 429 - } - - return when (responseCode) { - in HTTP_OK..299 -> DeliveryStatus.DELIVERED - in unrecoverableCodes -> DeliveryStatus.FAILURE + return when { + responseCode in HTTP_OK..299 -> DeliveryStatus.DELIVERED + isUnrecoverableStatusCode(responseCode) -> DeliveryStatus.FAILURE else -> DeliveryStatus.UNDELIVERED } } + + private fun isUnrecoverableStatusCode(responseCode: Int) = + responseCode in HTTP_BAD_REQUEST..499 && // 400-499 are considered unrecoverable + responseCode != HTTP_CLIENT_TIMEOUT && // except for 408 + responseCode != 429 // and 429 } diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/Notifier.kt b/bugsnag-android-core/src/main/java/com/bugsnag/android/Notifier.kt index 254ac28a6d..c8b01a9f4b 100644 --- a/bugsnag-android-core/src/main/java/com/bugsnag/android/Notifier.kt +++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/Notifier.kt @@ -7,7 +7,7 @@ import java.io.IOException */ class Notifier @JvmOverloads constructor( var name: String = "Android Bugsnag Notifier", - var version: String = "5.17.0", + var version: String = "5.18.0", var url: String = "https://bugsnag.com" ) : JsonStream.Streamable { diff --git a/bugsnag-android-core/src/test/java/com/bugsnag/android/BugsnagTestUtils.java b/bugsnag-android-core/src/sharedTest/java/com/bugsnag/android/BugsnagTestUtils.java similarity index 78% rename from bugsnag-android-core/src/test/java/com/bugsnag/android/BugsnagTestUtils.java rename to bugsnag-android-core/src/sharedTest/java/com/bugsnag/android/BugsnagTestUtils.java index 8ae4882a08..361375f0e0 100644 --- a/bugsnag-android-core/src/test/java/com/bugsnag/android/BugsnagTestUtils.java +++ b/bugsnag-android-core/src/sharedTest/java/com/bugsnag/android/BugsnagTestUtils.java @@ -3,7 +3,7 @@ import com.bugsnag.android.internal.ImmutableConfig; import com.bugsnag.android.internal.ImmutableConfigKt; -import org.jetbrains.annotations.NotNull; +import androidx.annotation.NonNull; import java.io.File; import java.io.IOException; @@ -39,6 +39,19 @@ static ImmutableConfig generateImmutableConfig() { return convert(generateConfiguration()); } + static ImmutableConfig generateImmutableConfig(Configuration config) { + config.setDelivery(generateDelivery()); + config.setLogger(NoopLogger.INSTANCE); + config.setProjectPackages(Collections.singleton("com.example.foo")); + try { + File dir = Files.createTempDirectory("test").toFile(); + config.setPersistenceDirectory(dir); + } catch (IOException ignored) { + // ignore IO exception + } + return ImmutableConfigKt.convertToImmutableConfig(config); + } + static EventPayload generateEventPayload(ImmutableConfig config) { return new EventPayload(config.getApiKey(), generateEvent(), new Notifier(), config); } @@ -87,17 +100,17 @@ static DeviceWithState generateDeviceWithState() { public static Delivery generateDelivery() { return new Delivery() { - @NotNull + @NonNull @Override - public DeliveryStatus deliver(@NotNull EventPayload payload, - @NotNull DeliveryParams deliveryParams) { + public DeliveryStatus deliver(@NonNull EventPayload payload, + @NonNull DeliveryParams deliveryParams) { return DeliveryStatus.DELIVERED; } - @NotNull + @NonNull @Override - public DeliveryStatus deliver(@NotNull Session payload, - @NotNull DeliveryParams deliveryParams) { + public DeliveryStatus deliver(@NonNull Session payload, + @NonNull DeliveryParams deliveryParams) { return DeliveryStatus.DELIVERED; } }; @@ -111,4 +124,8 @@ public static AppWithState generateAppWithState() { public static App generateApp() { return new App(generateImmutableConfig(), null, null, null, null, null); } + + static MetadataState generateMetadataState() { + return new MetadataState(); + } } diff --git a/bugsnag-android-core/src/test/java/com/bugsnag/android/DeliveryTest.kt b/bugsnag-android-core/src/test/java/com/bugsnag/android/DeliveryTest.kt index 1dbc2a3fc8..243bc15a38 100644 --- a/bugsnag-android-core/src/test/java/com/bugsnag/android/DeliveryTest.kt +++ b/bugsnag-android-core/src/test/java/com/bugsnag/android/DeliveryTest.kt @@ -14,5 +14,10 @@ class DeliveryTest { assertEquals(DeliveryStatus.UNDELIVERED, delivery.getDeliveryStatus(408)) assertEquals(DeliveryStatus.UNDELIVERED, delivery.getDeliveryStatus(429)) assertEquals(DeliveryStatus.FAILURE, delivery.getDeliveryStatus(400)) + assertEquals(DeliveryStatus.FAILURE, delivery.getDeliveryStatus(401)) + assertEquals(DeliveryStatus.FAILURE, delivery.getDeliveryStatus(498)) + assertEquals(DeliveryStatus.FAILURE, delivery.getDeliveryStatus(499)) + assertEquals(DeliveryStatus.UNDELIVERED, delivery.getDeliveryStatus(408)) + assertEquals(DeliveryStatus.UNDELIVERED, delivery.getDeliveryStatus(429)) } } diff --git a/bugsnag-plugin-android-anr/src/test/java/com/bugsnag/android/BugsnagTestUtils.java b/bugsnag-plugin-android-anr/src/test/java/com/bugsnag/android/BugsnagTestUtils.java deleted file mode 100644 index 3d87326412..0000000000 --- a/bugsnag-plugin-android-anr/src/test/java/com/bugsnag/android/BugsnagTestUtils.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.bugsnag.android; - -import com.bugsnag.android.internal.ImmutableConfig; -import com.bugsnag.android.internal.ImmutableConfigKt; - -import org.jetbrains.annotations.NotNull; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; - -final class BugsnagTestUtils { - - private BugsnagTestUtils() { - } - - static Configuration generateConfiguration() { - Configuration configuration = new Configuration("5d1ec5bd39a74caa1267142706a7fb21"); - configuration.setDelivery(generateDelivery()); - configuration.setLogger(NoopLogger.INSTANCE); - try { - File dir = Files.createTempDirectory("test").toFile(); - configuration.setPersistenceDirectory(dir); - } catch (IOException ignored) { - // ignore IO exception - } - return configuration; - } - - static ImmutableConfig generateImmutableConfig() { - return convert(generateConfiguration()); - } - - static MetadataState generateMetadataState() { - return new MetadataState(); - } - - static ImmutableConfig convert(Configuration config) { - return ImmutableConfigKt.convertToImmutableConfig(config, null); - } - - public static Delivery generateDelivery() { - return new Delivery() { - @NotNull - @Override - public DeliveryStatus deliver(@NotNull EventPayload payload, - @NotNull DeliveryParams deliveryParams) { - return DeliveryStatus.DELIVERED; - } - - @NotNull - @Override - public DeliveryStatus deliver(@NotNull Session payload, - @NotNull DeliveryParams deliveryParams) { - return DeliveryStatus.DELIVERED; - } - }; - } -} diff --git a/bugsnag-plugin-android-ndk/src/main/jni/bugsnag.c b/bugsnag-plugin-android-ndk/src/main/jni/bugsnag.c index 71ec27bdc4..e46f88abdd 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/bugsnag.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/bugsnag.c @@ -89,7 +89,7 @@ void bsg_populate_notify_stacktrace(JNIEnv *env, bugsnag_stackframe *stacktrace, // populate method jstring method = NULL; - if (strlen(frame.method) == 0) { + if (bsg_strlen(frame.method) == 0) { char frame_address[32]; snprintf(frame_address, sizeof(frame_address), "0x%lx", (unsigned long)frame.frame_address); @@ -258,7 +258,7 @@ void bugsnag_set_user_env(JNIEnv *env, const char *id, const char *email, bsg_safe_delete_local_ref(env, interface_class); } -jfieldID bsg_parse_jcrumb_type(JNIEnv *env, bugsnag_breadcrumb_type type, +jfieldID bsg_parse_jcrumb_type(JNIEnv *env, const bugsnag_breadcrumb_type type, jclass type_class) { const char *type_sig = "Lcom/bugsnag/android/BreadcrumbType;"; if (type == BSG_CRUMB_USER) { @@ -282,7 +282,7 @@ jfieldID bsg_parse_jcrumb_type(JNIEnv *env, bugsnag_breadcrumb_type type, } void bugsnag_leave_breadcrumb_env(JNIEnv *env, const char *message, - bugsnag_breadcrumb_type type) { + const bugsnag_breadcrumb_type type) { jclass interface_class = NULL; jmethodID leave_breadcrumb_method = NULL; jclass type_class = NULL; diff --git a/bugsnag-plugin-android-ndk/src/main/jni/bugsnag_ndk.c b/bugsnag-plugin-android-ndk/src/main/jni/bugsnag_ndk.c index 8b1f5514f1..857df55d93 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/bugsnag_ndk.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/bugsnag_ndk.c @@ -171,8 +171,8 @@ JNIEXPORT void JNICALL Java_com_bugsnag_android_ndk_NativeBridge_install( if (last_run_info_path == NULL) { return; } - bsg_strncpy_safe(bugsnag_env->last_run_info_path, last_run_info_path, - sizeof(bugsnag_env->last_run_info_path)); + bsg_strncpy(bugsnag_env->last_run_info_path, last_run_info_path, + sizeof(bugsnag_env->last_run_info_path)); bsg_safe_release_string_utf_chars(env, _last_run_info_path, last_run_info_path); @@ -189,16 +189,16 @@ JNIEXPORT void JNICALL Java_com_bugsnag_android_ndk_NativeBridge_install( } // If set, save os build info to report info header - if (strlen(bugsnag_env->next_event.device.os_build) > 0) { - bsg_strncpy_safe(bugsnag_env->report_header.os_build, - bugsnag_env->next_event.device.os_build, - sizeof(bugsnag_env->report_header.os_build)); + if (bsg_strlen(bugsnag_env->next_event.device.os_build) > 0) { + bsg_strncpy(bugsnag_env->report_header.os_build, + bugsnag_env->next_event.device.os_build, + sizeof(bugsnag_env->report_header.os_build)); } const char *api_key = bsg_safe_get_string_utf_chars(env, _api_key); if (api_key != NULL) { - bsg_strncpy_safe(bugsnag_env->next_event.api_key, (char *)api_key, - sizeof(bugsnag_env->next_event.api_key)); + bsg_strncpy(bugsnag_env->next_event.api_key, (char *)api_key, + sizeof(bugsnag_env->next_event.api_key)); bsg_safe_release_string_utf_chars(env, _api_key, api_key); } @@ -224,6 +224,10 @@ Java_com_bugsnag_android_ndk_NativeBridge_deliverReportAtPath( } event = bsg_deserialize_event_from_file((char *)event_path); + // remove persisted NDK struct early - this reduces the chance of crash loops + // in delivery. + remove(event_path); + if (event != NULL) { payload = bsg_serialize_event_to_json_string(event); if (payload != NULL) { @@ -269,7 +273,6 @@ Java_com_bugsnag_android_ndk_NativeBridge_deliverReportAtPath( } else { BUGSNAG_LOG("Failed to read event at file: %s", event_path); } - remove(event_path); goto exit; exit: @@ -343,8 +346,8 @@ JNIEXPORT void JNICALL Java_com_bugsnag_android_ndk_NativeBridge_pausedSession( } bsg_request_env_write_lock(); bugsnag_event *event = &bsg_global_env->next_event; - memset(event->session_id, 0, strlen(event->session_id)); - memset(event->session_start, 0, strlen(event->session_start)); + memset(event->session_id, 0, bsg_strlen(event->session_id)); + memset(event->session_start, 0, bsg_strlen(event->session_start)); event->handled_events = 0; event->unhandled_events = 0; bsg_release_env_write_lock(); @@ -362,8 +365,8 @@ JNIEXPORT void JNICALL Java_com_bugsnag_android_ndk_NativeBridge_addBreadcrumb( if (name != NULL && type != NULL && timestamp != NULL) { bugsnag_breadcrumb *crumb = calloc(1, sizeof(bugsnag_breadcrumb)); - bsg_strncpy_safe(crumb->name, name, sizeof(crumb->name)); - bsg_strncpy_safe(crumb->timestamp, timestamp, sizeof(crumb->timestamp)); + bsg_strncpy(crumb->name, name, sizeof(crumb->name)); + bsg_strncpy(crumb->timestamp, timestamp, sizeof(crumb->timestamp)); if (strcmp(type, "user") == 0) { crumb->type = BSG_CRUMB_USER; } else if (strcmp(type, "error") == 0) { @@ -455,8 +458,8 @@ Java_com_bugsnag_android_ndk_NativeBridge_updateInForeground( bsg_request_env_write_lock(); bool was_in_foreground = bsg_global_env->next_event.app.in_foreground; bsg_global_env->next_event.app.in_foreground = (bool)new_value; - bsg_strncpy_safe(bsg_global_env->next_event.app.active_screen, activity, - sizeof(bsg_global_env->next_event.app.active_screen)); + bsg_strncpy(bsg_global_env->next_event.app.active_screen, activity, + sizeof(bsg_global_env->next_event.app.active_screen)); if ((bool)new_value) { if (!was_in_foreground) { time(&bsg_global_env->foreground_start_time); diff --git a/bugsnag-plugin-android-ndk/src/main/jni/event.c b/bugsnag-plugin-android-ndk/src/main/jni/event.c index 155948eabc..7864e245d1 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/event.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/event.c @@ -21,10 +21,10 @@ int bsg_allocate_metadata_index(bugsnag_metadata *metadata, const char *section, if (index < 0) { return index; } - bsg_strncpy_safe(metadata->values[index].section, section, - sizeof(metadata->values[index].section)); - bsg_strncpy_safe(metadata->values[index].name, name, - sizeof(metadata->values[index].name)); + bsg_strncpy(metadata->values[index].section, section, + sizeof(metadata->values[index].section)); + bsg_strncpy(metadata->values[index].name, name, + sizeof(metadata->values[index].name)); if (metadata->value_count < BUGSNAG_METADATA_MAX) { metadata->value_count = index + 1; } @@ -46,8 +46,8 @@ void bsg_add_metadata_value_str(bugsnag_metadata *metadata, const char *section, int index = bsg_allocate_metadata_index(metadata, section, name); if (index >= 0) { metadata->values[index].type = BSG_METADATA_CHAR_VALUE; - bsg_strncpy_safe(metadata->values[index].char_value, value, - sizeof(metadata->values[index].char_value)); + bsg_strncpy(metadata->values[index].char_value, value, + sizeof(metadata->values[index].char_value)); } } @@ -163,12 +163,12 @@ bool bugsnag_event_get_metadata_bool(void *event_ptr, const char *section, return false; } -void bugsnag_event_start_session(bugsnag_event *event, char *session_id, - char *started_at, int handled_count, - int unhandled_count) { - bsg_strncpy_safe(event->session_id, session_id, sizeof(event->session_id)); - bsg_strncpy_safe(event->session_start, started_at, - sizeof(event->session_start)); +void bugsnag_event_start_session(bugsnag_event *event, const char *session_id, + const char *started_at, + const int handled_count, + const int unhandled_count) { + bsg_strncpy(event->session_id, session_id, sizeof(event->session_id)); + bsg_strncpy(event->session_start, started_at, sizeof(event->session_start)); event->handled_events = handled_count; event->unhandled_events = unhandled_count; } @@ -180,7 +180,7 @@ char *bugsnag_event_get_api_key(void *event_ptr) { void bugsnag_event_set_api_key(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->api_key, value, sizeof(event->api_key)); + bsg_strncpy(event->api_key, value, sizeof(event->api_key)); } char *bugsnag_event_get_context(void *event_ptr) { @@ -190,15 +190,15 @@ char *bugsnag_event_get_context(void *event_ptr) { void bugsnag_event_set_context(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->context, value, sizeof(event->context)); + bsg_strncpy(event->context, value, sizeof(event->context)); } void bugsnag_event_set_user(void *event_ptr, const char *id, const char *email, const char *name) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->user.id, id, sizeof(event->user.id)); - bsg_strncpy_safe(event->user.email, email, sizeof(event->user.email)); - bsg_strncpy_safe(event->user.name, name, sizeof(event->user.name)); + bsg_strncpy(event->user.id, id, sizeof(event->user.id)); + bsg_strncpy(event->user.email, email, sizeof(event->user.email)); + bsg_strncpy(event->user.name, name, sizeof(event->user.name)); } void bugsnag_event_add_breadcrumb(bugsnag_event *event, @@ -220,8 +220,8 @@ void bugsnag_event_clear_breadcrumbs(bugsnag_event *event) { event->crumb_first_index = 0; } -bool bugsnag_event_has_session(bugsnag_event *event) { - return strlen(event->session_id) > 0; +bool bugsnag_event_has_session(const bugsnag_event *event) { + return bsg_strlen(event->session_id) > 0; } /* Accessors for event.app */ @@ -233,8 +233,7 @@ char *bugsnag_app_get_binary_arch(void *event_ptr) { void bugsnag_app_set_binary_arch(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->app.binary_arch, value, - sizeof(event->app.binary_arch)); + bsg_strncpy(event->app.binary_arch, value, sizeof(event->app.binary_arch)); } char *bugsnag_app_get_build_uuid(void *event_ptr) { @@ -244,7 +243,7 @@ char *bugsnag_app_get_build_uuid(void *event_ptr) { void bugsnag_app_set_build_uuid(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->app.build_uuid, value, sizeof(event->app.build_uuid)); + bsg_strncpy(event->app.build_uuid, value, sizeof(event->app.build_uuid)); } char *bugsnag_app_get_id(void *event_ptr) { @@ -254,7 +253,7 @@ char *bugsnag_app_get_id(void *event_ptr) { void bugsnag_app_set_id(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->app.id, value, sizeof(event->app.id)); + bsg_strncpy(event->app.id, value, sizeof(event->app.id)); } char *bugsnag_app_get_release_stage(void *event_ptr) { @@ -264,8 +263,8 @@ char *bugsnag_app_get_release_stage(void *event_ptr) { void bugsnag_app_set_release_stage(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->app.release_stage, value, - sizeof(event->app.release_stage)); + bsg_strncpy(event->app.release_stage, value, + sizeof(event->app.release_stage)); } char *bugsnag_app_get_type(void *event_ptr) { @@ -275,7 +274,7 @@ char *bugsnag_app_get_type(void *event_ptr) { void bugsnag_app_set_type(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->app.type, value, sizeof(event->app.type)); + bsg_strncpy(event->app.type, value, sizeof(event->app.type)); } char *bugsnag_app_get_version(void *event_ptr) { @@ -285,7 +284,7 @@ char *bugsnag_app_get_version(void *event_ptr) { void bugsnag_app_set_version(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->app.version, value, sizeof(event->app.version)); + bsg_strncpy(event->app.version, value, sizeof(event->app.version)); } int bugsnag_app_get_version_code(void *event_ptr) { @@ -357,7 +356,7 @@ char *bugsnag_device_get_id(void *event_ptr) { void bugsnag_device_set_id(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->device.id, value, sizeof(event->device.id)); + bsg_strncpy(event->device.id, value, sizeof(event->device.id)); } char *bugsnag_device_get_locale(void *event_ptr) { @@ -367,7 +366,7 @@ char *bugsnag_device_get_locale(void *event_ptr) { void bugsnag_device_set_locale(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->device.locale, value, sizeof(event->device.locale)); + bsg_strncpy(event->device.locale, value, sizeof(event->device.locale)); } char *bugsnag_device_get_manufacturer(void *event_ptr) { @@ -377,8 +376,8 @@ char *bugsnag_device_get_manufacturer(void *event_ptr) { void bugsnag_device_set_manufacturer(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->device.manufacturer, value, - sizeof(event->device.manufacturer)); + bsg_strncpy(event->device.manufacturer, value, + sizeof(event->device.manufacturer)); } char *bugsnag_device_get_model(void *event_ptr) { @@ -388,7 +387,7 @@ char *bugsnag_device_get_model(void *event_ptr) { void bugsnag_device_set_model(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->device.model, value, sizeof(event->device.model)); + bsg_strncpy(event->device.model, value, sizeof(event->device.model)); } char *bugsnag_device_get_os_version(void *event_ptr) { @@ -398,8 +397,8 @@ char *bugsnag_device_get_os_version(void *event_ptr) { void bugsnag_device_set_os_version(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->device.os_version, value, - sizeof(event->device.os_version)); + bsg_strncpy(event->device.os_version, value, + sizeof(event->device.os_version)); } long bugsnag_device_get_total_memory(void *event_ptr) { @@ -419,8 +418,8 @@ char *bugsnag_device_get_orientation(void *event_ptr) { void bugsnag_device_set_orientation(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->device.orientation, value, - sizeof(event->device.orientation)); + bsg_strncpy(event->device.orientation, value, + sizeof(event->device.orientation)); } time_t bugsnag_device_get_time(void *event_ptr) { @@ -440,7 +439,7 @@ char *bugsnag_device_get_os_name(void *event_ptr) { void bugsnag_device_set_os_name(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->device.os_name, value, sizeof(event->device.os_name)); + bsg_strncpy(event->device.os_name, value, sizeof(event->device.os_name)); } char *bugsnag_error_get_error_class(void *event_ptr) { @@ -450,8 +449,7 @@ char *bugsnag_error_get_error_class(void *event_ptr) { void bugsnag_error_set_error_class(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->error.errorClass, value, - sizeof(event->error.errorClass)); + bsg_strncpy(event->error.errorClass, value, sizeof(event->error.errorClass)); } char *bugsnag_error_get_error_message(void *event_ptr) { @@ -461,8 +459,8 @@ char *bugsnag_error_get_error_message(void *event_ptr) { void bugsnag_error_set_error_message(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->error.errorMessage, value, - sizeof(event->error.errorMessage)); + bsg_strncpy(event->error.errorMessage, value, + sizeof(event->error.errorMessage)); } char *bugsnag_error_get_error_type(void *event_ptr) { @@ -472,7 +470,7 @@ char *bugsnag_error_get_error_type(void *event_ptr) { void bugsnag_error_set_error_type(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->error.type, value, sizeof(event->error.type)); + bsg_strncpy(event->error.type, value, sizeof(event->error.type)); } bugsnag_severity bugsnag_event_get_severity(void *event_ptr) { @@ -507,7 +505,7 @@ char *bugsnag_event_get_grouping_hash(void *event_ptr) { void bugsnag_event_set_grouping_hash(void *event_ptr, const char *value) { bugsnag_event *event = (bugsnag_event *)event_ptr; - bsg_strncpy_safe(event->grouping_hash, value, sizeof(event->grouping_hash)); + bsg_strncpy(event->grouping_hash, value, sizeof(event->grouping_hash)); } int bugsnag_event_get_stacktrace_size(void *event_ptr) { diff --git a/bugsnag-plugin-android-ndk/src/main/jni/event.h b/bugsnag-plugin-android-ndk/src/main/jni/event.h index 2db2e7ba9a..c9286ca50e 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/event.h +++ b/bugsnag-plugin-android-ndk/src/main/jni/event.h @@ -229,10 +229,10 @@ typedef struct { void bugsnag_event_add_breadcrumb(bugsnag_event *event, bugsnag_breadcrumb *crumb); void bugsnag_event_clear_breadcrumbs(bugsnag_event *event); -void bugsnag_event_start_session(bugsnag_event *event, char *session_id, - char *started_at, int handled_count, +void bugsnag_event_start_session(bugsnag_event *event, const char *session_id, + const char *started_at, int handled_count, int unhandled_count); -bool bugsnag_event_has_session(bugsnag_event *event); +bool bugsnag_event_has_session(const bugsnag_event *event); void bsg_add_metadata_value_double(bugsnag_metadata *metadata, const char *section, const char *name, diff --git a/bugsnag-plugin-android-ndk/src/main/jni/handlers/signal_handler.c b/bugsnag-plugin-android-ndk/src/main/jni/handlers/signal_handler.c index c0b7d09b3e..5f53554c6a 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/handlers/signal_handler.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/handlers/signal_handler.c @@ -196,10 +196,12 @@ void bsg_handle_signal(int signum, siginfo_t *info, for (int i = 0; i < BSG_HANDLED_SIGNAL_COUNT; i++) { const int signal = bsg_native_signals[i]; if (signal == signum) { - bsg_strcpy(bsg_global_env->next_event.error.errorClass, - (char *)bsg_native_signal_names[i]); - bsg_strcpy(bsg_global_env->next_event.error.errorMessage, - (char *)bsg_native_signal_msgs[i]); + bsg_strncpy(bsg_global_env->next_event.error.errorClass, + (char *)bsg_native_signal_names[i], + sizeof(bsg_global_env->next_event.error.errorClass)); + bsg_strncpy(bsg_global_env->next_event.error.errorMessage, + (char *)bsg_native_signal_msgs[i], + sizeof(bsg_global_env->next_event.error.errorMessage)); break; } } diff --git a/bugsnag-plugin-android-ndk/src/main/jni/metadata.c b/bugsnag-plugin-android-ndk/src/main/jni/metadata.c index ac4b8da9c4..bf16caec4b 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/metadata.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/metadata.c @@ -263,7 +263,7 @@ void bsg_copy_map_value_string(JNIEnv *env, bsg_jni_cache *jni_cache, if (_value != NULL) { const char *value = bsg_safe_get_string_utf_chars(env, (jstring)_value); if (value != NULL) { - bsg_strncpy_safe(dest, value, len); + bsg_strncpy(dest, value, len); bsg_safe_release_string_utf_chars(env, _value, value); } } @@ -336,8 +336,8 @@ int bsg_populate_cpu_abi_from_map(JNIEnv *env, bsg_jni_cache *jni_cache, const char *abi = bsg_safe_get_string_utf_chars(env, jabi); if (abi != NULL) { - bsg_strncpy_safe(device->cpu_abi[i].value, abi, - sizeof(device->cpu_abi[i].value)); + bsg_strncpy(device->cpu_abi[i].value, abi, + sizeof(device->cpu_abi[i].value)); bsg_safe_release_string_utf_chars(env, jabi, abi); device->cpu_abi_count++; } @@ -465,7 +465,7 @@ void bsg_populate_app_data(JNIEnv *env, bsg_jni_cache *jni_cache, bsg_safe_delete_local_ref(env, data); } -char *bsg_os_name() { return "android"; } +const char *bsg_os_name() { return "android"; } void populate_device_metadata(JNIEnv *env, bsg_jni_cache *jni_cache, bugsnag_event *event, void *data) { @@ -531,7 +531,8 @@ void bsg_populate_device_data(JNIEnv *env, bsg_jni_cache *jni_cache, bsg_copy_map_value_string(env, jni_cache, data, "orientation", event->device.orientation, sizeof(event->device.orientation)); - bsg_strcpy(event->device.os_name, bsg_os_name()); + bsg_strncpy(event->device.os_name, bsg_os_name(), + sizeof(event->device.os_name)); bsg_copy_map_value_string(env, jni_cache, data, "osVersion", event->device.os_version, sizeof(event->device.os_version)); @@ -581,11 +582,11 @@ void bsg_populate_context(JNIEnv *env, bsg_jni_cache *jni_cache, if (_context != NULL) { const char *value = bsg_safe_get_string_utf_chars(env, (jstring)_context); if (value != NULL) { - bsg_strncpy_safe(event->context, value, sizeof(event->context) - 1); + bsg_strncpy(event->context, value, sizeof(event->context) - 1); bsg_safe_release_string_utf_chars(env, _context, value); } } else { - memset(&event->context, 0, strlen(event->context)); + memset(&event->context, 0, bsg_strlen(event->context)); } } diff --git a/bugsnag-plugin-android-ndk/src/main/jni/metadata.h b/bugsnag-plugin-android-ndk/src/main/jni/metadata.h index c94f1edcb6..de3e0e59d6 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/metadata.h +++ b/bugsnag-plugin-android-ndk/src/main/jni/metadata.h @@ -23,6 +23,6 @@ void bsg_populate_metadata(JNIEnv *env, bugsnag_metadata *dst, void bsg_populate_crumb_metadata(JNIEnv *env, bugsnag_breadcrumb *crumb, jobject metadata); -char *bsg_os_name(); +const char *bsg_os_name(); #endif diff --git a/bugsnag-plugin-android-ndk/src/main/jni/utils/serializer.c b/bugsnag-plugin-android-ndk/src/main/jni/utils/serializer.c index 9c41368735..048c4dc47e 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/utils/serializer.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/utils/serializer.c @@ -15,7 +15,8 @@ #ifdef __cplusplus extern "C" { #endif -bool bsg_event_write(bsg_report_header *header, bugsnag_event *event, int fd); +bool bsg_event_write(const bsg_report_header *header, + const bugsnag_event *event, const int fd); bugsnag_event *bsg_event_read(int fd); bsg_report_header *bsg_report_header_read(int fd); @@ -41,8 +42,8 @@ void migrate_breadcrumb_v2(bugsnag_report_v5 *report_v5, bugsnag_event *event); * Serializes the LastRunInfo to the file. This persists information about * why the current launch crashed, for use on future launch. */ -bool bsg_serialize_last_run_info_to_file(bsg_environment *env) { - char *path = env->last_run_info_path; +bool bsg_serialize_last_run_info_to_file(const bsg_environment *env) { + const char *path = env->last_run_info_path; int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd == -1) { return false; @@ -53,7 +54,7 @@ bool bsg_serialize_last_run_info_to_file(bsg_environment *env) { return len == size; } -bool bsg_serialize_event_to_file(bsg_environment *env) { +bool bsg_serialize_event_to_file(const bsg_environment *env) { int fd = open(env->next_event_path, O_WRONLY | O_CREAT, 0644); if (fd == -1) { return false; @@ -62,7 +63,7 @@ bool bsg_serialize_event_to_file(bsg_environment *env) { return bsg_event_write(&env->report_header, &env->next_event, fd); } -bugsnag_event *bsg_deserialize_event_from_file(char *filepath) { +bugsnag_event *bsg_deserialize_event_from_file(const char *filepath) { int fd = open(filepath, O_RDONLY); if (fd == -1) { return NULL; @@ -222,22 +223,21 @@ bugsnag_event *bsg_map_v5_to_report(bugsnag_report_v5 *report_v5) { event->notifier = report_v5->notifier; event->app = report_v5->app; event->device = report_v5->device; - bsg_strcpy(event->context, report_v5->context); + bsg_strncpy(event->context, report_v5->context, sizeof(event->context)); event->user = report_v5->user; event->error = report_v5->error; event->metadata = report_v5->metadata; event->severity = report_v5->severity; - bsg_strncpy_safe(event->session_id, report_v5->session_id, - sizeof(event->session_id)); - bsg_strncpy_safe(event->session_start, report_v5->session_start, - sizeof(event->session_id)); + bsg_strncpy(event->session_id, report_v5->session_id, + sizeof(event->session_id)); + bsg_strncpy(event->session_start, report_v5->session_start, + sizeof(event->session_id)); event->handled_events = report_v5->handled_events; event->unhandled_events = report_v5->unhandled_events; - bsg_strncpy_safe(event->grouping_hash, report_v5->grouping_hash, - sizeof(event->session_id)); + bsg_strncpy(event->grouping_hash, report_v5->grouping_hash, + sizeof(event->session_id)); event->unhandled = report_v5->unhandled; - bsg_strncpy_safe(event->api_key, report_v5->api_key, - sizeof(event->api_key)); + bsg_strncpy(event->api_key, report_v5->api_key, sizeof(event->api_key)); migrate_breadcrumb_v2(report_v5, event); free(report_v5); @@ -262,17 +262,16 @@ bugsnag_event *bsg_map_v4_to_report(bugsnag_report_v4 *report_v4) { memcpy(event->breadcrumbs, report_v4->breadcrumbs, sizeof(event->breadcrumbs)); event->severity = report_v4->severity; - bsg_strncpy_safe(event->session_id, report_v4->session_id, - sizeof(event->session_id)); - bsg_strncpy_safe(event->session_start, report_v4->session_start, - sizeof(event->session_id)); + bsg_strncpy(event->session_id, report_v4->session_id, + sizeof(event->session_id)); + bsg_strncpy(event->session_start, report_v4->session_start, + sizeof(event->session_id)); event->handled_events = report_v4->handled_events; event->unhandled_events = report_v4->unhandled_events; - bsg_strncpy_safe(event->grouping_hash, report_v4->grouping_hash, - sizeof(event->session_id)); + bsg_strncpy(event->grouping_hash, report_v4->grouping_hash, + sizeof(event->session_id)); event->unhandled = report_v4->unhandled; - bsg_strncpy_safe(event->api_key, report_v4->api_key, - sizeof(event->api_key)); + bsg_strncpy(event->api_key, report_v4->api_key, sizeof(event->api_key)); migrate_app_v2(report_v4, event); free(report_v4); } @@ -297,15 +296,18 @@ bugsnag_event *bsg_map_v3_to_report(bugsnag_report_v3 *report_v3) { memcpy(event->breadcrumbs, report_v3->breadcrumbs, sizeof(event->breadcrumbs)); event->severity = report_v3->severity; - strcpy(event->session_id, report_v3->session_id); - strcpy(event->session_start, report_v3->session_start); + bsg_strncpy(event->session_id, report_v3->session_id, + sizeof(event->session_id)); + bsg_strncpy(event->session_start, report_v3->session_start, + sizeof(event->session_start)); event->handled_events = report_v3->handled_events; event->unhandled_events = report_v3->unhandled_events; - strcpy(event->grouping_hash, report_v3->grouping_hash); + bsg_strncpy(event->grouping_hash, report_v3->grouping_hash, + sizeof(event->grouping_hash)); event->unhandled = report_v3->unhandled; // set a default value for the api key - strcpy(event->api_key, ""); + event->api_key[0] = 0; free(report_v3); } return bsg_map_v4_to_report(event); @@ -325,22 +327,30 @@ bugsnag_event *bsg_map_v2_to_report(bugsnag_report_v2 *report_v2) { event->user = report_v2->user; migrate_breadcrumb_v1(report_v2, event); - strcpy(event->context, report_v2->context); + bsg_strncpy(event->context, report_v2->context, sizeof(event->context)); event->severity = report_v2->severity; - strcpy(event->session_id, report_v2->session_id); - strcpy(event->session_start, report_v2->session_start); + bsg_strncpy(event->session_id, report_v2->session_id, + sizeof(event->session_id)); + bsg_strncpy(event->session_start, report_v2->session_start, + sizeof(event->session_start)); event->handled_events = report_v2->handled_events; event->unhandled_events = report_v2->unhandled_events; // migrate changed notifier fields - strcpy(event->notifier.version, report_v2->notifier.version); - strcpy(event->notifier.name, report_v2->notifier.name); - strcpy(event->notifier.url, report_v2->notifier.url); + bsg_strncpy(event->notifier.version, report_v2->notifier.version, + sizeof(event->notifier.version)); + bsg_strncpy(event->notifier.name, report_v2->notifier.name, + sizeof(event->notifier.name)); + bsg_strncpy(event->notifier.url, report_v2->notifier.url, + sizeof(event->notifier.url)); // migrate changed error fields - strcpy(event->error.errorClass, report_v2->exception.name); - strcpy(event->error.errorMessage, report_v2->exception.message); - strcpy(event->error.type, report_v2->exception.type); + bsg_strncpy(event->error.errorClass, report_v2->exception.name, + sizeof(event->error.errorClass)); + bsg_strncpy(event->error.errorMessage, report_v2->exception.message, + sizeof(event->error.errorMessage)); + bsg_strncpy(event->error.type, report_v2->exception.type, + sizeof(event->error.type)); event->error.frame_count = report_v2->exception.frame_count; size_t error_size = sizeof(bugsnag_stackframe) * BUGSNAG_FRAMES_MAX; memcpy(&event->error.stacktrace, report_v2->exception.stacktrace, @@ -368,7 +378,7 @@ int bsg_calculate_v1_crumb_index(int crumb_pos, int first_index) { } void bugsnag_report_v3_add_breadcrumb(bugsnag_report_v3 *event, - bugsnag_breadcrumb *crumb) { + const bugsnag_breadcrumb *crumb) { int crumb_index; if (event->crumb_count < V2_BUGSNAG_CRUMBS_MAX) { crumb_index = event->crumb_count; @@ -401,14 +411,14 @@ void migrate_breadcrumb_v1(bugsnag_report_v2 *report_v2, // copy old crumb fields to new new_crumb->type = old_crumb->type; - bsg_strncpy_safe(new_crumb->name, old_crumb->name, sizeof(new_crumb->name)); - bsg_strncpy_safe(new_crumb->timestamp, old_crumb->timestamp, - sizeof(new_crumb->timestamp)); + bsg_strncpy(new_crumb->name, old_crumb->name, sizeof(new_crumb->name)); + bsg_strncpy(new_crumb->timestamp, old_crumb->timestamp, + sizeof(new_crumb->timestamp)); for (int j = 0; j < 8; j++) { bsg_char_metadata_pair pair = old_crumb->metadata[j]; - if (strlen(pair.value) > 0 && strlen(pair.key) > 0) { + if (bsg_strlen(pair.value) > 0 && bsg_strlen(pair.key) > 0) { bsg_add_metadata_value_str(&new_crumb->metadata, "metaData", pair.key, pair.value); } @@ -421,13 +431,18 @@ void migrate_breadcrumb_v1(bugsnag_report_v2 *report_v2, } void migrate_app_v1(bugsnag_report_v2 *report_v2, bugsnag_report_v3 *event) { - bsg_strcpy(event->app.id, report_v2->app.id); - bsg_strcpy(event->app.release_stage, report_v2->app.release_stage); - bsg_strcpy(event->app.type, report_v2->app.type); - bsg_strcpy(event->app.version, report_v2->app.version); - bsg_strcpy(event->app.active_screen, report_v2->app.active_screen); - bsg_strcpy(event->app.build_uuid, report_v2->app.build_uuid); - bsg_strcpy(event->app.binary_arch, report_v2->app.binaryArch); + bsg_strncpy(event->app.id, report_v2->app.id, sizeof(event->app.id)); + bsg_strncpy(event->app.release_stage, report_v2->app.release_stage, + sizeof(event->app.release_stage)); + bsg_strncpy(event->app.type, report_v2->app.type, sizeof(event->app.type)); + bsg_strncpy(event->app.version, report_v2->app.version, + sizeof(event->app.version)); + bsg_strncpy(event->app.active_screen, report_v2->app.active_screen, + sizeof(event->app.active_screen)); + bsg_strncpy(event->app.build_uuid, report_v2->app.build_uuid, + sizeof(event->app.build_uuid)); + bsg_strncpy(event->app.binary_arch, report_v2->app.binaryArch, + sizeof(event->app.binary_arch)); event->app.version_code = report_v2->app.version_code; event->app.duration = report_v2->app.duration; event->app.duration_in_foreground = report_v2->app.duration_in_foreground; @@ -458,19 +473,18 @@ void migrate_breadcrumb_v2(bugsnag_report_v5 *report_v5, bugsnag_event *event) { } void migrate_app_v2(bugsnag_report_v4 *report_v4, bugsnag_event *event) { - bsg_strncpy_safe(event->app.id, report_v4->app.id, sizeof(event->app.id)); - bsg_strncpy_safe(event->app.release_stage, report_v4->app.release_stage, - sizeof(event->app.release_stage)); - bsg_strncpy_safe(event->app.type, report_v4->app.type, - sizeof(event->app.type)); - bsg_strncpy_safe(event->app.version, report_v4->app.version, - sizeof(event->app.version)); - bsg_strncpy_safe(event->app.active_screen, report_v4->app.active_screen, - sizeof(event->app.active_screen)); - bsg_strncpy_safe(event->app.build_uuid, report_v4->app.build_uuid, - sizeof(event->app.build_uuid)); - bsg_strncpy_safe(event->app.binary_arch, report_v4->app.binary_arch, - sizeof(event->app.binary_arch)); + bsg_strncpy(event->app.id, report_v4->app.id, sizeof(event->app.id)); + bsg_strncpy(event->app.release_stage, report_v4->app.release_stage, + sizeof(event->app.release_stage)); + bsg_strncpy(event->app.type, report_v4->app.type, sizeof(event->app.type)); + bsg_strncpy(event->app.version, report_v4->app.version, + sizeof(event->app.version)); + bsg_strncpy(event->app.active_screen, report_v4->app.active_screen, + sizeof(event->app.active_screen)); + bsg_strncpy(event->app.build_uuid, report_v4->app.build_uuid, + sizeof(event->app.build_uuid)); + bsg_strncpy(event->app.binary_arch, report_v4->app.binary_arch, + sizeof(event->app.binary_arch)); event->app.version_code = report_v4->app.version_code; event->app.duration = report_v4->app.duration; event->app.duration_in_foreground = report_v4->app.duration_in_foreground; @@ -484,8 +498,8 @@ void migrate_app_v2(bugsnag_report_v4 *report_v4, bugsnag_event *event) { } void migrate_device_v1(bugsnag_report_v2 *report_v2, bugsnag_report_v3 *event) { - bsg_strcpy(event->device.os_name, - bsg_os_name()); // os_name was not a field in v2 + bsg_strncpy(event->device.os_name, bsg_os_name(), + sizeof(event->device.os_name)); // os_name was not a field in v2 event->device.api_level = report_v2->device.api_level; event->device.cpu_abi_count = report_v2->device.cpu_abi_count; event->device.time = report_v2->device.time; @@ -495,18 +509,25 @@ void migrate_device_v1(bugsnag_report_v2 *report_v2, bugsnag_report_v3 *event) { for (int k = 0; k < report_v2->device.cpu_abi_count && k < sizeof(report_v2->device.cpu_abi); k++) { - bsg_strcpy(event->device.cpu_abi[k].value, - report_v2->device.cpu_abi[k].value); + bsg_strncpy(event->device.cpu_abi[k].value, + report_v2->device.cpu_abi[k].value, + sizeof(event->device.cpu_abi[k].value)); event->device.cpu_abi_count++; } - bsg_strcpy(event->device.orientation, report_v2->device.orientation); - bsg_strcpy(event->device.id, report_v2->device.id); - bsg_strcpy(event->device.locale, report_v2->device.locale); - bsg_strcpy(event->device.manufacturer, report_v2->device.manufacturer); - bsg_strcpy(event->device.model, report_v2->device.model); - bsg_strcpy(event->device.os_build, report_v2->device.os_build); - bsg_strcpy(event->device.os_version, report_v2->device.os_version); + bsg_strncpy(event->device.orientation, report_v2->device.orientation, + sizeof(event->device.orientation)); + bsg_strncpy(event->device.id, report_v2->device.id, sizeof(event->device.id)); + bsg_strncpy(event->device.locale, report_v2->device.locale, + sizeof(event->device.locale)); + bsg_strncpy(event->device.manufacturer, report_v2->device.manufacturer, + sizeof(event->device.manufacturer)); + bsg_strncpy(event->device.model, report_v2->device.model, + sizeof(event->device.model)); + bsg_strncpy(event->device.os_build, report_v2->device.os_build, + sizeof(event->device.os_build)); + bsg_strncpy(event->device.os_version, report_v2->device.os_version, + sizeof(event->device.os_version)); // migrate legacy fields to metadata bugsnag_event_add_metadata_bool(event, "device", "emulator", @@ -548,10 +569,13 @@ bugsnag_event *bsg_map_v1_to_report(bugsnag_report_v1 *report_v1) { sizeof(bugsnag_breadcrumb_v1) * V1_BUGSNAG_CRUMBS_MAX; memcpy(&event_v2->breadcrumbs, report_v1->breadcrumbs, breadcrumb_size); - strcpy(event_v2->context, report_v1->context); + bsg_strncpy(event_v2->context, report_v1->context, + sizeof(event_v2->context)); event_v2->severity = report_v1->severity; - strcpy(event_v2->session_id, report_v1->session_id); - strcpy(event_v2->session_start, report_v1->session_start); + bsg_strncpy(event_v2->session_id, report_v1->session_id, + sizeof(event_v2->session_id)); + bsg_strncpy(event_v2->session_start, report_v1->session_start, + sizeof(event_v2->session_start)); event_v2->handled_events = report_v1->handled_events; event_v2->unhandled_events = 1; @@ -571,13 +595,14 @@ bsg_report_header *bsg_report_header_read(int fd) { return header; } -bool bsg_report_header_write(bsg_report_header *header, int fd) { +bool bsg_report_header_write(const bsg_report_header *header, int fd) { ssize_t len = write(fd, header, sizeof(bsg_report_header)); return len == sizeof(bsg_report_header); } -bool bsg_event_write(bsg_report_header *header, bugsnag_event *event, int fd) { +bool bsg_event_write(const bsg_report_header *header, + const bugsnag_event *event, const int fd) { if (!bsg_report_header_write(header, fd)) { return false; } @@ -586,7 +611,7 @@ bool bsg_event_write(bsg_report_header *header, bugsnag_event *event, int fd) { return len == sizeof(bugsnag_event); } -const char *bsg_crumb_type_string(bugsnag_breadcrumb_type type) { +const char *bsg_crumb_type_string(const bugsnag_breadcrumb_type type) { switch (type) { case BSG_CRUMB_ERROR: return "error"; @@ -607,7 +632,7 @@ const char *bsg_crumb_type_string(bugsnag_breadcrumb_type type) { } } -const char *bsg_severity_string(bugsnag_severity type) { +const char *bsg_severity_string(const bugsnag_severity type) { switch (type) { case BSG_SEVERITY_INFO: return "info"; @@ -624,7 +649,7 @@ void bsg_serialize_context(const bugsnag_event *event, JSON_Object *event_obj) { void bsg_serialize_grouping_hash(const bugsnag_event *event, JSON_Object *event_obj) { - if (strlen(event->grouping_hash) > 0) { + if (bsg_strlen(event->grouping_hash) > 0) { json_object_set_string(event_obj, "groupingHash", event->grouping_hash); } } @@ -655,7 +680,7 @@ void bsg_serialize_app(const bsg_app_info app, JSON_Object *event_obj) { json_object_dotset_string(event_obj, "app.releaseStage", app.release_stage); json_object_dotset_number(event_obj, "app.versionCode", app.version_code); - if (strlen(app.build_uuid) > 0) { + if (bsg_strlen(app.build_uuid) > 0) { json_object_dotset_string(event_obj, "app.buildUUID", app.build_uuid); } json_object_dotset_string(event_obj, "app.binaryArch", app.binary_arch); @@ -764,15 +789,15 @@ void bsg_serialize_breadcrumb_metadata(const bugsnag_metadata metadata, } void bsg_serialize_user(const bugsnag_user user, JSON_Object *event_obj) { - if (strlen(user.name) > 0) + if (bsg_strlen(user.name) > 0) json_object_dotset_string(event_obj, "user.name", user.name); - if (strlen(user.email) > 0) + if (bsg_strlen(user.email) > 0) json_object_dotset_string(event_obj, "user.email", user.email); - if (strlen(user.id) > 0) + if (bsg_strlen(user.id) > 0) json_object_dotset_string(event_obj, "user.id", user.id); } -void bsg_serialize_session(bugsnag_event *event, JSON_Object *event_obj) { +void bsg_serialize_session(const bugsnag_event *event, JSON_Object *event_obj) { if (bugsnag_event_has_session(event)) { json_object_dotset_string(event_obj, "session.startedAt", event->session_start); @@ -784,7 +809,7 @@ void bsg_serialize_session(bugsnag_event *event, JSON_Object *event_obj) { } } -void bsg_serialize_error(bsg_error exc, JSON_Object *exception, +void bsg_serialize_error(const bsg_error exc, JSON_Object *exception, JSON_Array *stacktrace) { json_object_set_string(exception, "errorClass", exc.errorClass); json_object_set_string(exception, "message", exc.errorMessage); @@ -802,7 +827,7 @@ void bsg_serialize_error(bsg_error exc, JSON_Object *exception, } } -void bsg_serialize_stackframe(bugsnag_stackframe *stackframe, bool is_pc, +void bsg_serialize_stackframe(const bugsnag_stackframe *stackframe, bool is_pc, JSON_Array *stacktrace) { JSON_Value *frame_val = json_value_init_object(); JSON_Object *frame = json_value_get_object(frame_val); @@ -815,10 +840,10 @@ void bsg_serialize_stackframe(bugsnag_stackframe *stackframe, bool is_pc, // the field keeps payload sizes smaller. json_object_set_boolean(frame, "isPC", true); } - if (strlen((*stackframe).filename) > 0) { + if (bsg_strlen((*stackframe).filename) > 0) { json_object_set_string(frame, "file", (*stackframe).filename); } - if (strlen((*stackframe).method) == 0) { + if (bsg_strlen((*stackframe).method) == 0) { char *frame_address = calloc(1, sizeof(char) * 32); sprintf(frame_address, "0x%lx", (unsigned long)(*stackframe).frame_address); json_object_set_string(frame, "method", frame_address); @@ -930,7 +955,7 @@ void bsg_serialize_threads(const bugsnag_event *event, JSON_Array *threads) { } } -char *bsg_serialize_event_to_json_string(bugsnag_event *event) { +char *bsg_serialize_event_to_json_string(const bugsnag_event *event) { JSON_Value *event_val = json_value_init_object(); JSON_Object *event_obj = json_value_get_object(event_val); JSON_Value *crumbs_val = json_value_init_array(); diff --git a/bugsnag-plugin-android-ndk/src/main/jni/utils/serializer.h b/bugsnag-plugin-android-ndk/src/main/jni/utils/serializer.h index 185c86f079..aaa26d6f09 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/utils/serializer.h +++ b/bugsnag-plugin-android-ndk/src/main/jni/utils/serializer.h @@ -11,13 +11,14 @@ extern "C" { #endif -char *bsg_serialize_event_to_json_string(bugsnag_event *event); +char *bsg_serialize_event_to_json_string(const bugsnag_event *event); -bool bsg_serialize_event_to_file(bsg_environment *env) __asyncsafe; +bool bsg_serialize_event_to_file(const bsg_environment *env) __asyncsafe; -bool bsg_serialize_last_run_info_to_file(bsg_environment *env) __asyncsafe; +bool bsg_serialize_last_run_info_to_file(const bsg_environment *env) + __asyncsafe; -bugsnag_event *bsg_deserialize_event_from_file(char *filepath); +bugsnag_event *bsg_deserialize_event_from_file(const char *filepath); void bsg_serialize_context(const bugsnag_event *event, JSON_Object *event_obj); void bsg_serialize_severity_reason(const bugsnag_event *event, @@ -30,7 +31,7 @@ void bsg_serialize_device_metadata(const bsg_device_info device, void bsg_serialize_custom_metadata(const bugsnag_metadata metadata, JSON_Object *event_obj); void bsg_serialize_user(const bugsnag_user user, JSON_Object *event_obj); -void bsg_serialize_session(bugsnag_event *event, JSON_Object *event_obj); +void bsg_serialize_session(const bugsnag_event *event, JSON_Object *event_obj); /** * Append a JSON-serialized stackframe to an array * @@ -38,13 +39,12 @@ void bsg_serialize_session(bugsnag_event *event, JSON_Object *event_obj); * @param is_pc true if the current frame is the program counter * @param stacktrace the destination array */ -void bsg_serialize_stackframe(bugsnag_stackframe *stackframe, bool is_pc, +void bsg_serialize_stackframe(const bugsnag_stackframe *stackframe, bool is_pc, JSON_Array *stacktrace); -void bsg_serialize_error(bsg_error exc, JSON_Object *exception, +void bsg_serialize_error(const bsg_error exc, JSON_Object *exception, JSON_Array *stacktrace); void bsg_serialize_breadcrumbs(const bugsnag_event *event, JSON_Array *crumbs); void bsg_serialize_threads(const bugsnag_event *event, JSON_Array *threads); -char *bsg_serialize_event_to_json_string(bugsnag_event *event); int bsg_calculate_total_crumbs(int old_count); int bsg_calculate_v1_start_index(int old_count); diff --git a/bugsnag-plugin-android-ndk/src/main/jni/utils/stack_unwinder.c b/bugsnag-plugin-android-ndk/src/main/jni/utils/stack_unwinder.c index 00c0a2a8ab..1ee8e67b24 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/utils/stack_unwinder.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/utils/stack_unwinder.c @@ -51,10 +51,12 @@ void bsg_insert_fileinfo(ssize_t frame_count, stacktrace[i].line_number = stacktrace[i].frame_address - stacktrace[i].load_address; if (info.dli_fname != NULL) { - bsg_strcpy(stacktrace[i].filename, (char *)info.dli_fname); + bsg_strncpy(stacktrace[i].filename, (char *)info.dli_fname, + sizeof(stacktrace[i].filename)); } if (info.dli_sname != NULL) { - bsg_strcpy(stacktrace[i].method, (char *)info.dli_sname); + bsg_strncpy(stacktrace[i].method, (char *)info.dli_sname, + sizeof(stacktrace[i].method)); } } } diff --git a/bugsnag-plugin-android-ndk/src/main/jni/utils/stack_unwinder_libcorkscrew.c b/bugsnag-plugin-android-ndk/src/main/jni/utils/stack_unwinder_libcorkscrew.c index 01dbe2cf9b..ecf59c03d0 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/utils/stack_unwinder_libcorkscrew.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/utils/stack_unwinder_libcorkscrew.c @@ -111,7 +111,8 @@ bsg_unwind_stack_libcorkscrew(bugsnag_stackframe stacktrace[BUGSNAG_FRAMES_MAX], continue; // already seen this } if (backtrace_symbol.symbol_name != NULL) { - bsg_strcpy(stacktrace[frame_count].method, backtrace_symbol.symbol_name); + bsg_strncpy(stacktrace[frame_count].method, backtrace_symbol.symbol_name, + sizeof(stacktrace[frame_count].method)); } stacktrace[frame_count].frame_address = backtrace_frame.absolute_pc; diff --git a/bugsnag-plugin-android-ndk/src/main/jni/utils/string.c b/bugsnag-plugin-android-ndk/src/main/jni/utils/string.c index f096497885..9ede122ed3 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/utils/string.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/utils/string.c @@ -3,38 +3,20 @@ #include #include -void bsg_strcpy(char *dst, const char *src) { bsg_strncpy(dst, src, INT_MAX); } - -void bsg_strncpy(char *dst, const char *src, size_t len) { - int i = 0; - while (i <= len) { - char current = src[i]; - dst[i] = current; - if (current == '\0') { - break; - } - i++; - } -} +// Anything more than this and we shouldn't even be sending or using it. +const size_t STRING_MAX_LENGTH = 1024 * 1024 * 10; size_t bsg_strlen(const char *str) { - size_t i = 0; - while (true) { - char current = str[i]; - if (current == '\0') { - return i; - } else if (i == INT_MAX) { - return INT_MAX; - } - i++; + if (str == NULL) { + return 0; } + return strnlen(str, STRING_MAX_LENGTH); } -void bsg_strncpy_safe(char *dst, const char *src, int dst_size) { - if (dst_size == 0) +void bsg_strncpy(char *dst, const char *src, size_t dst_size) { + if (src == NULL || dst == NULL || dst_size == 0) { return; - dst[0] = '\0'; - if (src != NULL) { - strncat(dst, src, dst_size - 1); } + dst[0] = '\0'; + strncat(dst, src, dst_size - 1); } diff --git a/bugsnag-plugin-android-ndk/src/main/jni/utils/string.h b/bugsnag-plugin-android-ndk/src/main/jni/utils/string.h index 1879fdbfd7..3f65860094 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/utils/string.h +++ b/bugsnag-plugin-android-ndk/src/main/jni/utils/string.h @@ -1,7 +1,7 @@ #ifndef BUGSNAG_UTILS_STRING_H #define BUGSNAG_UTILS_STRING_H -#include "build.h" +#include "build.h" #include #ifdef __cplusplus @@ -9,12 +9,7 @@ extern "C" { #endif /** - * Copy the contents of src to dst where src is null-terminated - */ -void bsg_strcpy(char *dst, const char *src) __asyncsafe; - -/** - * Return the length of a string + * Return the length of a string, or 0 if the pointer is NULL. */ size_t bsg_strlen(const char *str) __asyncsafe; @@ -23,10 +18,6 @@ size_t bsg_strlen(const char *str) __asyncsafe; */ void bsg_strncpy(char *dst, const char *src, size_t len) __asyncsafe; -/** - * Copy a string from src to dst, null padding the rest - */ -void bsg_strncpy_safe(char *dst, const char *src, int dst_size); #ifdef __cplusplus } #endif diff --git a/bugsnag-plugin-android-ndk/src/main/jni/utils/threads.c b/bugsnag-plugin-android-ndk/src/main/jni/utils/threads.c index 1ca3afb3de..289477fddc 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/utils/threads.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/utils/threads.c @@ -42,11 +42,12 @@ static const char *const task_state_array[] = { "X dead", "Z zombie", "P parked", "I idle", }; -static void get_task_state_description(const char code, char *dest) { +static void get_task_state_description(const char code, char *dest, + size_t dest_size) { for (size_t index = 0; index < (sizeof(task_state_array) / sizeof(char *)); index++) { if (task_state_array[index][0] == code) { - bsg_strcpy(dest, &task_state_array[index][2]); + bsg_strncpy(dest, &task_state_array[index][2], dest_size); return; } } @@ -121,7 +122,7 @@ static bool parse_stat_content(bsg_thread *dest, char *content, size_t len) { } break; case PARSE_STATUS: - get_task_state_description(current, dest->state); + get_task_state_description(current, dest->state, sizeof(dest->state)); state = PARSE_DONE; break; case PARSE_DONE: diff --git a/bugsnag-plugin-android-ndk/src/test/cpp/test_bsg_event.c b/bugsnag-plugin-android-ndk/src/test/cpp/test_bsg_event.c index 776cd57a8c..52a02455f7 100644 --- a/bugsnag-plugin-android-ndk/src/test/cpp/test_bsg_event.c +++ b/bugsnag-plugin-android-ndk/src/test/cpp/test_bsg_event.c @@ -6,48 +6,48 @@ bugsnag_event *init_event() { bugsnag_event *event = calloc(1, sizeof(bugsnag_event)); - bsg_strncpy_safe(event->api_key, "5d1e5fbd39a74caa1200142706a90b20", sizeof(event->api_key)); - bsg_strncpy_safe(event->context, "Foo", sizeof(event->context)); - bsg_strncpy_safe(event->user.id, "123", sizeof(event->user.id)); - bsg_strncpy_safe(event->user.email, "jane@example.com", sizeof(event->user.email)); - bsg_strncpy_safe(event->user.name, "Jane Doe", sizeof(event->user.name)); + bsg_strncpy(event->api_key, "5d1e5fbd39a74caa1200142706a90b20", sizeof(event->api_key)); + bsg_strncpy(event->context, "Foo", sizeof(event->context)); + bsg_strncpy(event->user.id, "123", sizeof(event->user.id)); + bsg_strncpy(event->user.email, "jane@example.com", sizeof(event->user.email)); + bsg_strncpy(event->user.name, "Jane Doe", sizeof(event->user.name)); event->severity = BSG_SEVERITY_INFO; event->unhandled = true; - bsg_strncpy_safe(event->user.id, "123", sizeof(event->user.id)); - bsg_strncpy_safe(event->user.email, "bob@example.com", sizeof(event->user.email)); - bsg_strncpy_safe(event->user.name, "Bob Bobbiton", sizeof(event->user.name)); - - bsg_strncpy_safe(event->app.binary_arch, "x86", sizeof(event->app.binary_arch)); - bsg_strncpy_safe(event->app.build_uuid, "123", sizeof(event->app.build_uuid)); - bsg_strncpy_safe(event->app.id, "fa02", sizeof(event->app.id)); - bsg_strncpy_safe(event->app.release_stage, "dev", sizeof(event->app.release_stage)); - bsg_strncpy_safe(event->app.type, "C", sizeof(event->app.type)); - bsg_strncpy_safe(event->app.version, "1.0", sizeof(event->app.version)); + bsg_strncpy(event->user.id, "123", sizeof(event->user.id)); + bsg_strncpy(event->user.email, "bob@example.com", sizeof(event->user.email)); + bsg_strncpy(event->user.name, "Bob Bobbiton", sizeof(event->user.name)); + + bsg_strncpy(event->app.binary_arch, "x86", sizeof(event->app.binary_arch)); + bsg_strncpy(event->app.build_uuid, "123", sizeof(event->app.build_uuid)); + bsg_strncpy(event->app.id, "fa02", sizeof(event->app.id)); + bsg_strncpy(event->app.release_stage, "dev", sizeof(event->app.release_stage)); + bsg_strncpy(event->app.type, "C", sizeof(event->app.type)); + bsg_strncpy(event->app.version, "1.0", sizeof(event->app.version)); event->app.version_code = 55; event->app.duration = 9019; event->app.duration_in_foreground = 7017; event->app.in_foreground = true; event->app.is_launching = true; - bsg_strncpy_safe(event->grouping_hash, "Bar", sizeof(event->grouping_hash)); + bsg_strncpy(event->grouping_hash, "Bar", sizeof(event->grouping_hash)); event->device.jailbroken = true; event->device.total_memory = 1095092340; - bsg_strncpy_safe(event->device.id, "my-id-123", sizeof(event->device.id)); - bsg_strncpy_safe(event->device.locale, "en", sizeof(event->device.locale)); - bsg_strncpy_safe(event->device.os_name, "android", sizeof(event->device.os_name)); - bsg_strncpy_safe(event->device.manufacturer, "Google", sizeof(event->device.manufacturer)); - bsg_strncpy_safe(event->device.model, "Nexus", sizeof(event->device.model)); - bsg_strncpy_safe(event->device.os_version, "9.1", sizeof(event->device.os_version)); - bsg_strncpy_safe(event->device.orientation, "portrait", sizeof(event->device.orientation)); + bsg_strncpy(event->device.id, "my-id-123", sizeof(event->device.id)); + bsg_strncpy(event->device.locale, "en", sizeof(event->device.locale)); + bsg_strncpy(event->device.os_name, "android", sizeof(event->device.os_name)); + bsg_strncpy(event->device.manufacturer, "Google", sizeof(event->device.manufacturer)); + bsg_strncpy(event->device.model, "Nexus", sizeof(event->device.model)); + bsg_strncpy(event->device.os_version, "9.1", sizeof(event->device.os_version)); + bsg_strncpy(event->device.orientation, "portrait", sizeof(event->device.orientation)); event->device.time = 7609; - bsg_strncpy_safe(event->error.errorClass, "SIGSEGV", sizeof(event->error.errorClass)); - bsg_strncpy_safe(event->error.errorMessage, "Whoops!", sizeof(event->error.errorMessage)); - bsg_strncpy_safe(event->error.type, "C", sizeof(event->error.type)); + bsg_strncpy(event->error.errorClass, "SIGSEGV", sizeof(event->error.errorClass)); + bsg_strncpy(event->error.errorMessage, "Whoops!", sizeof(event->error.errorMessage)); + bsg_strncpy(event->error.type, "C", sizeof(event->error.type)); event->error.frame_count = 1; - bsg_strncpy_safe(event->error.stacktrace->method, "foo()", sizeof(event->error.stacktrace->method)); - bsg_strncpy_safe(event->error.stacktrace->filename, "Something.c", sizeof(event->error.stacktrace->filename)); + bsg_strncpy(event->error.stacktrace->method, "foo()", sizeof(event->error.stacktrace->method)); + bsg_strncpy(event->error.stacktrace->filename, "Something.c", sizeof(event->error.stacktrace->filename)); event->error.stacktrace->line_number = 58; return event; } @@ -376,7 +376,7 @@ TEST test_event_stacktrace(void) { ASSERT_EQ(58, frame->line_number); // modify and copy into a new array - bsg_strncpy_safe(frame->method, "bar()", sizeof(frame->method)); + bsg_strncpy(frame->method, "bar()", sizeof(frame->method)); bugsnag_stackframe *another_frame = bugsnag_event_get_stackframe(event, 0); ASSERT_EQ(frame, another_frame); diff --git a/bugsnag-plugin-android-ndk/src/test/cpp/test_serializer.c b/bugsnag-plugin-android-ndk/src/test/cpp/test_serializer.c index 003980bd3c..e67a8b3fd4 100644 --- a/bugsnag-plugin-android-ndk/src/test/cpp/test_serializer.c +++ b/bugsnag-plugin-android-ndk/src/test/cpp/test_serializer.c @@ -45,7 +45,7 @@ void loadAppMetadataTestCase(bugsnag_event *event) { void loadDeviceTestCase(bugsnag_event *event) { bsg_device_info *device = &event->device; device->api_level = 29; - bsg_strncpy_safe(device->cpu_abi[0].value, "x86", sizeof(device->cpu_abi[0].value)); + bsg_strncpy(device->cpu_abi[0].value, "x86", sizeof(device->cpu_abi[0].value)); device->cpu_abi_count = 1; strcpy(device->orientation, "portrait"); diff --git a/bugsnag-plugin-android-ndk/src/test/cpp/test_utils_string.c b/bugsnag-plugin-android-ndk/src/test/cpp/test_utils_string.c index ce41e67237..e8182c9ebf 100644 --- a/bugsnag-plugin-android-ndk/src/test/cpp/test_utils_string.c +++ b/bugsnag-plugin-android-ndk/src/test/cpp/test_utils_string.c @@ -4,8 +4,9 @@ TEST test_copy_empty_string(void) { char *src = ""; - char *dst = calloc(sizeof(char), 10); - bsg_strcpy(dst, src); + int dst_len = 10; + char *dst = calloc(sizeof(char), dst_len); + bsg_strncpy(dst, src, dst_len); ASSERT(dst[0] == '\0'); free(dst); PASS(); @@ -13,8 +14,9 @@ TEST test_copy_empty_string(void) { TEST test_copy_literal_string(void) { char *src = "C h a n g e"; - char *dst = calloc(sizeof(char), 10); - bsg_strcpy(dst, src); + int dst_len = 10; + char *dst = calloc(sizeof(char), dst_len); + bsg_strncpy(dst, src, dst_len); ASSERT(dst[0] == 'C'); ASSERT(dst[1] == ' '); ASSERT(dst[2] == 'h'); @@ -24,9 +26,7 @@ TEST test_copy_literal_string(void) { ASSERT(dst[6] == 'n'); ASSERT(dst[7] == ' '); ASSERT(dst[8] == 'g'); - ASSERT(dst[9] == ' '); - ASSERT(dst[10] == 'e'); - ASSERT(dst[11] == '\0'); + ASSERT(dst[9] == '\0'); free(dst); PASS(); } @@ -35,15 +35,22 @@ TEST length_literal_string(void) { ASSERT_EQ(11, bsg_strlen("C h a n g e")); PASS(); } + TEST length_empty_string(void) { ASSERT_EQ(0, bsg_strlen("")); PASS(); } +TEST length_null_string(void) { + ASSERT_EQ(0, bsg_strlen(NULL)); + PASS(); +} + SUITE(suite_string_utils) { RUN_TEST(test_copy_empty_string); RUN_TEST(test_copy_literal_string); RUN_TEST(length_empty_string); RUN_TEST(length_literal_string); + RUN_TEST(length_null_string); } diff --git a/bugsnag-plugin-android-okhttp/src/test/java/com/bugsnag/android/BugsnagTestUtils.java b/bugsnag-plugin-android-okhttp/src/test/java/com/bugsnag/android/BugsnagTestUtils.java deleted file mode 100644 index 085f4ea399..0000000000 --- a/bugsnag-plugin-android-okhttp/src/test/java/com/bugsnag/android/BugsnagTestUtils.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.bugsnag.android; - -import com.bugsnag.android.internal.ImmutableConfig; -import com.bugsnag.android.internal.ImmutableConfigKt; - -import androidx.annotation.NonNull; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.Collections; - -final class BugsnagTestUtils { - - static ImmutableConfig generateImmutableConfig() { - Configuration config = new Configuration("5d1ec5bd39a74caa1267142706a7fb21"); - return generateImmutableConfig(config); - } - - static ImmutableConfig generateImmutableConfig(Configuration config) { - config.setDelivery(generateDelivery()); - config.setLogger(NoopLogger.INSTANCE); - config.setProjectPackages(Collections.singleton("com.example.foo")); - try { - File dir = Files.createTempDirectory("test").toFile(); - config.setPersistenceDirectory(dir); - } catch (IOException ignored) { - // ignore IO exception - } - return ImmutableConfigKt.convertToImmutableConfig(config); - } - - public static Delivery generateDelivery() { - return new Delivery() { - @NonNull - @Override - public DeliveryStatus deliver(@NonNull EventPayload payload, - @NonNull DeliveryParams deliveryParams) { - return DeliveryStatus.DELIVERED; - } - - @NonNull - @Override - public DeliveryStatus deliver(@NonNull Session payload, - @NonNull DeliveryParams deliveryParams) { - return DeliveryStatus.DELIVERED; - } - }; - } -} diff --git a/buildSrc/src/main/kotlin/com/bugsnag/android/BugsnagBuildPlugin.kt b/buildSrc/src/main/kotlin/com/bugsnag/android/BugsnagBuildPlugin.kt index 779d102c0c..0eb3523e74 100644 --- a/buildSrc/src/main/kotlin/com/bugsnag/android/BugsnagBuildPlugin.kt +++ b/buildSrc/src/main/kotlin/com/bugsnag/android/BugsnagBuildPlugin.kt @@ -125,6 +125,12 @@ class BugsnagBuildPlugin : Plugin { isReturnDefaultValues = true } } + + sourceSets { + named("test") { + java.srcDir(SHARED_TEST_SRC_DIR) + } + } } /** @@ -181,4 +187,8 @@ class BugsnagBuildPlugin : Plugin { plugins.apply("org.jlleitschuh.gradle.ktlint") } } + + companion object { + private const val SHARED_TEST_SRC_DIR = "../bugsnag-android-core/src/sharedTest/java" + } } \ No newline at end of file diff --git a/features/steps/android_steps.rb b/features/steps/android_steps.rb index 97e3549622..c89ae15da2 100644 --- a/features/steps/android_steps.rb +++ b/features/steps/android_steps.rb @@ -17,7 +17,7 @@ $logger.info "System dialog cleared, reattempting wait_for_element" if clicked end - assert(present, "The element #{element_id} could not be found") + Maze.check.true(present, "The element #{element_id} could not be found") end When("I run {string}") do |event_type| @@ -78,7 +78,6 @@ } end - When("I configure the app to run in the {string} state") do |event_metadata| steps %Q{ Given any dialog is cleared and the element "scenario_metadata" is present @@ -89,14 +88,12 @@ Then("the exception reflects a signal was raised") do value = Maze::Helper.read_key_path(Maze::Server.errors.current[:body], "events.0.exceptions.0") error_class = value["errorClass"] - assert_block("The errorClass was not from a signal: #{error_class}") do - %w[SIGFPE SIGILL SIGSEGV SIGABRT SIGTRAP SIGBUS].include? error_class - end + Maze.check.include(%w[SIGFPE SIGILL SIGSEGV SIGABRT SIGTRAP SIGBUS], error_class) end Then("the exception {string} equals one of:") do |keypath, possible_values| value = Maze::Helper.read_key_path(Maze::Server.errors.current[:body], "events.0.exceptions.0.#{keypath}") - assert_includes(possible_values.raw.flatten, value) + Maze.check.include(possible_values.raw.flatten, value) end # Checks whether the first significant frames match several given frames @@ -121,8 +118,14 @@ test_frame = significant_frames[index] method_match_a = expected_frame[0] == test_frame[:method] method_match_b = expected_frame[1] == test_frame[:method] - assert(method_match_a || method_match_b, "'#{test_frame[:method]}' in frame #{test_frame[:index]} is not equal to '#{expected_frame[0]}' or '#{expected_frame[1]}'") - assert(test_frame[:file].end_with?(expected_frame[2]), "'#{test_frame[:file]}' in frame #{test_frame[:index]} does not end with '#{expected_frame[2]}'") + Maze.check.true( + method_match_a || method_match_b, + "'#{test_frame[:method]}' in frame #{test_frame[:index]} is not equal to '#{expected_frame[0]}' or '#{expected_frame[1]}'" + ) + Maze.check.true( + test_frame[:file].end_with?(expected_frame[2]), + "'#{test_frame[:file]}' in frame #{test_frame[:index]} does not end with '#{expected_frame[2]}'" + ) end end @@ -177,9 +180,9 @@ } stack = Maze::Helper.read_key_path(Maze::Server.errors.current[:body], "events.0.exceptions.0.stacktrace") stack.each_with_index do |frame, index| - assert_not_nil(frame['symbolAddress'], "The symbolAddress of frame #{index} is nil") - assert_not_nil(frame['frameAddress'], "The frameAddress of frame #{index} is nil") - assert_not_nil(frame['loadAddress'], "The loadAddress of frame #{index} is nil") + Maze.check.not_nil(frame['symbolAddress'], "The symbolAddress of frame #{index} is nil") + Maze.check.not_nil(frame['frameAddress'], "The frameAddress of frame #{index} is nil") + Maze.check.not_nil(frame['loadAddress'], "The loadAddress of frame #{index} is nil") end end @@ -196,8 +199,8 @@ step("the error payload field \"events.0.exceptions.0.stacktrace\" is a non-empty array") stack = Maze::Helper.read_key_path(Maze::Server.errors.current[:body], "events.0.exceptions.0.stacktrace") stack.each_with_index do |frame, index| - assert_not_nil(frame['method'], "The method of frame #{index} is nil") - assert_not_nil(frame['lineNumber'], "The lineNumber of frame #{index} is nil") + Maze.check.not_nil(frame['method'], "The method of frame #{index} is nil") + Maze.check.not_nil(frame['lineNumber'], "The lineNumber of frame #{index} is nil") end end @@ -220,11 +223,13 @@ Then("the exception stacktrace matches the thread stacktrace") do exc_trace = Maze::Helper.read_key_path(Maze::Server.errors.current[:body], "events.0.exceptions.0.stacktrace") thread_trace = Maze::Helper.read_key_path(Maze::Server.errors.current[:body], "events.0.threads.0.stacktrace") - assert_equal(exc_trace.length(), thread_trace.length(), "Exception and thread stacktraces are different lengths.") + Maze.check.equal(exc_trace.length(), + thread_trace.length(), + "Exception and thread stacktraces are different lengths.") thread_trace.each_with_index do |thread_frame, index| exc_frame = exc_trace[index] - assert_equal(exc_frame, thread_frame) + Maze.check.equal(exc_frame, thread_frame) end end @@ -246,28 +251,28 @@ def click_if_present(element) Then("the exception stacktrace matches the thread stacktrace") do exc_trace = read_key_path(Server.current_request[:body], "events.0.exceptions.0.stacktrace") thread_trace = read_key_path(Server.current_request[:body], "events.0.threads.0.stacktrace") - assert_equal(exc_trace.length(), thread_trace.length(), "Exception and thread stacktraces are different lengths.") + Maze.check.equal(exc_trace.length(), + thread_trace.length(), + "Exception and thread stacktraces are different lengths.") thread_trace.each_with_index do |thread_frame, index| exc_frame = exc_trace[index] - assert_equal(exc_frame, thread_frame) + Maze.check.equal(exc_frame, thread_frame) end end Then("the event binary arch field is valid") do arch = Maze::Helper.read_key_path(Maze::Server.errors.current[:body], "events.0.app.binaryArch") - assert_block "'#{arch}' is not a valid value for app.binaryArch" do - ["x86", "x86_64", "arm32", "arm64"].include? arch - end + Maze.check.include(%w[x86 x86_64 arm32 arm64], arch) end Then("the event stacktrace identifies the program counter") do trace = Maze::Helper.read_key_path(Maze::Server.errors.current[:body], "events.0.exceptions.0.stacktrace") trace.each_with_index do |frame, index| if index == 0 - assert_equal(frame["isPC"], true, "The first frame should be the program counter") + Maze.check.equal(frame["isPC"], true, "The first frame should be the program counter") else - assert_equal(frame["isPC"], nil, "The #{index} frame should not be the program counter") + Maze.check.equal(frame["isPC"], nil, "The #{index} frame should not be the program counter") end end end diff --git a/gradle.properties b/gradle.properties index 0b888924b3..a3eab41e82 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ org.gradle.jvmargs=-Xmx4096m # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects org.gradle.parallel=true -VERSION_NAME=5.17.0 +VERSION_NAME=5.18.0 GROUP=com.bugsnag POM_SCM_URL=https://github.com/bugsnag/bugsnag-android POM_SCM_CONNECTION=scm:git@github.com:bugsnag/bugsnag-android.git