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 MIN_HEIGHT_IN_DP = 100
const val MAX_HEIGHT_IN_DP = 360 const val MAX_HEIGHT_IN_DP = 360
const val DEFAULT_ASPECT_RATIO = 1.33f const val DEFAULT_ASPECT_RATIO = 1.33f
const val MIN_ASPECT_RATIO = 0.001f
const val MAX_ASPECT_RATIO = 10f
@Composable @Composable
fun TimelineItemAspectRatioBox( fun TimelineItemAspectRatioBox(
@ -30,7 +32,8 @@ fun TimelineItemAspectRatioBox(
maxHeight: Int = MAX_HEIGHT_IN_DP, maxHeight: Int = MAX_HEIGHT_IN_DP,
content: @Composable (BoxScope.() -> Unit), 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( Box(
modifier = modifier modifier = modifier
.heightIn(min = minHeight.dp, max = maxHeight.dp) .heightIn(min = minHeight.dp, max = maxHeight.dp)

View file

@ -50,6 +50,11 @@ import kotlinx.collections.immutable.toImmutableList
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import kotlin.time.Duration 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 @Inject
class TimelineItemContentMessageFactory( class TimelineItemContentMessageFactory(
private val fileSizeFormatter: FileSizeFormatter, private val fileSizeFormatter: FileSizeFormatter,
@ -83,7 +88,10 @@ class TimelineItemContentMessageFactory(
val dom = messageType.formattedCaption?.toHtmlDocument(permalinkParser = permalinkParser) val dom = messageType.formattedCaption?.toHtmlDocument(permalinkParser = permalinkParser)
val formattedCaption = dom?.let(::parseHtml) val formattedCaption = dom?.let(::parseHtml)
?: messageType.caption?.withLinks() ?: 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( TimelineItemImageContent(
filename = messageType.filename, filename = messageType.filename,
fileSize = messageType.info?.size ?: 0, fileSize = messageType.info?.size ?: 0,
@ -94,10 +102,10 @@ class TimelineItemContentMessageFactory(
thumbnailSource = messageType.info?.thumbnailSource, thumbnailSource = messageType.info?.thumbnailSource,
mimeType = messageType.info?.mimetype ?: MimeTypes.OctetStream, mimeType = messageType.info?.mimetype ?: MimeTypes.OctetStream,
blurhash = messageType.info?.blurhash, blurhash = messageType.info?.blurhash,
width = messageType.info?.width?.toInt(), width = width?.toInt(),
height = messageType.info?.height?.toInt(), height = height?.toInt(),
thumbnailWidth = messageType.info?.thumbnailInfo?.width?.toInt(), thumbnailWidth = messageType.info?.thumbnailInfo?.width?.coerceIn(MIN_IMAGE_SIZE, MAX_IMAGE_SIZE)?.toInt(),
thumbnailHeight = messageType.info?.thumbnailInfo?.height?.toInt(), thumbnailHeight = messageType.info?.thumbnailInfo?.height?.coerceIn(MIN_IMAGE_SIZE, MAX_IMAGE_SIZE)?.toInt(),
aspectRatio = aspectRatio, aspectRatio = aspectRatio,
formattedFileSize = fileSizeFormatter.format(messageType.info?.size ?: 0), formattedFileSize = fileSizeFormatter.format(messageType.info?.size ?: 0),
fileExtension = fileExtensionExtractor.extractFromName(messageType.filename) fileExtension = fileExtensionExtractor.extractFromName(messageType.filename)