[NAN] Add (T)LV validation testing

Test for validity of a (T)LV. Used in construction of publish and
subscribe configuration (both Tx and Rx filters).

Bug: 30007730
Change-Id: Ibf2179121d45c582bb054c06ec2a765ed0927040
(cherry picked from commit c13b9f6b7d132e06e09b8604b095bdf59ec42307)
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.java b/wifi/java/android/net/wifi/nan/PublishConfig.java
index 96d257c..a4969bd 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.java
+++ b/wifi/java/android/net/wifi/nan/PublishConfig.java
@@ -300,10 +300,18 @@
             throw new IllegalArgumentException(
                     "Non-matching combination of txFilter and txFilterLength");
         }
+        if (!TlvBufferUtils.isValid(mTxFilter, mTxFilterLength, 0, 1)) {
+            throw new IllegalArgumentException(
+                    "Invalid txFilter configuration - LV fields do not match up to length");
+        }
         if (mRxFilterLength != 0 && (mRxFilter == null || mRxFilter.length < mRxFilterLength)) {
             throw new IllegalArgumentException(
                     "Non-matching combination of rxFilter and rxFilterLength");
         }
+        if (!TlvBufferUtils.isValid(mRxFilter, mRxFilterLength, 0, 1)) {
+            throw new IllegalArgumentException(
+                    "Invalid rxFilter configuration - LV fields do not match up to length");
+        }
         if (mPublishType < PUBLISH_TYPE_UNSOLICITED || mPublishType > PUBLISH_TYPE_SOLICITED) {
             throw new IllegalArgumentException("Invalid publishType - " + mPublishType);
         }
diff --git a/wifi/java/android/net/wifi/nan/SubscribeConfig.java b/wifi/java/android/net/wifi/nan/SubscribeConfig.java
index 3133d3e..0d3ea01 100644
--- a/wifi/java/android/net/wifi/nan/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/nan/SubscribeConfig.java
@@ -327,10 +327,18 @@
             throw new IllegalArgumentException(
                     "Non-matching combination of txFilter and txFilterLength");
         }
+        if (!TlvBufferUtils.isValid(mTxFilter, mTxFilterLength, 0, 1)) {
+            throw new IllegalArgumentException(
+                    "Invalid txFilter configuration - LV fields do not match up to length");
+        }
         if (mRxFilterLength != 0 && (mRxFilter == null || mRxFilter.length < mRxFilterLength)) {
             throw new IllegalArgumentException(
                     "Non-matching combination of rxFilter and rxFilterLength");
         }
+        if (!TlvBufferUtils.isValid(mRxFilter, mRxFilterLength, 0, 1)) {
+            throw new IllegalArgumentException(
+                    "Invalid rxFilter configuration - LV fields do not match up to length");
+        }
         if (mSubscribeType < SUBSCRIBE_TYPE_PASSIVE || mSubscribeType > SUBSCRIBE_TYPE_ACTIVE) {
             throw new IllegalArgumentException("Invalid subscribeType - " + mSubscribeType);
         }
diff --git a/wifi/java/android/net/wifi/nan/TlvBufferUtils.java b/wifi/java/android/net/wifi/nan/TlvBufferUtils.java
index fa1dcf1..da7ecd8 100644
--- a/wifi/java/android/net/wifi/nan/TlvBufferUtils.java
+++ b/wifi/java/android/net/wifi/nan/TlvBufferUtils.java
@@ -488,4 +488,43 @@
             };
         }
     }
+
+    /**
+     * Validates that a (T)LV array is constructed correctly. I.e. that its specified Length
+     * fields correctly fill the specified length (and do not overshoot).
+     *
+     * @param array The (T)LV array to verify.
+     * @param length The number of bytes in the array to consider (starting at offset 0).
+     * @param typeSize The size (in bytes) of the type field. Valid values are 0, 1, or 2.
+     * @param lengthSize The size (in bytes) of the length field. Valid values are 1 or 2.
+     * @return A boolean indicating whether the array is valid (true) or invalid (false).
+     */
+    public static boolean isValid(byte[] array, int length, int typeSize, int lengthSize) {
+        if (typeSize < 0 || typeSize > 2) {
+            throw new IllegalArgumentException(
+                    "Invalid arguments - typeSize must be 0, 1, or 2: typeSize=" + typeSize);
+        }
+        if (lengthSize <= 0 || lengthSize > 2) {
+            throw new IllegalArgumentException(
+                    "Invalid arguments - lengthSize must be 1 or 2: lengthSize=" + lengthSize);
+        }
+        if (length < 0 || length > array.length) {
+            throw new IllegalArgumentException(
+                    "Invalid arguments - length must be non-negative and <= array.length: length="
+                            + length + ", array.length=" + array.length);
+        }
+
+        int nextTlvIndex = 0;
+        while (nextTlvIndex + typeSize + lengthSize <= length) {
+            nextTlvIndex += typeSize;
+            if (lengthSize == 1) {
+                nextTlvIndex += lengthSize + array[nextTlvIndex];
+            } else {
+                nextTlvIndex += lengthSize + Memory.peekShort(array, nextTlvIndex,
+                        ByteOrder.BIG_ENDIAN);
+            }
+        }
+
+        return nextTlvIndex == length;
+    }
 }