From d1d2aaf7c5bf08221055116f3658f3a7e28e6763 Mon Sep 17 00:00:00 2001 From: isaactolley <205617977+isaactolley@users.noreply.github.com> Date: Fri, 10 Jul 2026 16:44:10 +0100 Subject: [PATCH] fix: reject invalid Android thumbnail options --- .../ThumbnailGenerator.kt | 16 ++++---- .../ThumbnailGeneratorTest.kt | 39 ++++++++++++++++--- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/android/src/main/java/com/marshallbear1/reactnativesystemthumbnails/ThumbnailGenerator.kt b/android/src/main/java/com/marshallbear1/reactnativesystemthumbnails/ThumbnailGenerator.kt index 269e748..b8f8141 100644 --- a/android/src/main/java/com/marshallbear1/reactnativesystemthumbnails/ThumbnailGenerator.kt +++ b/android/src/main/java/com/marshallbear1/reactnativesystemthumbnails/ThumbnailGenerator.kt @@ -174,17 +174,19 @@ internal data class ThumbnailRequest( ) } if (!width.isFinite() || width < 1.0 || width % 1.0 != 0.0 || - !height.isFinite() || height < 1.0 || height % 1.0 != 0.0 + width > MAX_DIMENSION.toDouble() || + !height.isFinite() || height < 1.0 || height % 1.0 != 0.0 || + height > MAX_DIMENSION.toDouble() ) { throw ThumbnailNativeException( ThumbnailErrorCode.INVALID_ARGUMENT, - "width and height must be positive whole numbers." + "width and height must be whole numbers from 1 to $MAX_DIMENSION." ) } - if (!quality.isFinite()) { + if (!quality.isFinite() || quality < 0.0 || quality > 1.0) { throw ThumbnailNativeException( ThumbnailErrorCode.INVALID_ARGUMENT, - "quality must be a finite number." + "quality must be a finite number from 0 through 1." ) } @@ -200,10 +202,10 @@ internal data class ThumbnailRequest( return ThumbnailRequest( requestId = requestId, uri = uri.trim(), - width = width.coerceAtMost(MAX_DIMENSION.toDouble()).toInt(), - height = height.coerceAtMost(MAX_DIMENSION.toDouble()).toInt(), + width = width.toInt(), + height = height.toInt(), format = nativeFormat, - qualityPercent = (quality.coerceIn(0.0, 1.0) * 100.0).roundToInt(), + qualityPercent = (quality * 100.0).roundToInt(), useCache = useCache, allowIconFallback = allowIconFallback ) diff --git a/android/src/test/java/com/marshallbear1/reactnativesystemthumbnails/ThumbnailGeneratorTest.kt b/android/src/test/java/com/marshallbear1/reactnativesystemthumbnails/ThumbnailGeneratorTest.kt index 7fd3fd5..17ea7fc 100644 --- a/android/src/test/java/com/marshallbear1/reactnativesystemthumbnails/ThumbnailGeneratorTest.kt +++ b/android/src/test/java/com/marshallbear1/reactnativesystemthumbnails/ThumbnailGeneratorTest.kt @@ -120,13 +120,42 @@ class ThumbnailGeneratorTest { assertEquals(ThumbnailErrorCode.CANCELLED, error.code) } - private fun request(uri: String, width: Int, height: Int) = ThumbnailRequest( + @Test + fun `bridge request rejects dimensions above maximum`() { + val error = try { + request("file:///tmp/too-large.png", 4097, 32) + throw AssertionError("Expected oversized dimensions to fail") + } catch (error: ThumbnailNativeException) { + error + } + + assertEquals(ThumbnailErrorCode.INVALID_ARGUMENT, error.code) + } + + @Test + fun `bridge request rejects quality outside supported range`() { + val error = try { + request("file:///tmp/too-lossy.jpg", 32, 32, qualityPercent = 101) + throw AssertionError("Expected invalid quality to fail") + } catch (error: ThumbnailNativeException) { + error + } + + assertEquals(ThumbnailErrorCode.INVALID_ARGUMENT, error.code) + } + + private fun request( + uri: String, + width: Int, + height: Int, + qualityPercent: Int = 90 + ) = ThumbnailRequest.fromBridge( requestId = "image-1", uri = uri, - width = width, - height = height, - format = ThumbnailFormat.PNG, - qualityPercent = 90, + width = width.toDouble(), + height = height.toDouble(), + format = "png", + quality = qualityPercent.toDouble() / 100.0, useCache = true, allowIconFallback = true )