0

PiiElider: apply to multi-line messages. Simplify how frames are identified.

Makes sanitizeStacktrace() assume that all stack frames have "\tat"
prefix.

Adds a URL exception for common storage paths (e.g. /data/data)

Bug: 1267770
Change-Id: I6f2e827acdee601b893ab1c843f6e3e8cea6f07f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5075138
Commit-Queue: Andrew Grieve <agrieve@chromium.org>
Reviewed-by: Mohamed Heikal <mheikal@chromium.org>
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/heads/main@{#1238115}
This commit is contained in:
Andrew Grieve
2023-12-15 17:16:30 +00:00
committed by Chromium LUCI CQ
parent cfd7fb1faf
commit 2e1badd3fb
2 changed files with 38 additions and 55 deletions
base/android
java
src
org
chromium
junit
src
org
chromium

@@ -75,23 +75,15 @@ public class PiiElider {
+ "*)?" // Rest of the URI path. + "*)?" // Rest of the URI path.
+ "(\\b|$)"); // Always end on a word boundary or end of string. + "(\\b|$)"); // Always end on a word boundary or end of string.
// Example variant info chromium-TrichromeChromeGoogle6432.aab private static final Pattern NOT_URLS_PATTERN =
private static final String CHROME_VARIANT_INFO = "chromium-[^\\.]+\\.aab";
private static final Pattern LIKELY_EXCEPTION_LOG =
Pattern.compile( Pattern.compile(
"\\sat\\s" ""
// These are all package prefixes of classes that are likely to
// exist on a stacktrace and are very unlikely to be a PII url.
+ "(org\\.chromium|com\\.google|java|android|com\\.android)\\.[^ ]+.|"
// if a line has what looks like line number info, it's probably an
// exception log.
+ "\\("
+ CHROME_VARIANT_INFO
+ "[^:]+:\\d+\\)|"
// When a class is not found it can fail to satisfy our isClass // When a class is not found it can fail to satisfy our isClass
// check but is still worth noting what it was. // check but is still worth noting what it was.
+ "Caused by: java\\.lang\\." + "^(?:Caused by: )?java\\.lang\\."
+ "(ClassNotFoundException|NoClassDefFoundError):"); + "(?:ClassNotFoundException|NoClassDefFoundError):|"
// Ensure common local paths are not interpreted as URLs.
+ "(?:[\"' ]/(?:apex|data|mnt|proc|sdcard|storage|system))/");
private static final String IP_ELISION = "1.2.3.4"; private static final String IP_ELISION = "1.2.3.4";
private static final String MAC_ELISION = "01:23:45:67:89:AB"; private static final String MAC_ELISION = "01:23:45:67:89:AB";
@@ -140,7 +132,7 @@ public class PiiElider {
*/ */
public static String elideUrl(String original) { public static String elideUrl(String original) {
// Url-matching is fussy. If something looks like an exception message, just return. // Url-matching is fussy. If something looks like an exception message, just return.
if (LIKELY_EXCEPTION_LOG.matcher(original).find()) return original; if (NOT_URLS_PATTERN.matcher(original).find()) return original;
StringBuilder buffer = new StringBuilder(original); StringBuilder buffer = new StringBuilder(original);
Matcher matcher = WEB_URL.matcher(buffer); Matcher matcher = WEB_URL.matcher(buffer);
int start = 0; int start = 0;
@@ -242,15 +234,19 @@ public class PiiElider {
if (TextUtils.isEmpty(stacktrace)) { if (TextUtils.isEmpty(stacktrace)) {
return ""; return "";
} }
String[] frames = stacktrace.split("\\n"); String[] lines = stacktrace.split("\\n");
// Sanitize first stacktrace line which contains the exception message. boolean foundAtLine = false;
frames[0] = elideUrl(frames[0]); for (int i = 0; i < lines.length; i++) {
for (int i = 1; i < frames.length; i++) { if (lines[i].startsWith("\tat ")) {
// Nested exceptions should also have their message sanitized. foundAtLine = true;
if (frames[i].startsWith("Caused by:")) { } else {
frames[i] = elideUrl(frames[i]); lines[i] = elideUrl(lines[i]);
} }
} }
return TextUtils.join("\n", frames); // Guard against non-properly formatted stacktraces to ensure checking for "\tat :" is
// sufficient (e.g.: no logging-related line prefixes).
// There can be no frames when a native thread creates an exception using JNI.
assert foundAtLine || lines.length == 1 : "Was not a stack trace: " + stacktrace;
return TextUtils.join("\n", lines);
} }
} }

@@ -72,22 +72,6 @@ public class PiiEliderTest {
assertEquals(original, PiiElider.elideUrl(original)); assertEquals(original, PiiElider.elideUrl(original));
} }
@Test
public void testElideUrl8() {
String original =
"exception at org.chromium.chrome.browser.compositor.scene_layer."
+ "TabListSceneLayer.nativeUpdateLayer(Native Method)";
assertEquals(original, PiiElider.elideUrl(original));
}
@Test
public void testElideUrl9() {
String original =
"I/dalvikvm( 5083): at org.chromium.chrome.browser.compositor."
+ "scene_layer.TabListSceneLayer.nativeUpdateLayer(Native Method)";
assertEquals(original, PiiElider.elideUrl(original));
}
@Test @Test
public void testElideUrl10() { public void testElideUrl10() {
String original = String original =
@@ -109,14 +93,6 @@ public class PiiEliderTest {
assertEquals(original, PiiElider.elideUrl(original)); assertEquals(original, PiiElider.elideUrl(original));
} }
@Test
public void testElideUrl12() {
String original =
"System.err: at kH.onAnimationEnd"
+ "(chromium-TrichromeChromeGoogle6432.aab-canary-530200034:42)";
assertEquals(original, PiiElider.elideUrl(original));
}
@Test @Test
public void testElideNonHttpUrl() { public void testElideNonHttpUrl() {
String original = "test some-other-scheme://address/01010?param=33&other_param=AAA !!!"; String original = "test some-other-scheme://address/01010?param=33&other_param=AAA !!!";
@@ -130,6 +106,15 @@ public class PiiEliderTest {
assertEquals(original, PiiElider.elideUrl(original)); assertEquals(original, PiiElider.elideUrl(original));
} }
@Test
public void testDontElideFilePaths() {
String original =
"""
dlopen failed: library "/data/app/com.chrome.dev-Lo4Mduh0dhPARVPBiAM_ag==/Chrome.apk!/\
lib/arm64-v8a/libelements.so" not found""";
assertEquals(original, PiiElider.elideUrl(original));
}
@Test @Test
public void testDontElideAndroidPermission() { public void testDontElideAndroidPermission() {
String original = String original =
@@ -170,23 +155,25 @@ public class PiiEliderTest {
public void testElideUrlInStacktrace() { public void testElideUrlInStacktrace() {
String original = String original =
"java.lang.RuntimeException: Outer Exception crbug.com/12345\n" "java.lang.RuntimeException: Outer Exception crbug.com/12345\n"
+ " at org.chromium.base.PiiElider.sanitizeStacktrace (PiiElider.java:120)\n" + "\tat org.chromium.base.PiiElider.sanitizeStacktrace (PiiElider.java:120)\n"
+ "Caused by: java.lang.NullPointerException: Inner Exception" + "Caused by: java.lang.NullPointerException: Inner Exception\n"
+ " shorturl.com/bxyj5"; + " shorturl.com/bxyj5";
String expected = String expected =
"java.lang.RuntimeException: Outer Exception HTTP://WEBADDRESS.ELIDED\n" "java.lang.RuntimeException: Outer Exception HTTP://WEBADDRESS.ELIDED\n"
+ " at org.chromium.base.PiiElider.sanitizeStacktrace (PiiElider.java:120)\n" + "\tat org.chromium.base.PiiElider.sanitizeStacktrace (PiiElider.java:120)\n"
+ "Caused by: java.lang.NullPointerException: Inner Exception " + "Caused by: java.lang.NullPointerException: Inner Exception\n"
+ "HTTP://WEBADDRESS.ELIDED"; + " HTTP://WEBADDRESS.ELIDED";
assertEquals(expected, PiiElider.sanitizeStacktrace(original)); assertEquals(expected, PiiElider.sanitizeStacktrace(original));
} }
@Test @Test
public void testDoesNotElideMethodNameInStacktrace() { public void testDoesNotElideMethodNameInStacktrace() {
String original = String original =
"java.lang.NullPointerException: Attempt to invoke virtual method 'int" """
+ " org.robolectric.internal.AndroidSandbox.getBackStackEntryCount()' on a null" java.lang.NullPointerException: Attempt to invoke virtual method 'int \
+ " object reference"; org.robolectric.internal.AndroidSandbox.getBackStackEntryCount()' on a null \
object reference
\tat ...""";
assertEquals(original, PiiElider.sanitizeStacktrace(original)); assertEquals(original, PiiElider.sanitizeStacktrace(original));
} }
} }