-
Notifications
You must be signed in to change notification settings - Fork 536
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
[AndroidMessageHandler] ReadAsByteArrayAsync occasionally returning incorrect byte array #8740
Comments
Here's an example project that helps reproducing the issue: androidmessagehandler.zip The returned data should be an 8 byte long byte array (string "dGVzdA=="). In my tests, the problem occured 3x after ~1.800 HTTP requests on Android. I confirmed via Fiddler that in fact there was always the exact same byte array sent over the network each time. |
@tipa thanks for the repro project. @grendello This looks like a race condition to me. The If at the same time we're processing a response in another thread, we might return raw compressed data instead of decompressing them: If I understand the code correctly, |
Fixes: #8740 There is a race condition in `AndroidMessageHandler` (see #8740 (comment) for more information). The solution is fairly simple: we should determine the decompression strategy only during the setup, when `AutomaticDecompression` is set. We don't need to do any more work during the request. To prevent changing the decompression strategy while there are requests mid-flight, the setter will only accept values until the first request is sent. This is exactly what the `SocketsHttpHandler` does. I didn't want to touch any code unrelated to the race condition in this PR so if we want to prevent other properties from being mutated while HTTP requests are being sent, we should do it in a follow-up PR.
Fixes: #8740 There is a race condition in `AndroidMessageHandler` (see #8740 (comment) for more information). The solution is fairly simple: we should determine the decompression strategy only during the setup, when `AutomaticDecompression` is set. We don't need to do any more work during the request. To prevent changing the decompression strategy while there are requests mid-flight, the setter will only accept values until the first request is sent. This is exactly what the `SocketsHttpHandler` does. I didn't want to touch any code unrelated to the race condition in this PR so if we want to prevent other properties from being mutated while HTTP requests are being sent, we should do it in a follow-up PR.
Android application type
.NET Android (net8.0-android)
Affected platform version
34.0.79/8.0.100
Description
My app is syncing contents to and from users personal cloud storage (e.g. OneDrive, Google Drive, & Dropbox), using the respective official HTTP APIs. The files are encrypted and after downloading, my app decrypts them using Aes.DecryptCbc. Now, occasionally, this method throws an exception:
System.Security.Cryptography.CryptographicException: Cryptography_PartialBlock
It appears that an incorrect byte array has been returned by
HttpContent.ReadAsByteArrayAsync()
and the decryption fails due to invalid padding.The following reasons make me believe that this is a bug in
AndroidMessageHandler
rather than my apps code or the servers returning wrong data:CryptographicException
mentioned above occurs, I am retrying the download of the same file & running the decryption again: it always works and doesn't throw an exception any moreHttpClientHandlers
below)Accept-Encoding: gzip,deflate
in the http request. Dropbox on the other hand does not compress the http body when downloading files even when theAccept-Encoding
header is present.Therefore it appears to me that the problem is somehow connected to how the
AndroidMessageHandler
does decrypts the gzipped data before returning it to the applicationSteps to Reproduce
I'd expect this problem very hard to reproduce. According to Google Console, my app does approx. a million requests to Google Drive & OneDrive every month and according to AppCenter, this issue occured ~100 times in the last 28 days. I did not yet observe the problem when downloading a file through the Dropbox API
As I am using the same
HttpClient
instance across the app and multiple requests are sent simultaneously, perhaps the issue is caused by some race condition.On iOS/macOS I use
NSUrlSessionHandler
. Note: I did not specifyAutomaticDecompression
as NSUrlSessionHandler is using gzip by defaultOn Windows/UWP:
And this is essentially how the request is sent
Did you find any workaround?
I will attempt to use another static HttpClient that is not configured with
AutomaticDecompression
that I will use for downloading binary data, so that the servers will not return gzipped data. As the data I am syncing is mostly .jpgs or .mp4s, gzip-compressing that data doesn't shrink the size any further, I might even save some CPU cycles and network bandwidth...The text was updated successfully, but these errors were encountered: