Ensure aspect ratio of images in the timeline is restricted (#6168)

* Ensure aspect ratio of images in the timeline is restricted

Otherwise, this could cause a crash in Compose since the width and height values could become way too large.
This commit is contained in:
Jorge Martin Espinosa
2026-02-10 15:38:55 +01:00
committed by GitHub
parent ea994bd85f
commit 1ec39821af
2 changed files with 17 additions and 6 deletions

View File

@@ -20,6 +20,8 @@ import androidx.compose.ui.unit.dp
const val MIN_HEIGHT_IN_DP = 100
const val MAX_HEIGHT_IN_DP = 360
const val DEFAULT_ASPECT_RATIO = 1.33f
const val MIN_ASPECT_RATIO = 0.001f
const val MAX_ASPECT_RATIO = 10f
@Composable
fun TimelineItemAspectRatioBox(
@@ -30,7 +32,8 @@ fun TimelineItemAspectRatioBox(
maxHeight: Int = MAX_HEIGHT_IN_DP,
content: @Composable (BoxScope.() -> Unit),
) {
val safeAspectRatio = aspectRatio ?: DEFAULT_ASPECT_RATIO
// Make sure the aspect ratio is not extremely large, otherwise the resulting size can crash Compose
val safeAspectRatio = aspectRatio?.coerceIn(MIN_ASPECT_RATIO, MAX_ASPECT_RATIO) ?: DEFAULT_ASPECT_RATIO
Box(
modifier = modifier
.heightIn(min = minHeight.dp, max = maxHeight.dp)

View File

@@ -50,6 +50,11 @@ import kotlinx.collections.immutable.toImmutableList
import org.jsoup.nodes.Document
import kotlin.time.Duration
private const val MIN_IMAGE_SIZE = 1L
private const val MAX_IMAGE_SIZE = 10_000L
private const val MIN_ASPECT_RATIO = 0.001f
private const val MAX_ASPECT_RATIO = 10f
@Inject
class TimelineItemContentMessageFactory(
private val fileSizeFormatter: FileSizeFormatter,
@@ -83,7 +88,10 @@ class TimelineItemContentMessageFactory(
val dom = messageType.formattedCaption?.toHtmlDocument(permalinkParser = permalinkParser)
val formattedCaption = dom?.let(::parseHtml)
?: messageType.caption?.withLinks()
val aspectRatio = aspectRatioOf(messageType.info?.width, messageType.info?.height)
// Coerce the image sizes and prevent invalid aspect ratios, which can cause crashes
val width = messageType.info?.width?.coerceIn(MIN_IMAGE_SIZE, MAX_IMAGE_SIZE)
val height = messageType.info?.height?.coerceIn(MIN_IMAGE_SIZE, MAX_IMAGE_SIZE)
val aspectRatio = aspectRatioOf(width, height)?.coerceIn(MIN_ASPECT_RATIO, MAX_ASPECT_RATIO)
TimelineItemImageContent(
filename = messageType.filename,
fileSize = messageType.info?.size ?: 0,
@@ -94,10 +102,10 @@ class TimelineItemContentMessageFactory(
thumbnailSource = messageType.info?.thumbnailSource,
mimeType = messageType.info?.mimetype ?: MimeTypes.OctetStream,
blurhash = messageType.info?.blurhash,
width = messageType.info?.width?.toInt(),
height = messageType.info?.height?.toInt(),
thumbnailWidth = messageType.info?.thumbnailInfo?.width?.toInt(),
thumbnailHeight = messageType.info?.thumbnailInfo?.height?.toInt(),
width = width?.toInt(),
height = height?.toInt(),
thumbnailWidth = messageType.info?.thumbnailInfo?.width?.coerceIn(MIN_IMAGE_SIZE, MAX_IMAGE_SIZE)?.toInt(),
thumbnailHeight = messageType.info?.thumbnailInfo?.height?.coerceIn(MIN_IMAGE_SIZE, MAX_IMAGE_SIZE)?.toInt(),
aspectRatio = aspectRatio,
formattedFileSize = fileSizeFormatter.format(messageType.info?.size ?: 0),
fileExtension = fileExtensionExtractor.extractFromName(messageType.filename)