Crashlytics plugin writes build ID lists in directory listing order, so APKs can differ between machines

Abierto Apto para principiantes
#8,789 1 comentario 0 reacciones 1 asignado Ver en GitHub

Los mantenedores suelen responder en 1 día

@mrober ya está trabajando en esto.

Desde el 6/11/2026.

  • #8801 de @Nikhila-Dhevi-R — abierto

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
72/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
android, java

Línea de trabajo

Empieza en BuildIdInfoCollector.collect() en firebase-crashlytics-buildtools, donde el bucle sobre FileUtils.listFiles() añade filas de BuildIdInfo, y revisa cómo se derivan las listas de nombre de biblioteca, arquitectura e ID de compilación a partir de esa única lista. Añade una ordenación determinista al final de collect() usando los campos que propone el issue, y verifica la salida con una prueba unitaria que alimente los archivos en orden aleatorio. Está terminado cuando las mismas entradas siempre producen el mismo orden de filas y las tres listas siguen emparejadas.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

api: crashlytics
[REQUIRED] Step 2: Describe your environment
  • Android Studio version: not used; command-line build with Gradle 9.3.1, AGP 9.1.1 and JDK 21
  • Firebase Component: Crashlytics Gradle plugin
  • Component version: 3.0.8
[REQUIRED] Step 3: Describe the problem

When nativeSymbolUploadEnabled is on, the plugin writes three lists into the app's resources:
com.google.firebase.crashlytics.build_ids_lib, _arch and _build_id.

The rows follow directory listing order and are not sorted. So the same source can produce a different
resources.arsc, which breaks reproducible builds. We verify open source Bitcoin wallets at WalletScrutiny,
and this is how we found it.

BuildIdInfoCollector.collect() loops over FileUtils.listFiles()
and adds rows in that order. That helper
does not sort either.

Steps to reproduce:
  1. Use an app with native libraries, and set nativeSymbolUploadEnabled true.
  2. Build it normally, and keep com_google_firebase_crashlytics_build_ids.xml.
  3. Mount the source with disorderfs --shuffle-dirents=yes --reverse-dirents=no --sort-dirents=no <source> <mount>.
  4. Build the same commit inside the mount.
  5. Compare the two files. The rows match, but their order differs.

We ran these builds with P.CASH 0.60.1, commit ab67f8e649, on one host:

Build List order
Normal, first same as second
Normal, second same as first
Under disorderfs shuffle different

The shuffled build still had the same 80 rows. After sorting them, the only decoded difference left was the
random mapping_file_id (#2570). Two of the three APK splits stayed byte-identical.

We also compared the developer's official builds with ours:

Release Official file Commit Rows Changed list lines
0.60.1 Google Play base.apk ab67f8e649 80 262
1.0.260 GitHub -google APK 596bf08522 74 246

Each pair has the same rows once sorted.

Limits of our testing:

  • We ran one shuffled build.
  • We did not build on two machines of our own.
  • We have no minimal sample project.

Expected: the same source gives the same list order, whatever the directory listing order is.

Relevant Code:

Part of the 0.60.1 diff (official <, ours >):

<         <item>libjnidispatch.so</item>
<         <item>libgojni.so</item>
<         <item>libcrashlytics-common.so</item>
>         <item>libc++_shared.so</item>
>         <item>libimage_processing_util_jni.so</item>
>         <item>libsecp256k1-jni.so</item>

A possible fix, at the end of collect(), which we have not compiled or tested:

buildIdInfoList.sort(
    Comparator.comparing(BuildIdInfo::getLibraryName)
        .thenComparing(BuildIdInfo::getArch)
        .thenComparing(BuildIdInfo::getBuildId));

All three lists come from this one list, so the rows should stay paired.

Related: #2570 covers the random mapping_file_id. This issue is only about list order.

Lenguaje dominante
Java
Estrellas
2.6k
Forks
733
Merge medio
2 d 15 h
PR fusionados (30 d)
72

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de firebase/firebase-android-sdk

Todos los issues de firebase/firebase-android-sdk

Issues similares

Más issues de Java

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.