Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(storage): prevent transfer work exception #2851

Closed
wants to merge 6 commits into from

Conversation

tylerjroach
Copy link
Member

@tylerjroach tylerjroach commented Jun 14, 2024

  • PR title and description conform to Pull Request guidelines.

We did not have a try/catch around a method that can throw https://developer.android.com/reference/android/database/Cursor#getColumnIndexOrThrow(java.lang.String).

In rare cases (likely db close) a column may not be available. If this happens, we break out of reading the cursor.

See customer issue for more details.

Issue #, if available:
#2840

Description of changes:
See reported issue for details

How did you test these changes?
(Please add a line here how the changes were tested)

Documentation update required?

  • No
  • Yes (Please include a PR link for the documentation update)

General Checklist

  • Added Unit Tests
  • Added Integration Tests
  • Security oriented best practices and standards are followed (e.g. using input sanitization, principle of least privilege, etc)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@tylerjroach tylerjroach requested a review from a team as a code owner June 14, 2024 13:46
vincetran
vincetran previously approved these changes Jun 14, 2024
@tylerjroach tylerjroach enabled auto-merge (squash) June 27, 2024 18:25
@@ -186,8 +186,14 @@ internal class TransferWorkerObserver private constructor(
)
)?.use {
while (it.moveToNext()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

if we catch and continue, what happens on the next it.moveToNext() ? does it return null and break out? would it be safer to catch and break out?

Copy link
Member Author

Choose a reason for hiding this comment

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

It would be false the next time and break out itself

Copy link
Contributor

@lawmicha lawmicha Jul 2, 2024

Choose a reason for hiding this comment

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

I think moving the try-catch to include the while(it.moveToNext()) may be safer incase there's a behavior change where it also throws on closed cursor or some other issue

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

I went ahead and added a break as looking through cursor code, I couldn't find where cursor count would be reset to 0 when closed, and didn't see moveToNext checking if cursor were open.

Comment on lines 194 to 196
} catch (exception: IllegalStateException) {
// do nothing. Cursor is likely closed
}
Copy link
Contributor

Choose a reason for hiding this comment

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

If we want to swallow all exceptions here, we would need a second catch block for exceptions other than IlllegalStateException

Copy link
Member Author

Choose a reason for hiding this comment

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

https://developer.android.com/reference/android/database/Cursor#getColumnIndexOrThrow(java.lang.String)

IllegalStateException is the only exception type to be handled here. Since these Android APIs are written in Java, we can trust that the exceptions thrown should only be the ones listed in documentation.

attachObserver(id.toString())
} catch (exception: IllegalStateException) {
// Stop iterating over cursor. Cursor is likely closed
break
Copy link
Member

Choose a reason for hiding this comment

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

Is this situation worthy of an error long? What is the impact of failing to attach an observer?

val id = it.getInt(it.getColumnIndexOrThrow(TransferTable.COLUMN_ID))
attachObserver(id.toString())
// getInt has been reported to throw in rare cases where it appears another thread
// may have closed cursor
Copy link
Member

Choose a reason for hiding this comment

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

Any ideas how this could happen?

@tylerjroach
Copy link
Member Author

Closing this PR as the fix was a bit misguided.

  1. The cursor is never closed in the app, so this isn't a closed cursor.
  2. getInt is in fact throwing (even though it doesn't say it throws. It's crashing at a native jni layer.
  3. Couldn't read at row 912, column 0 means that a row in the db was not able to be read. Column 0 should just be the "_id" column of TransferTable. In research, this type of issue typically appears if we attempt to read column data containing 2+MB of data. This shouldn't be the case here being only the _id. My only other speculation at this time (outside of device bugs outside of our control), is that multithreaded operations hitting the table could be clearing the cursor where row 912 doesn't actually exist at the time we try to read data from it.

@tylerjroach tylerjroach closed this Jul 2, 2024
auto-merge was automatically disabled July 2, 2024 16:14

Pull request was closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants