Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import android.content.Intent
import android.net.Uri
import android.graphics.drawable.BitmapDrawable
import android.provider.Settings
import android.os.Build
import android.content.pm.PackageManager
import android.content.pm.PackageInfo
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.activity.compose.BackHandler
Expand Down Expand Up @@ -180,6 +183,34 @@ fun PhotoReasoningScreen(
) { uri ->
uri?.let { imageUris.add(it) }
}

fun hasTermuxRunCommandPermission(): Boolean {
val runtimeGranted = ContextCompat.checkSelfPermission(
context,
"com.termux.permission.RUN_COMMAND"
) == PackageManager.PERMISSION_GRANTED
if (!runtimeGranted) return false

return runCatching {
val packageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
context.packageManager.getPackageInfo(
context.packageName,
PackageManager.PackageInfoFlags.of(PackageManager.GET_PERMISSIONS.toLong())
)
} else {
@Suppress("DEPRECATION")
context.packageManager.getPackageInfo(context.packageName, PackageManager.GET_PERMISSIONS)
}
val permissions = packageInfo.requestedPermissions ?: return@runCatching runtimeGranted
val flags = packageInfo.requestedPermissionsFlags ?: return@runCatching runtimeGranted
val index = permissions.indexOf("com.termux.permission.RUN_COMMAND")
if (index == -1 || index >= flags.size) runtimeGranted
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Logic Error: The index bounds check on line 207 allows the function to return runtimeGranted when index >= flags.size, but this creates a logic flaw. If the permission exists in requestedPermissions at position index but flags array is too short, the code assumes the runtime permission check alone is sufficient. However, this bypasses the intended hardening that verifies both runtime permission state AND the grant flags. When flags array is unexpectedly shorter than permissions array (indicating a corrupted or inconsistent PackageInfo state), the function should treat this as a permission denial rather than falling back to the potentially incorrect runtime check that the PR aims to fix.

Suggested change
if (index == -1 || index >= flags.size) runtimeGranted
if (index == -1 || index >= flags.size) false

else (flags[index] and PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0
}.getOrElse {
Log.w("PhotoReasoningScreen", "Unable to verify requestedPermissionsFlags for Termux permission", it)
runtimeGranted
}
}
val termuxPermissionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted ->
Expand Down Expand Up @@ -444,10 +475,7 @@ fun PhotoReasoningScreen(
}

if (userQuestion.isNotBlank()) {
val hasTermuxRunCommandPermission = ContextCompat.checkSelfPermission(
context,
"com.termux.permission.RUN_COMMAND"
) == android.content.pm.PackageManager.PERMISSION_GRANTED
val hasTermuxRunCommandPermission = hasTermuxRunCommandPermission()
if (!hasTermuxRunCommandPermission) {
val denialCount = TermuxFeedbackPreferences.incrementPermissionDenialCount(context)
if (denialCount >= 3) {
Expand Down
Loading