diff --git a/CHANGELOG.md b/CHANGELOG.md index c44d7645e4..ddc6f8c42b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Fix: Mark `Sentry.currentHub` as deprecated (#406) * Fix: Use name from pubspec.yaml for release if package id is not available (#411) * Feat: `SentryHttpClient` tracks the duration which a request takes and logs failed requests (#414) +* Fix: Trim `\u0000` from Windows package info (#420) # 5.0.0 diff --git a/flutter/lib/src/default_integrations.dart b/flutter/lib/src/default_integrations.dart index 62256ee945..93bee046e8 100644 --- a/flutter/lib/src/default_integrations.dart +++ b/flutter/lib/src/default_integrations.dart @@ -366,19 +366,31 @@ class LoadReleaseIntegration extends Integration { try { if (options.release == null || options.dist == null) { final packageInfo = await _packageLoader(); - var name = packageInfo.packageName; + var name = _cleanString(packageInfo.packageName); if (name.isEmpty) { // Not all platforms have a packageName. // If no packageName is available, use the appName instead. - name = _cleanAppName(packageInfo.appName); + name = _cleanString(packageInfo.appName); + } + + final version = _cleanString(packageInfo.version); + final buildNumber = _cleanString(packageInfo.buildNumber); + + var release = name; + if (version.isNotEmpty) { + release = '$release@$version'; + } + // At least windows sometimes does not have a buildNumber + if (buildNumber.isNotEmpty) { + release = '$release+$buildNumber'; } - final release = - '$name@${packageInfo.version}+${packageInfo.buildNumber}'; options.logger(SentryLevel.debug, 'release: $release'); options.release = options.release ?? release; - options.dist = options.dist ?? packageInfo.buildNumber; + if (buildNumber.isNotEmpty) { + options.dist = options.dist ?? buildNumber; + } } } catch (error) { options.logger( @@ -388,15 +400,21 @@ class LoadReleaseIntegration extends Integration { options.sdk.addIntegration('loadReleaseIntegration'); } - String _cleanAppName(String appName) { + /// This method cleans the given string from characters which should not be + /// used. + /// For example https://docs.sentry.io/platforms/flutter/configuration/releases/#bind-the-version + /// imposes some requirements. Also Windows uses some characters which + /// should not be used. + String _cleanString(String appName) { // Replace disallowed chars with an underscore '_' - // https://docs.sentry.io/platforms/flutter/configuration/releases/#bind-the-version return appName .replaceAll('/', '_') .replaceAll('\\', '_') .replaceAll('\t', '_') .replaceAll('\r\n', '_') .replaceAll('\r', '_') - .replaceAll('\n', '_'); + .replaceAll('\n', '_') + // replace Unicode NULL character with an empty string + .replaceAll('\u{0000}', ''); } } diff --git a/flutter/test/default_integrations_test.dart b/flutter/test/default_integrations_test.dart index 35b2b45ab2..4e5866c10d 100644 --- a/flutter/test/default_integrations_test.dart +++ b/flutter/test/default_integrations_test.dart @@ -267,7 +267,8 @@ void main() { expect(fixture.options.dist, '789'); }); - test('release name does not contain ivalid chars', () async { + test('release name does not contain invalid chars defined by Sentry', + () async { final loader = () { return Future.value(PackageInfo( appName: '\\/sentry\tflutter \r\nfoo\nbar\r', @@ -283,6 +284,69 @@ void main() { expect(fixture.options.release, '__sentry_flutter _foo_bar_@1.2.3+789'); expect(fixture.options.dist, '789'); }); + + /// See the following issues: + /// - https://github.com/getsentry/sentry-dart/issues/410 + /// - https://github.com/fluttercommunity/plus_plugins/issues/182 + test('does not send Unicode NULL \\u0000 character in app name or version', + () async { + final loader = () { + return Future.value(PackageInfo( + // As per + // https://api.dart.dev/stable/2.12.4/dart-core/String-class.html + // this is how \u0000 is added to a string in dart + appName: 'sentry_flutter_example\u{0000}', + packageName: '', + version: '1.0.0\u{0000}', + buildNumber: '', + )); + }; + await fixture + .getIntegration(loader: loader) + .call(MockHub(), fixture.options); + + expect(fixture.options.release, 'sentry_flutter_example@1.0.0'); + }); + + /// See the following issues: + /// - https://github.com/getsentry/sentry-dart/issues/410 + /// - https://github.com/fluttercommunity/plus_plugins/issues/182 + test( + 'does not send Unicode NULL \\u0000 character in package name or build number', + () async { + final loader = () { + return Future.value(PackageInfo( + // As per + // https://api.dart.dev/stable/2.12.4/dart-core/String-class.html + // this is how \u0000 is added to a string in dart + appName: '', + packageName: 'sentry_flutter_example\u{0000}', + version: '', + buildNumber: '123\u{0000}', + )); + }; + await fixture + .getIntegration(loader: loader) + .call(MockHub(), fixture.options); + + expect(fixture.options.release, 'sentry_flutter_example+123'); + }); + + test('dist is null if build number is an empty string', () async { + final loader = () { + return Future.value(PackageInfo( + appName: 'sentry_flutter_example', + packageName: 'a.b.c', + version: '1.0.0', + buildNumber: '', + )); + }; + await fixture + .getIntegration(loader: loader) + .call(MockHub(), fixture.options); + + expect(fixture.options.dist, isNull); + }); }); }