From 547db82dc925d3029a14677202e0b3ff973e43b5 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Thu, 10 Oct 2024 17:11:35 +0200 Subject: [PATCH] fix(app-start): accessing null json fields from `fetchNativeAppStart` (#2340) * update --- CHANGELOG.md | 1 + flutter/lib/src/native/native_app_start.dart | 28 ++++++++++++++++---- flutter/test/sentry_native_channel_test.dart | 15 +++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a156eb1f6..1933f70105 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - Rounding error used on frames.total and reject frame measurements if frames.total is less than frames.slow or frames.frozen ([#2308](https://github.com/getsentry/sentry-dart/pull/2308)) - iOS replay integration when only `onErrorSampleRate` is specified ([#2306](https://github.com/getsentry/sentry-dart/pull/2306)) - Fix TTID timing issue ([#2326](https://github.com/getsentry/sentry-dart/pull/2326)) +- Accessing invalid json fields from `fetchNativeAppStart` should return null ([#2340](https://github.com/getsentry/sentry-dart/pull/2340)) - Error when calling `SentryFlutter.reportFullyDisplayed()` twice ([#2339](https://github.com/getsentry/sentry-dart/pull/2339)) ### Deprecate diff --git a/flutter/lib/src/native/native_app_start.dart b/flutter/lib/src/native/native_app_start.dart index 7b6d53422f..16723400f9 100644 --- a/flutter/lib/src/native/native_app_start.dart +++ b/flutter/lib/src/native/native_app_start.dart @@ -1,4 +1,5 @@ import 'package:meta/meta.dart'; +import 'package:sentry/sentry.dart'; @internal class NativeAppStart { @@ -13,12 +14,29 @@ class NativeAppStart { bool isColdStart; Map nativeSpanTimes; - factory NativeAppStart.fromJson(Map json) { + static NativeAppStart? fromJson(Map json) { + final appStartTime = json['appStartTime']; + final pluginRegistrationTime = json['pluginRegistrationTime']; + final isColdStart = json['isColdStart']; + final nativeSpanTimes = json['nativeSpanTimes']; + + if (appStartTime is! double || + pluginRegistrationTime is! int || + isColdStart is! bool || + nativeSpanTimes is! Map) { + // ignore: invalid_use_of_internal_member + Sentry.currentHub.options.logger( + SentryLevel.warning, + 'Failed to parse json when capturing App Start metrics. App Start wont be reported.', + ); + return null; + } + return NativeAppStart( - appStartTime: json['appStartTime'] as double, - pluginRegistrationTime: json['pluginRegistrationTime'] as int, - isColdStart: json['isColdStart'] as bool, - nativeSpanTimes: json['nativeSpanTimes'] as Map, + appStartTime: appStartTime, + pluginRegistrationTime: pluginRegistrationTime, + isColdStart: isColdStart, + nativeSpanTimes: nativeSpanTimes, ); } } diff --git a/flutter/test/sentry_native_channel_test.dart b/flutter/test/sentry_native_channel_test.dart index fe5ed79dd6..0e52efbc84 100644 --- a/flutter/test/sentry_native_channel_test.dart +++ b/flutter/test/sentry_native_channel_test.dart @@ -52,6 +52,21 @@ void main() { expect(actual?.isColdStart, true); }); + test('invalid fetchNativeAppStart returns null', () async { + when(channel.invokeMethod('fetchNativeAppStart')) + .thenAnswer((_) async => { + 'pluginRegistrationTime': 'invalid', + 'appStartTime': 'invalid', + 'isColdStart': 'invalid', + // ignore: inference_failure_on_collection_literal + 'nativeSpanTimes': 'invalid', + }); + + final actual = await sut.fetchNativeAppStart(); + + expect(actual, isNull); + }); + test('beginNativeFrames', () async { when(channel.invokeMethod('beginNativeFrames')) .thenAnswer((realInvocation) async {});