kotlin-toolkit icon indicating copy to clipboard operation
kotlin-toolkit copied to clipboard

LCP Decryption Fails for Large PDF (~180MB) with OutOfMemoryError in LcpDecryptorKt.decryptFully

Open nageshwararao1988 opened this issue 4 months ago • 4 comments

Describe the bug

I am encountering a java.lang.OutOfMemoryError when attempting to decrypt a large LCP-protected resource using the readium-lcp module.

I tried with android:largeHeap="true in Manifest, Still app getting crash issue

Here is the The stack trace:

java.lang.OutOfMemoryError: Failed to allocate a 189462448 byte allocation with 25099808 free bytes and 23MB until OOM, target footprint 603979776, growth limit 603979776 at java.util.Arrays.copyOfRange(Arrays.java:3870) at kotlin.collections.ArraysKt___ArraysJvmKt.copyOfRange(_ArraysJvm.kt:1475) at org.readium.r2.lcp.LcpDecryptorKt.decryptFully(LcpDecryptor.kt:281) at org.readium.r2.lcp.LcpDecryptorKt.access$decryptFully(LcpDecryptor.kt:1) at org.readium.r2.lcp.LcpDecryptorKt$decryptFully$1.invokeSuspend(Unknown Source:14) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100) at android.os.Handler.handleCallback(Handler.java:959) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loopOnce(Looper.java:232) at android.os.Looper.loop(Looper.java:317) at android.app.ActivityThread.main(ActivityThread.java:8705) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:886) Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@b4fa5e1, Dispatchers.Main.immediate]

How to reproduce?

Trying to open PDF books After download

Readium version

3.1.2

Android API version

Android 15

Additional context

The stack trace indicates that the library is attempting to allocate a very large ByteArrayin memory using Arrays.copyOfRange within the decryptFully function, which is the root cause of the OOM crash.

nageshwararao1988 avatar Nov 25 '25 08:11 nageshwararao1988

Are you using the PDFium adapter? It doesn't support range requests, so reading and decrypting the whole file is the expected behavior.

qnga avatar Nov 25 '25 09:11 qnga

val publicationOpener = PublicationOpener( publicationParser = DefaultPublicationParser( context, assetRetriever = assetRetriever, httpClient = httpClient, pdfFactory = PdfiumDocumentFactory(context) ), contentProtections = contentProtections )

Yes @qnga ,I'm using the PDFium adapter. Since it needs to load the entire file, it crashes on large PDFs. Are there any other parsers in Readium that support for large LCP files, or any workaround to avoid loading everything into memory?

cc @mickael-menu

nageshwararao1988 avatar Nov 26 '25 10:11 nageshwararao1988

We've got an adapter for PsPdfKit. It supports range requests but it is paid.

qnga avatar Nov 26 '25 11:11 qnga

For more information:

  • https://github.com/readium/kotlin-toolkit/tree/develop/readium/adapters/pdfium
  • https://github.com/readium/kotlin-toolkit/tree/develop/readium/adapters/pspdfkit

mickael-menu avatar Nov 26 '25 12:11 mickael-menu