libfec: correct verity table only if it's invalid

To increase reliability in the case where part of the partition is
corrupt and error correction might fail, attempt to use raw verity
table before the corrected one.

Bug: 32288104
Test: tested on angler
Change-Id: I201fdc6162c87b1808979486df5707d683a6d20c
(cherry picked from commit b5afa97f093e0b87614cb9e96a754f7c0e169c4f)
diff --git a/libfec/fec_verity.cpp b/libfec/fec_verity.cpp
index 5dea53d..3f636dd 100644
--- a/libfec/fec_verity.cpp
+++ b/libfec/fec_verity.cpp
@@ -312,6 +312,11 @@
 
     debug("valid");
 
+    if (v->hash) {
+        delete[] v->hash;
+        v->hash = NULL;
+    }
+
     v->hash = data_hashes.release();
     return 0;
 }
@@ -319,7 +324,7 @@
 /* reads, corrects and parses the verity table, validates parameters, and if
    `f->flags' does not have `FEC_VERITY_DISABLE' set, calls `verify_tree' to
    load and validate the hash tree */
-static int parse_table(fec_handle *f, uint64_t offset, uint32_t size)
+static int parse_table(fec_handle *f, uint64_t offset, uint32_t size, bool useecc)
 {
     check(f);
     check(size >= VERITY_MIN_TABLE_SIZE);
@@ -335,8 +340,13 @@
         return -1;
     }
 
-    if (fec_pread(f, table.get(), size, offset) != (ssize_t)size) {
-        error("failed to read verity table: %s", strerror(errno));
+    if (!useecc) {
+        if (!raw_pread(f, table.get(), size, offset)) {
+            error("failed to read verity table: %s", strerror(errno));
+            return -1;
+        }
+    } else if (fec_pread(f, table.get(), size, offset) != (ssize_t)size) {
+        error("failed to ecc read verity table: %s", strerror(errno));
         return -1;
     }
 
@@ -430,7 +440,18 @@
         check(v->data_blocks == v->hash_start / FEC_BLOCKSIZE);
     }
 
+    if (v->salt) {
+        delete[] v->salt;
+        v->salt = NULL;
+    }
+
     v->salt = salt.release();
+
+    if (v->table) {
+        delete[] v->table;
+        v->table = NULL;
+    }
+
     v->table = table.release();
 
     if (!(f->flags & FEC_VERITY_DISABLE)) {
@@ -589,7 +610,10 @@
 
     v->metadata_start = offset;
 
-    if (parse_table(f, offset + sizeof(v->header), v->header.length) == -1) {
+    if (parse_table(f, offset + sizeof(v->header), v->header.length,
+            false) == -1 &&
+        parse_table(f, offset + sizeof(v->header), v->header.length,
+            true)  == -1) {
         return -1;
     }