Skip to content

Commit

Permalink
[ package:vm_service ] Fix issue where an exception could be thrown i…
Browse files Browse the repository at this point in the history
…f remote service protocl version was older than that supported by package:vm_service

When connecting to a VM service which supports an older version of the
protocol than that supported by package:vm_service, there was the
possibility for a crash if the package tried to create a List for a
response property which is not supported by the remote VM service. The
fix here is to check for null from createServiceObject when building a
List from a response and produce an empty list for that property.

Issue originally filed here: https://github.com/dart-lang/coverage/issues/278

Change-Id: Ibe8593fa8e4a55d05dd821bbdf363a67c15d5483
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127065
Reviewed-by: Devon Carew <devoncarew@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
  • Loading branch information
bkonyi authored and commit-bot@chromium.org committed Dec 3, 2019
1 parent f4e44dd commit 7a911ce
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 31 deletions.
6 changes: 6 additions & 0 deletions pkg/vm_service/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# Changelog
## 2.1.3
- Fixed issue where exception would be thrown when attempting to parse a
List entry in a response which is not present. This occurs when connected to
a service which does not yet support the latest service protocol supported by
this package.

## 2.1.2
- Requests which have not yet completed when `VmService.dispose` is invoked will
now complete with an `RPCError` exception rather than a `String` exception.
Expand Down
61 changes: 33 additions & 28 deletions pkg/vm_service/lib/vm_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2279,7 +2279,7 @@ class AllocationProfile extends Response {
AllocationProfile._fromJson(Map<String, dynamic> json)
: super._fromJson(json) {
members = List<ClassHeapStats>.from(
createServiceObject(json['members'], const ['ClassHeapStats']));
createServiceObject(json['members'], const ['ClassHeapStats']) ?? []);
memoryUsage =
createServiceObject(json['memoryUsage'], const ['MemoryUsage']);
dateLastAccumulatorReset = json['dateLastAccumulatorReset'] is String
Expand Down Expand Up @@ -2587,14 +2587,14 @@ class Class extends Obj {
superClass = createServiceObject(json['super'], const ['ClassRef']);
superType = createServiceObject(json['superType'], const ['InstanceRef']);
interfaces = List<InstanceRef>.from(
createServiceObject(json['interfaces'], const ['InstanceRef']));
createServiceObject(json['interfaces'], const ['InstanceRef']) ?? []);
mixin = createServiceObject(json['mixin'], const ['InstanceRef']);
fields = List<FieldRef>.from(
createServiceObject(json['fields'], const ['FieldRef']));
createServiceObject(json['fields'], const ['FieldRef']) ?? []);
functions = List<FuncRef>.from(
createServiceObject(json['functions'], const ['FuncRef']));
createServiceObject(json['functions'], const ['FuncRef']) ?? []);
subclasses = List<ClassRef>.from(
createServiceObject(json['subclasses'], const ['ClassRef']));
createServiceObject(json['subclasses'], const ['ClassRef']) ?? []);
}

@override
Expand Down Expand Up @@ -2692,7 +2692,7 @@ class ClassList extends Response {
});
ClassList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
classes = List<ClassRef>.from(
createServiceObject(json['classes'], const ['ClassRef']));
createServiceObject(json['classes'], const ['ClassRef']) ?? []);
}

@override
Expand Down Expand Up @@ -2843,7 +2843,7 @@ class Context extends Obj {
length = json['length'];
parent = createServiceObject(json['parent'], const ['Context']);
variables = List<ContextElement>.from(
createServiceObject(json['variables'], const ['ContextElement']));
createServiceObject(json['variables'], const ['ContextElement']) ?? []);
}

@override
Expand Down Expand Up @@ -2948,9 +2948,10 @@ class CpuSamples extends Response {
timeExtentMicros = json['timeExtentMicros'];
pid = json['pid'];
functions = List<ProfileFunction>.from(
createServiceObject(json['functions'], const ['ProfileFunction']));
createServiceObject(json['functions'], const ['ProfileFunction']) ??
[]);
samples = List<CpuSample>.from(
createServiceObject(json['samples'], const ['CpuSample']));
createServiceObject(json['samples'], const ['CpuSample']) ?? []);
}

@override
Expand Down Expand Up @@ -3630,7 +3631,8 @@ class FlagList extends Response {
@required this.flags,
});
FlagList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
flags = List<Flag>.from(createServiceObject(json['flags'], const ['Flag']));
flags = List<Flag>.from(
createServiceObject(json['flags'], const ['Flag']) ?? []);
}

@override
Expand Down Expand Up @@ -4459,9 +4461,9 @@ class Isolate extends Response {
pauseEvent = createServiceObject(json['pauseEvent'], const ['Event']);
rootLib = createServiceObject(json['rootLib'], const ['LibraryRef']);
libraries = List<LibraryRef>.from(
createServiceObject(json['libraries'], const ['LibraryRef']));
createServiceObject(json['libraries'], const ['LibraryRef']) ?? []);
breakpoints = List<Breakpoint>.from(
createServiceObject(json['breakpoints'], const ['Breakpoint']));
createServiceObject(json['breakpoints'], const ['Breakpoint']) ?? []);
error = createServiceObject(json['error'], const ['Error']);
exceptionPauseMode = json['exceptionPauseMode'];
extensionRPCs = json['extensionRPCs'] == null
Expand Down Expand Up @@ -4574,7 +4576,7 @@ class IsolateGroup extends Response {
number = json['number'];
name = json['name'];
isolates = List<IsolateRef>.from(
createServiceObject(json['isolates'], const ['IsolateRef']));
createServiceObject(json['isolates'], const ['IsolateRef']) ?? []);
}

@override
Expand Down Expand Up @@ -4613,7 +4615,8 @@ class InboundReferences extends Response {
InboundReferences._fromJson(Map<String, dynamic> json)
: super._fromJson(json) {
references = List<InboundReference>.from(
createServiceObject(json['references'], const ['InboundReference']));
createServiceObject(json['references'], const ['InboundReference']) ??
[]);
}

@override
Expand Down Expand Up @@ -4795,13 +4798,13 @@ class Library extends Obj {
dependencies = List<LibraryDependency>.from(
_createSpecificObject(json['dependencies'], LibraryDependency.parse));
scripts = List<ScriptRef>.from(
createServiceObject(json['scripts'], const ['ScriptRef']));
createServiceObject(json['scripts'], const ['ScriptRef']) ?? []);
variables = List<FieldRef>.from(
createServiceObject(json['variables'], const ['FieldRef']));
createServiceObject(json['variables'], const ['FieldRef']) ?? []);
functions = List<FuncRef>.from(
createServiceObject(json['functions'], const ['FuncRef']));
createServiceObject(json['functions'], const ['FuncRef']) ?? []);
classes = List<ClassRef>.from(
createServiceObject(json['classes'], const ['ClassRef']));
createServiceObject(json['classes'], const ['ClassRef']) ?? []);
}

@override
Expand Down Expand Up @@ -5458,7 +5461,7 @@ class RetainingPath extends Response {
length = json['length'];
gcRootType = json['gcRootType'];
elements = List<RetainingObject>.from(
createServiceObject(json['elements'], const ['RetainingObject']));
createServiceObject(json['elements'], const ['RetainingObject']) ?? []);
}

@override
Expand Down Expand Up @@ -5719,7 +5722,7 @@ class ScriptList extends Response {
});
ScriptList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
scripts = List<ScriptRef>.from(
createServiceObject(json['scripts'], const ['ScriptRef']));
createServiceObject(json['scripts'], const ['ScriptRef']) ?? []);
}

@override
Expand Down Expand Up @@ -5805,7 +5808,7 @@ class SourceReport extends Response {
ranges = List<SourceReportRange>.from(
_createSpecificObject(json['ranges'], SourceReportRange.parse));
scripts = List<ScriptRef>.from(
createServiceObject(json['scripts'], const ['ScriptRef']));
createServiceObject(json['scripts'], const ['ScriptRef']) ?? []);
}

@override
Expand Down Expand Up @@ -5965,8 +5968,8 @@ class Stack extends Response {
this.awaiterFrames,
});
Stack._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
frames =
List<Frame>.from(createServiceObject(json['frames'], const ['Frame']));
frames = List<Frame>.from(
createServiceObject(json['frames'], const ['Frame']) ?? []);
asyncCausalFrames = json['asyncCausalFrames'] == null
? null
: List<Frame>.from(
Expand All @@ -5976,7 +5979,7 @@ class Stack extends Response {
: List<Frame>.from(
createServiceObject(json['awaiterFrames'], const ['Frame']));
messages = List<Message>.from(
createServiceObject(json['messages'], const ['Message']));
createServiceObject(json['messages'], const ['Message']) ?? []);
}

@override
Expand Down Expand Up @@ -6037,7 +6040,8 @@ class Timeline extends Response {
});
Timeline._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
traceEvents = List<TimelineEvent>.from(
createServiceObject(json['traceEvents'], const ['TimelineEvent']));
createServiceObject(json['traceEvents'], const ['TimelineEvent']) ??
[]);
timeOriginMicros = json['timeOriginMicros'];
timeExtentMicros = json['timeExtentMicros'];
}
Expand Down Expand Up @@ -6202,7 +6206,7 @@ class TypeArguments extends Obj {
TypeArguments._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
name = json['name'];
types = List<InstanceRef>.from(
createServiceObject(json['types'], const ['InstanceRef']));
createServiceObject(json['types'], const ['InstanceRef']) ?? []);
}

@override
Expand Down Expand Up @@ -6416,9 +6420,10 @@ class VM extends Response {
pid = json['pid'];
startTime = json['startTime'];
isolates = List<IsolateRef>.from(
createServiceObject(json['isolates'], const ['IsolateRef']));
createServiceObject(json['isolates'], const ['IsolateRef']) ?? []);
isolateGroups = List<IsolateGroupRef>.from(
createServiceObject(json['isolateGroups'], const ['IsolateGroupRef']));
createServiceObject(json['isolateGroups'], const ['IsolateGroupRef']) ??
[]);
}

@override
Expand Down
3 changes: 1 addition & 2 deletions pkg/vm_service/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ name: vm_service
description: >-
A library to communicate with a service implementing the Dart VM
service protocol.
version: 2.1.2
version: 2.1.3

author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service

environment:
Expand Down
2 changes: 1 addition & 1 deletion pkg/vm_service/tool/dart/generate_dart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1465,7 +1465,7 @@ class Type extends Member {
"List<${fieldType.listTypeArg}>.from(createServiceObject($ref ?? json['samples'], $typesList));");
} else {
gen.writeln("${field.generatableName} = "
"List<${fieldType.listTypeArg}>.from(createServiceObject($ref, $typesList));");
"List<${fieldType.listTypeArg}>.from(createServiceObject($ref, $typesList) ?? []);");
}
}
}
Expand Down

0 comments on commit 7a911ce

Please sign in to comment.