| // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| /// This library gives some backstops to make sure that arbitrary string |
| /// exceptions generated by something that might be sent to the crash reporting |
| /// framework do not contain PII. The regular expressions here are |
| /// intentionally broad to make sure they get everything, possibly at the |
| /// expense of readability for the error message. Use care when reducing |
| /// their scope. |
| library; |
| |
| /// Contain an ordered list of regular expressions to be applied in sequence |
| /// with [applyTo] to a string, with any matches being substituted with |
| /// [substitution]. While a single regular expression could be |
| /// used in place of this class, this is intending to make the regular |
| /// expressions being applied more comprehensible to non-expert regular |
| /// expression authors and to make it very simple to add or remove individual |
| /// cases. |
| class _RegExpList { |
| /// This list should be usually be ordered from more specific to more general |
| /// cases in the event the regular expressions overlap. |
| final List<RegExp> _regExps; |
| final String substitution; |
| |
| _RegExpList(List<String> uncompiledRegexps, this.substitution) |
| : _regExps = uncompiledRegexps.map((s) => RegExp(s)).toList(); |
| |
| String applyTo(String input) => _regExps.fold( |
| input, (previousInput, r) => previousInput.replaceAll(r, substitution)); |
| } |
| |
| /// An ordered list of regular expressions to be substituted out and replaced |
| /// with a generic `<path>` string. To be applied in sequence. |
| /// The regular expressions here intentionally eat all characters after a |
| /// path is identified, with the hope of catching all potential complex |
| /// pathnames and assuming that most error messages will have any paths last. |
| /// For example: `throw Exception('error in: $fileName)` |
| final _piiPathRegexps = _RegExpList([ |
| // C:\Some\Things\Including Spaces\Too |
| r'\w:\\.*', |
| // \\Windows\Shares\Look\Like This |
| r'\\\\\S+\\.*', |
| // ..\StartsWithDots\Windows Path |
| r'[.]+\\+\S*\\.*', |
| // A\Relative\Windows Path |
| r'\b\S+\\.*', |
| // ../StartsWithDots/Unix path |
| r'[.]+/\S*/.*', |
| // /AUnix/path |
| r'/(\S|[.])+/.*', |
| // a/unix\ relative path/possibly-containing-strange-characters |
| r'\b(\S|[.])+/.*', |
| ], '<path>'); |
| |
| /// An ordered list of regular expressions to be substituted out and replaced |
| /// with a generic `<filename>` string. To be applied after |
| /// all paths from [_piiPathRegexps] are applied. This is somewhat less |
| /// all-encompassing than the path finder, above, just to try and grab things |
| /// that could be file names but without being quite so greedy or depending |
| /// on the presence of path separators. |
| final _piiFileRegexps = _RegExpList([ |
| // foo.dart |
| // something.exe |
| // code.js |
| r'\b\S+[.]\w{1,4}\b', |
| ], '<filename>'); |
| |
| /// Attempt to remove things that look like they could be PII from the |
| /// given [message]. |
| /// Returns the filtered string. |
| /// Not suitable for pre-scrubbed strings that intentionally include things |
| /// that look like filenames. |
| String filterPiiFromErrorMessage(String message) => [ |
| _piiPathRegexps, |
| _piiFileRegexps, |
| ].fold(message, (previousMessage, r) => r.applyTo(previousMessage)); |