Snap for 7316203 from 270b9ca26af8c8f8c76c5c3ee0b2e93181f3cd0e to rvc-platform-release

Change-Id: Id6d3acdd230c803fc38cdd94dbd0f3d87e23c60b
diff --git a/common/util/src/com/android/compatibility/common/util/CrashUtils.java b/common/util/src/com/android/compatibility/common/util/CrashUtils.java
index b397794..04051b9 100644
--- a/common/util/src/com/android/compatibility/common/util/CrashUtils.java
+++ b/common/util/src/com/android/compatibility/common/util/CrashUtils.java
@@ -24,6 +24,8 @@
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import java.math.BigInteger;
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -45,6 +47,7 @@
     public static final Pattern sNewTestPattern =
             Pattern.compile(NEW_TEST_ALERT + "(\\w+?)\\(.*?\\)");
     public static final String SIGNAL = "signal";
+    public static final String ABORT_MESSAGE = "abortmessage";
     public static final String NAME = "name";
     public static final String PROCESS = "process";
     public static final String PID = "pid";
@@ -61,9 +64,9 @@
             Pattern.compile(
                     "\\w+? \\d+? \\((.*?)\\), code -*?\\d+? \\(.*?\\), fault addr "
                             + "(?:0x(\\p{XDigit}+)|-+)");
-    // Matches the abort message line if it contains CHECK_
-    private static Pattern sAbortMessageCheckPattern =
-            Pattern.compile("(?i)Abort message.*?CHECK_");
+    // Matches the abort message line
+    private static Pattern sAbortMessagePattern =
+            Pattern.compile("(?i)Abort message: (.*)");
 
     public static final String SIGSEGV = "SIGSEGV";
     public static final String SIGBUS = "SIGBUS";
@@ -126,6 +129,24 @@
                     continue;
                 }
 
+                if (crash.has(ABORT_MESSAGE)) {
+                    String crashAbortMessage = crash.getString(ABORT_MESSAGE);
+                    if (!config.abortMessageIncludes.isEmpty()) {
+                        if (!config.abortMessageIncludes.stream()
+                                .filter(p -> p.matcher(crashAbortMessage).find())
+                                .findFirst()
+                                .isPresent()) {
+                            continue;
+                        }
+                    }
+                    if (config.abortMessageExcludes.stream()
+                            .filter(p -> p.matcher(crashAbortMessage).find())
+                            .findFirst()
+                            .isPresent()) {
+                        continue;
+                    }
+                }
+
                 // if check specified, reject crash if address is unlikely to be security-related
                 if (config.checkMinAddress) {
                     BigInteger faultAddress = getBigInteger(crash, FAULT_ADDRESS);
@@ -163,6 +184,7 @@
             String name = null;
             String process = null;
             String signal = null;
+            String abortMessage = null;
 
             Matcher pidtidNameMatcher = sPidtidNamePattern.matcher(crashStr);
             if (pidtidNameMatcher.find()) {
@@ -186,19 +208,24 @@
                     } catch (NumberFormatException e) {}
                 }
             }
-            if (!sAbortMessageCheckPattern.matcher(crashStr).find()) {
-                try {
-                    JSONObject crash = new JSONObject();
-                    crash.put(PID, pid);
-                    crash.put(TID, tid);
-                    crash.put(NAME, name);
-                    crash.put(PROCESS, process);
-                    crash.put(FAULT_ADDRESS,
-                            faultAddress == null ? null : faultAddress.toString(16));
-                    crash.put(SIGNAL, signal);
-                    crashes.put(crash);
-                } catch (JSONException e) {}
+
+            Matcher abortMessageMatcher = sAbortMessagePattern.matcher(crashStr);
+            if (abortMessageMatcher.find()) {
+                abortMessage = abortMessageMatcher.group(1);
             }
+
+            try {
+                JSONObject crash = new JSONObject();
+                crash.put(PID, pid);
+                crash.put(TID, tid);
+                crash.put(NAME, name);
+                crash.put(PROCESS, process);
+                crash.put(FAULT_ADDRESS,
+                        faultAddress == null ? null : faultAddress.toString(16));
+                crash.put(SIGNAL, signal);
+                crash.put(ABORT_MESSAGE, abortMessage);
+                crashes.put(crash);
+            } catch (JSONException e) {}
         }
         return crashes;
     }
@@ -208,11 +235,15 @@
         private BigInteger minCrashAddress;
         private List<String> signals;
         private List<Pattern> processPatterns;
+        private List<Pattern> abortMessageIncludes;
+        private List<Pattern> abortMessageExcludes;
 
         public Config() {
             checkMinAddress = true;
             minCrashAddress = MIN_CRASH_ADDR;
             setSignals(SIGSEGV, SIGBUS);
+            abortMessageIncludes = new ArrayList<>();
+            setAbortMessageExcludes("CHECK_", "CANNOT LINK EXECUTABLE");
             processPatterns = new ArrayList();
         }
 
@@ -236,12 +267,50 @@
             return this;
         }
 
+        public Config setAbortMessageIncludes(String... abortMessages) {
+            this.abortMessageIncludes = new ArrayList<>(toPatterns(abortMessages));
+            return this;
+        }
+
+        public Config setAbortMessageIncludes(Pattern... abortMessages) {
+            this.abortMessageIncludes = new ArrayList<>(Arrays.asList(abortMessages));
+            return this;
+        }
+
+        public Config appendAbortMessageIncludes(String... abortMessages) {
+            this.abortMessageIncludes.addAll(toPatterns(abortMessages));
+            return this;
+        }
+
+        public Config appendAbortMessageIncludes(Pattern... abortMessages) {
+            Collections.addAll(this.abortMessageIncludes, abortMessages);
+            return this;
+        }
+
+        public Config setAbortMessageExcludes(String... abortMessages) {
+            this.abortMessageExcludes = new ArrayList<>(toPatterns(abortMessages));
+            return this;
+        }
+
+        public Config setAbortMessageExcludes(Pattern... abortMessages) {
+            this.abortMessageExcludes = new ArrayList<>(Arrays.asList(abortMessages));
+            return this;
+        }
+
+        public Config appendAbortMessageExcludes(String... abortMessages) {
+            this.abortMessageExcludes.addAll(toPatterns(abortMessages));
+            return this;
+        }
+
+        public Config appendAbortMessageExcludes(Pattern... abortMessages) {
+            Collections.addAll(this.abortMessageExcludes, abortMessages);
+            return this;
+        }
+
+
         public Config setProcessPatterns(String... processPatternStrings) {
-            Pattern[] processPatterns = new Pattern[processPatternStrings.length];
-            for (int i = 0; i < processPatternStrings.length; i++) {
-                processPatterns[i] = Pattern.compile(processPatternStrings[i]);
-            }
-            return setProcessPatterns(processPatterns);
+            this.processPatterns = new ArrayList<>(toPatterns(processPatternStrings));
+            return this;
         }
 
         public Config setProcessPatterns(Pattern... processPatterns) {
@@ -253,9 +322,18 @@
             return Collections.unmodifiableList(processPatterns);
         }
 
+        public Config appendProcessPatterns(String... processPatternStrings) {
+            this.processPatterns.addAll(toPatterns(processPatternStrings));
+            return this;
+        }
+
         public Config appendProcessPatterns(Pattern... processPatterns) {
             Collections.addAll(this.processPatterns, processPatterns);
             return this;
         }
     }
+
+    private static List<Pattern> toPatterns(String... patternStrings) {
+        return Stream.of(patternStrings).map(Pattern::compile).collect(Collectors.toList());
+    }
 }
diff --git a/common/util/src/com/android/compatibility/common/util/GasTest.java b/common/util/src/com/android/compatibility/common/util/GasTest.java
index 4c3b555..1300383 100644
--- a/common/util/src/com/android/compatibility/common/util/GasTest.java
+++ b/common/util/src/com/android/compatibility/common/util/GasTest.java
@@ -25,5 +25,23 @@
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD, ElementType.TYPE})
 public @interface GasTest {
+    // The GAS requirement ID the GasTest applies to.
+    // Example: @GasTest(requirement = "G-0-000")
     String requirement();
+
+    // The minimum GAS software requirement version the GasTest applies to.
+    // Example: @GasTest(requirement = "G-0-000", minSoftwareVersion = 0.1)
+    double minSoftwareVersion() default 0;
+
+    // The maximum GAS software requirement version the GasTest applies to.
+    // Example: @GasTest(requirement = "G-0-000", maxSoftwareVersion = 0.1)
+    double maxSoftwareVersion() default 0;
+
+    // The minimum GAS hardware requirement version the GasTest applies to.
+    // Example: @GasTest(requirement = "G-0-000", minHardwareVersion = 0.1)
+    double minHardwareVersion() default 0;
+
+    // The maximum GAS hardware requirement version the GasTest applies to.
+    // Example: @GasTest(requirement = "G-0-000", maxHardwareVersion = 0.1)
+    double maxHardwareVersion() default 0;
 }
diff --git a/common/util/tests/assets/logcat.txt b/common/util/tests/assets/logcat.txt
index b9d10d0..ffb28ad 100644
--- a/common/util/tests/assets/logcat.txt
+++ b/common/util/tests/assets/logcat.txt
@@ -229,7 +229,6 @@
 05-04 21:59:23.743  9363  9363 F DEBUG   :     #22 pc 00000000001a1f94  /system/lib64/hw/bluetooth.default.so (run_thread(void*)+184)
 05-04 21:59:23.743  9363  9363 F DEBUG   :     #23 pc 0000000000067d80  /system/lib64/libc.so (__pthread_start(void*)+36)
 05-04 21:59:23.743  9363  9363 F DEBUG   :     #24 pc 000000000001ec18  /system/lib64/libc.so (__start_thread+68)
-1-25 19:47:35.417  8080 11665 F MPEG4Extractor: frameworks/av/media/libstagefright/MPEG4Extractor.cpp:6853 CHECK_EQ( (unsigned)ptr[0],1u) failed: 129 vs. 1
 11-25 19:47:35.417  8080 11665 F libc    : Fatal signal 6 (SIGABRT), code -6 in tid 11665 (generic)
 11-25 19:47:35.487   940   940 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
 11-25 19:47:35.487   940   940 F DEBUG   : Build fingerprint: 'samsung/hero2qltezc/hero2qltechn:6.0.1/MMB29M/G9350ZCU2APJ6:user/release-keys'
diff --git a/common/util/tests/src/com/android/compatibility/common/util/CrashUtilsTest.java b/common/util/tests/src/com/android/compatibility/common/util/CrashUtilsTest.java
index 071733f..2d80509 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/CrashUtilsTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/CrashUtilsTest.java
@@ -54,29 +54,40 @@
     public void testGetAllCrashes() throws Exception {
         JSONArray expectedResults = new JSONArray();
         expectedResults.put(createCrashJson(
-                11071, 11189, "AudioOut_D", "/system/bin/audioserver", "e9380000", "SIGSEGV"));
+                11071, 11189, "AudioOut_D", "/system/bin/audioserver", "e9380000", "SIGSEGV", null));
         expectedResults.put(createCrashJson(
-                12736, 12761, "Binder:12736_2", "/system/bin/audioserver", "0", "SIGSEGV"));
+                12736, 12761, "Binder:12736_2", "/system/bin/audioserver", "0", "SIGSEGV", null));
         expectedResults.put(createCrashJson(
-                26201, 26227, "Binder:26201_3", "/system/bin/audioserver", "0", "SIGSEGV"));
+                26201, 26227, "Binder:26201_3", "/system/bin/audioserver", "0", "SIGSEGV", null));
         expectedResults.put(createCrashJson(
-                26246, 26282, "Binder:26246_5", "/system/bin/audioserver", "0", "SIGSEGV"));
+                26246, 26282, "Binder:26246_5", "/system/bin/audioserver", "0", "SIGSEGV", null));
         expectedResults.put(createCrashJson(
-                245, 245, "installd", "/system/bin/installd", null, "SIGABRT"));
+                245, 245, "installd", "/system/bin/installd", null, "SIGABRT",
+                "'utils.cpp:67] Check failed: is_valid_package_name(package_name) == 0 '"));
         expectedResults.put(createCrashJson(
-                6371, 8072, "media.codec", "omx@1.0-service", "ed000000", "SIGSEGV"));
+                6371, 8072, "media.codec", "omx@1.0-service", "ed000000", "SIGSEGV", null));
         expectedResults.put(createCrashJson(
-                8373, 8414, "loo", "com.android.bluetooth", null, "SIGABRT"));
+                8373, 8414, "loo", "com.android.bluetooth", null, "SIGABRT",
+                "'[FATAL:allocation_tracker.cc(143)] Check failed: map_entry != allocations.end()."));
         expectedResults.put(createCrashJson(
-                11071, 11189, "synthetic_thread", "synthetic_process_0", "e9380000", "SIGSEGV"));
+                8080, 11665, "generic", "/system/bin/mediaserver", null, "SIGABRT",
+                "'frameworks/av/media/libstagefright/MPEG4Extractor.cpp:6853 CHECK_EQ( (unsigned)ptr[0],1u) failed: 129 vs. 1'"));
         expectedResults.put(createCrashJson(
-                12736, 12761, "synthetic_thread", "synthetic_process_1", "0", "SIGSEGV"));
+                11071, 11189, "synthetic_thread", "synthetic_process_0", "e9380000", "SIGSEGV", null));
+        expectedResults.put(createCrashJson(
+                12736, 12761, "synthetic_thread", "synthetic_process_1", "0", "SIGSEGV", null));
 
-        Assert.assertEquals(mCrashes.toString(), expectedResults.toString());
+        Assert.assertEquals(expectedResults.toString() + "\n" +  mCrashes.toString() + "\n", expectedResults.toString(), mCrashes.toString());
     }
 
     public JSONObject createCrashJson(
-            int pid, int tid, String name, String process, String faultaddress, String signal) {
+                int pid,
+                int tid,
+                String name,
+                String process,
+                String faultaddress,
+                String signal,
+                String abortMessage) {
         JSONObject json = new JSONObject();
         try {
             json.put(CrashUtils.PID, pid);
@@ -85,6 +96,7 @@
             json.put(CrashUtils.PROCESS, process);
             json.put(CrashUtils.FAULT_ADDRESS, faultaddress);
             json.put(CrashUtils.SIGNAL, signal);
+            json.put(CrashUtils.ABORT_MESSAGE, abortMessage);
         } catch (JSONException e) {}
         return json;
     }
@@ -143,9 +155,65 @@
     @Test
     public void testNullFaultAddress() throws Exception {
         JSONArray crashes = new JSONArray();
-        crashes.put(createCrashJson(8373, 8414, "loo", "com.android.bluetooth", null, "SIGSEGV"));
+        crashes.put(createCrashJson(8373, 8414, "loo", "com.android.bluetooth", null, "SIGSEGV", ""));
         Assert.assertTrue(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
                 .checkMinAddress(true)
                 .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
     }
+
+    @Test
+    public void testAbortMessageInclude() throws Exception {
+        JSONArray crashes = new JSONArray();
+        crashes.put(createCrashJson(8373, 8414, "loo", "com.android.bluetooth", null, "SIGABRT",
+              "'[FATAL:allocation_tracker.cc(143)] Check failed: map_entry != allocations.end()."));
+        Assert.assertTrue(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .appendSignals(CrashUtils.SIGABRT)
+                .appendAbortMessageIncludes("Check failed:")
+                .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
+
+        Assert.assertFalse(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .appendSignals(CrashUtils.SIGABRT)
+                .appendAbortMessageIncludes("include not matches")
+                .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
+    }
+
+    @Test
+    public void testAbortMessageExclude() throws Exception {
+        JSONArray crashes = new JSONArray();
+        crashes.put(createCrashJson(8373, 8414, "loo", "com.android.bluetooth", null, "SIGABRT",
+              "'[FATAL:allocation_tracker.cc(143)] Check failed: map_entry != allocations.end()."));
+        Assert.assertFalse(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .appendSignals(CrashUtils.SIGABRT)
+                .appendAbortMessageExcludes("Check failed:")
+                .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
+
+        Assert.assertTrue(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .appendSignals(CrashUtils.SIGABRT)
+                .appendAbortMessageExcludes("exclude not matches")
+                .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
+    }
+
+    @Test
+    public void testAbortMessageExcludeCannotLink() throws Exception {
+        JSONArray crashes = new JSONArray();
+        crashes.put(createCrashJson(
+                18959, 18959, "CVE-2020-0073", "/data/local/tmp/CVE-2020-0073", null, "SIGABRT",
+                "'CANNOT LINK EXECUTABLE \"/data/local/tmp/CVE-2020-0073\": library "
+                + "\"libnfc-nci.so\" (\"(default)\", \"/data/local/tmp/CVE-2020-0073\", \"\") "
+                + "not found'"));
+        Assert.assertFalse(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .appendSignals(CrashUtils.SIGABRT)
+                .setProcessPatterns(Pattern.compile("CVE-2020-0073"))));
+
+        crashes.put(createCrashJson(
+                5105, 5105, "CVE-2015-6616-2", "/data/local/tmp/CVE-2015-6616-2", null, "SIGABRT",
+                "'CANNOT LINK EXECUTABLE \"/data/local/tmp/CVE-2015-6616-2\": "
+                + "cannot locate symbol \""
+                + "_ZN7android14MediaExtractor17CreateFromServiceERKNS_2spINS_10DataSourceEEEPKc"
+                + "\" referenced by \"/data/local/tmp/CVE-2015-6616-2\"...'"));
+        Assert.assertFalse(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
+                .appendSignals(CrashUtils.SIGABRT)
+                .setProcessPatterns(Pattern.compile("CVE-2015-6616-2"))));
+
+    }
 }