[Android] Prevent sending group of folder lists with null items from the ML to the app
Nicolas Pomepuy
git at videolan.org
Fri Sep 11 07:09:29 UTC 2026
vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Tue May 13 14:21:19 2025 +0200| [b2f5a272616a77f5b06eaf5d75c375a0120f8202] | committer: Nicolas Pomepuy
Prevent sending group of folder lists with null items from the ML to the app
> https://code.videolan.org/videolan/vlc-android/commit/b2f5a272616a77f5b06eaf5d75c375a0120f8202
---
.../videolan/medialibrary/MedialibraryImpl.java | 4 +--
.../src/org/videolan/medialibrary/Tools.java | 26 ++++++++++++++++
.../test/org/videolan/medialibrary/ToolsTest.java | 36 ++++++++++++++++++++--
3 files changed, 62 insertions(+), 4 deletions(-)
diff --git a/medialibrary/src/org/videolan/medialibrary/MedialibraryImpl.java b/medialibrary/src/org/videolan/medialibrary/MedialibraryImpl.java
index beae616148..157866fd8a 100644
--- a/medialibrary/src/org/videolan/medialibrary/MedialibraryImpl.java
+++ b/medialibrary/src/org/videolan/medialibrary/MedialibraryImpl.java
@@ -240,7 +240,7 @@ public class MedialibraryImpl extends Medialibrary {
@Override
@WorkerThread
public VideoGroup[] getVideoGroups(int sort, boolean desc, boolean includeMissing, boolean onlyFavorites, int nbItems, int offset) {
- return mIsInitiated ? nativeGetVideoGroups(sort, desc, includeMissing, onlyFavorites, nbItems, offset) : new VideoGroup[0];
+ return mIsInitiated ? Tools.cleanupArray(nativeGetVideoGroups(sort, desc, includeMissing, onlyFavorites, nbItems, offset)) : new VideoGroup[0];
}
@Override
@@ -483,7 +483,7 @@ public class MedialibraryImpl extends Medialibrary {
@NonNull
@WorkerThread
public Folder[] getFolders(int type, int sort, boolean desc, boolean includeMissing, boolean onlyFavorites, int nbItems, int offset) {
- return mIsInitiated ? nativeGetFolders(type, sort, desc, includeMissing, onlyFavorites, nbItems, offset) : new Folder[0];
+ return mIsInitiated ? Tools.cleanupArray(nativeGetFolders(type, sort, desc, includeMissing, onlyFavorites, nbItems, offset)) : new Folder[0];
}
@Override
diff --git a/medialibrary/src/org/videolan/medialibrary/Tools.java b/medialibrary/src/org/videolan/medialibrary/Tools.java
index 6b7c0cb136..800dc01d4d 100644
--- a/medialibrary/src/org/videolan/medialibrary/Tools.java
+++ b/medialibrary/src/org/videolan/medialibrary/Tools.java
@@ -13,6 +13,7 @@ import org.videolan.medialibrary.media.MediaLibraryItem;
import java.text.DecimalFormat;
import java.text.NumberFormat;
+import java.util.Arrays;
import java.util.Locale;
import java.util.regex.Pattern;
@@ -161,4 +162,29 @@ public class Tools {
public static Boolean hasSubString(String source, String substring) {
return Pattern.compile(Pattern.quote(substring), Pattern.CASE_INSENSITIVE).matcher(source).find();
}
+
+ /**
+ * Removes null items from an array.
+ * This method is optimized to avoid allocations if the array is already "clean"
+ * and handles empty or null input safely.
+ *
+ * @param source The source array to clean
+ * @param <T> The type of the array elements
+ * @return A new array without nulls, or the original array if it was already clean or null/empty.
+ */
+ public static <T> T[] cleanupArray(T[] source) {
+ if (source == null || source.length == 0) return source;
+ int count = 0;
+ // Count non-null items first to determine the final size
+ for (T s : source) if (s != null) count++;
+ // If the array is already clean, return it as-is to save an allocation
+ if (count == source.length) return source;
+ // Create a new array of the same type and proper size
+ T[] result = Arrays.copyOf(source, count);
+ if (count == 0) return result;
+ int i = 0;
+ // Fill the new array with non-null items
+ for (T s : source) if (s != null) result[i++] = s;
+ return result;
+ }
}
diff --git a/medialibrary/test/org/videolan/medialibrary/ToolsTest.java b/medialibrary/test/org/videolan/medialibrary/ToolsTest.java
index 7e3a41400a..bb5955ab13 100644
--- a/medialibrary/test/org/videolan/medialibrary/ToolsTest.java
+++ b/medialibrary/test/org/videolan/medialibrary/ToolsTest.java
@@ -1,6 +1,12 @@
package org.videolan.medialibrary;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
import org.junit.Test;
+
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
@@ -8,7 +14,6 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
-import static org.junit.Assert.assertEquals;
public class ToolsTest {
@@ -56,4 +61,31 @@ public class ToolsTest {
exec.awaitTermination(10, TimeUnit.SECONDS);
}
-}
\ No newline at end of file
+ @Test
+ public void testCleanupArray() {
+ // Test with null
+ assertNull(Tools.cleanupArray(null));
+
+ // Test with empty array
+ String[] empty = new String[0];
+ assertSame(empty, Tools.cleanupArray(empty));
+
+ // Test with no nulls - should return same instance
+ String[] noNulls = {"a", "b", "c"};
+ assertSame(noNulls, Tools.cleanupArray(noNulls));
+
+ // Test with mixed nulls
+ String[] mixed = {"a", null, "b", null, "c"};
+ String[] expectedMixed = {"a", "b", "c"};
+ assertArrayEquals(expectedMixed, Tools.cleanupArray(mixed));
+
+ // Test with only nulls
+ String[] onlyNulls = {null, null};
+ assertEquals(0, Tools.cleanupArray(onlyNulls).length);
+
+ // Test with different types to ensure reflection works
+ Integer[] ints = {1, null, 2};
+ Integer[] expectedInts = {1, 2};
+ assertArrayEquals(expectedInts, Tools.cleanupArray(ints));
+ }
+}
More information about the Android
mailing list