ui: collect logs from IO thread only

Otherwise the pop() from the producer might causes an OOB read in the
consumer:

Exception java.lang.ArrayIndexOutOfBoundsException:
  at androidx.collection.CircularArray.get (CircularArray.java)
  at com.wireguard.android.activity.LogViewerActivity.rawLogBytes (LogViewerActivity.java)
  at com.wireguard.android.activity.LogViewerActivity.onCreate$lambda$3 (LogViewerActivity.java:133)
  at android.view.View.performClick (View.java:6935)
  at android.view.View$PerformClick.run (View.java:26214)
  at android.os.Handler.handleCallback (Handler.java:790)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loop (Looper.java:164)
  at android.app.ActivityThread.main (ActivityThread.java:7000)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:441)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1408)

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2023-05-05 02:56:51 +02:00
parent 7778ff63b5
commit a3bfa6f1ab

View File

@ -112,11 +112,12 @@ class LogViewerActivity : AppCompatActivity() {
} }
binding.shareFab.setOnClickListener { binding.shareFab.setOnClickListener {
lifecycleScope.launch {
revokeLastUri() revokeLastUri()
val key = KeyPair().privateKey.toHex() val key = KeyPair().privateKey.toHex()
LOGS[key] = rawLogBytes() LOGS[key] = rawLogBytes()
lastUri = Uri.parse("content://${BuildConfig.APPLICATION_ID}.exported-log/$key") lastUri = Uri.parse("content://${BuildConfig.APPLICATION_ID}.exported-log/$key")
val shareIntent = ShareCompat.IntentBuilder(this) val shareIntent = ShareCompat.IntentBuilder(this@LogViewerActivity)
.setType("text/plain") .setType("text/plain")
.setSubject(getString(R.string.log_export_subject)) .setSubject(getString(R.string.log_export_subject))
.setStream(lastUri) .setStream(lastUri)
@ -127,6 +128,7 @@ class LogViewerActivity : AppCompatActivity() {
revokeLastActivityResultLauncher.launch(shareIntent) revokeLastActivityResultLauncher.launch(shareIntent)
} }
} }
}
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.log_viewer, menu) menuInflater.inflate(R.menu.log_viewer, menu)
@ -151,12 +153,14 @@ class LogViewerActivity : AppCompatActivity() {
private val downloadsFileSaver = DownloadsFileSaver(this) private val downloadsFileSaver = DownloadsFileSaver(this)
private fun rawLogBytes() : ByteArray { private suspend fun rawLogBytes() : ByteArray {
val builder = StringBuilder() val builder = StringBuilder()
withContext(Dispatchers.IO) {
for (i in 0 until rawLogLines.size()) { for (i in 0 until rawLogLines.size()) {
builder.append(rawLogLines[i]) builder.append(rawLogLines[i])
builder.append('\n') builder.append('\n')
} }
}
return builder.toString().toByteArray(Charsets.UTF_8) return builder.toString().toByteArray(Charsets.UTF_8)
} }