Skip to content

Commit ec07719

Browse files
authored
Prevent crash when decoding binary multipart request bodies (#9680)
1 parent 4586915 commit ec07719

4 files changed

Lines changed: 64 additions & 16 deletions

File tree

packages/devtools_app/lib/src/screens/network/constants.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ enum NetworkEventKeys {
5656
httpOnly,
5757
secure,
5858
reasonPhrase,
59+
encoding,
5960
}
6061

6162
class NetworkEventDefaults {

packages/devtools_app/lib/src/screens/network/har_data_entry.dart

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
44

55
import 'dart:convert';
6+
import 'dart:typed_data';
67

78
import '../../screens/network/utils/http_utils.dart';
89
import '../../shared/http/http_request_data.dart';
9-
import '../../shared/primitives/utils.dart';
1010
import 'constants.dart';
1111

1212
/// A class representing a single entry in the HTTP Archive (HAR) format.
@@ -119,6 +119,11 @@ class HarDataEntry {
119119
};
120120
}).toList();
121121

122+
final encodedRequest = e.encodedRequest;
123+
final encodedResponse = e.encodedResponse;
124+
final decodedRequest = _decodeBytes(encodedRequest);
125+
final decodedResponse = _decodeBytes(encodedResponse);
126+
122127
return <String, Object?>{
123128
NetworkEventKeys.startedDateTime.name: e.startTimestamp
124129
.toUtc()
@@ -134,12 +139,12 @@ class HarDataEntry {
134139
NetworkEventKeys.queryString.name: queryString,
135140
NetworkEventKeys.postData.name: <String, Object?>{
136141
NetworkEventKeys.mimeType.name: e.contentType,
137-
NetworkEventKeys.text.name: e.requestBody,
142+
NetworkEventKeys.text.name: decodedRequest,
138143
},
139144
NetworkEventKeys.headersSize.name: calculateHeadersSize(
140145
e.requestHeaders,
141146
),
142-
NetworkEventKeys.bodySize.name: _calculateBodySize(e.requestBody),
147+
NetworkEventKeys.bodySize.name: _calculateBodySize(encodedRequest),
143148
},
144149
// Response
145150
NetworkEventKeys.response.name: <String, Object?>{
@@ -151,15 +156,17 @@ class HarDataEntry {
151156
NetworkEventKeys.cookies.name: responseCookies,
152157
NetworkEventKeys.headers.name: responseHeaders,
153158
NetworkEventKeys.content.name: <String, Object?>{
154-
NetworkEventKeys.size.name: e.responseBody?.length,
159+
NetworkEventKeys.size.name: encodedResponse?.length ?? 0,
155160
NetworkEventKeys.mimeType.name: e.type,
156-
NetworkEventKeys.text.name: e.responseBody,
161+
NetworkEventKeys.text.name: decodedResponse,
162+
if (_isBinary(encodedResponse))
163+
NetworkEventKeys.encoding.name: 'base64',
157164
},
158165
NetworkEventKeys.redirectURL.name: '',
159166
NetworkEventKeys.headersSize.name: calculateHeadersSize(
160167
e.responseHeaders,
161168
),
162-
NetworkEventKeys.bodySize.name: _calculateBodySize(e.responseBody),
169+
NetworkEventKeys.bodySize.name: _calculateBodySize(encodedResponse),
163170
},
164171
// Cache
165172
NetworkEventKeys.cache.name: <String, Object?>{},
@@ -194,6 +201,25 @@ class HarDataEntry {
194201
return request;
195202
}
196203

204+
static String? _decodeBytes(Uint8List? bytes) {
205+
if (bytes == null) return null;
206+
try {
207+
return utf8.decode(bytes);
208+
} catch (_) {
209+
return base64Encode(bytes);
210+
}
211+
}
212+
213+
static bool _isBinary(Uint8List? bytes) {
214+
if (bytes == null) return false;
215+
try {
216+
utf8.decode(bytes);
217+
return false;
218+
} catch (_) {
219+
return true;
220+
}
221+
}
222+
197223
static Map<String, Object?> _convertHeadersListToMap(
198224
List<Object?> serializedHeaders,
199225
) {
@@ -271,9 +297,6 @@ class HarDataEntry {
271297
}
272298
}
273299

274-
int _calculateBodySize(String? requestBody) {
275-
if (requestBody.isNullOrEmpty) {
276-
return 0;
277-
}
278-
return utf8.encode(requestBody!).length;
300+
int _calculateBodySize(Uint8List? body) {
301+
return body?.length ?? 0;
279302
}

packages/devtools_app/lib/src/shared/http/http_request_data.dart

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,23 @@ class DartIOHttpRequestData extends NetworkRequest {
101101
);
102102
_request = updated;
103103
final fullRequest = _request as HttpProfileRequest;
104-
_responseBody = utf8.decode(fullRequest.responseBody!);
105-
_requestBody = utf8.decode(fullRequest.requestBody!);
104+
if (fullRequest.responseBody != null) {
105+
try {
106+
_responseBody = utf8.decode(fullRequest.responseBody!);
107+
} catch (_) {
108+
_responseBody =
109+
'[Binary data (${fullRequest.responseBody!.length} bytes)]';
110+
}
111+
}
112+
113+
if (fullRequest.requestBody != null) {
114+
try {
115+
_requestBody = utf8.decode(fullRequest.requestBody!);
116+
} catch (_) {
117+
_requestBody =
118+
'[Binary data (${fullRequest.requestBody!.length} bytes)]';
119+
}
120+
}
106121
notifyListeners();
107122
}
108123
} finally {
@@ -303,7 +318,9 @@ class DartIOHttpRequestData extends NetworkRequest {
303318
_responseBody = utf8.decode(fullRequest.responseBody!);
304319
return _responseBody;
305320
} on FormatException {
306-
return '<binary data>';
321+
_responseBody =
322+
'[Binary data (${fullRequest.responseBody!.length} bytes)]';
323+
return _responseBody;
307324
}
308325
}
309326

@@ -313,6 +330,12 @@ class DartIOHttpRequestData extends NetworkRequest {
313330
return fullRequest.responseBody;
314331
}
315332

333+
Uint8List? get encodedRequest {
334+
if (_request is! HttpProfileRequest) return null;
335+
final fullRequest = _request as HttpProfileRequest;
336+
return fullRequest.requestBody;
337+
}
338+
316339
String? _responseBody;
317340

318341
String? get requestBody {
@@ -329,7 +352,8 @@ class DartIOHttpRequestData extends NetworkRequest {
329352
_requestBody = utf8.decode(fullRequest.requestBody!);
330353
return _requestBody;
331354
} on FormatException {
332-
return '<binary data>';
355+
_requestBody = '[Binary data (${fullRequest.requestBody!.length} bytes)]';
356+
return _requestBody;
333357
}
334358
}
335359

packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ TODO: Remove this section if there are not any updates.
3939

4040
## Network profiler updates
4141

42-
TODO: Remove this section if there are not any updates.
42+
- Fix crash in the Network tab when viewing binary multipart request or response bodies (#9978)
4343

4444
## Logging updates
4545

0 commit comments

Comments
 (0)