[cfe/ffi] Fix Struct invalid field crashes

Closes: https://github.com/dart-lang/sdk/issues/44985
Closes: https://github.com/dart-lang/sdk/issues/44986

TEST=tests/ffi(_2)/regress_4498[56]_test.dart

Change-Id: Ia21e6e41de14ef61843ce9bff0608a9235f08936
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/185860
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
Daco Harkes 2021-02-19 15:50:44 +00:00 committed by commit-bot@chromium.org
parent 229f59e669
commit c7ca192d6e
9 changed files with 109 additions and 1 deletions

View file

@ -3855,6 +3855,30 @@ Message _withArgumentsFfiFieldNoAnnotation(String name) {
arguments: {'name': name});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(String name)> templateFfiFieldNull = const Template<
Message Function(String name)>(
messageTemplate:
r"""Field '#name' cannot have type 'Null', it must be `int`, `double`, `Pointer`, or a subtype of `Struct`.""",
withArguments: _withArgumentsFfiFieldNull);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name)> codeFfiFieldNull =
const Code<Message Function(String name)>(
"FfiFieldNull",
);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsFfiFieldNull(String name) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(codeFfiFieldNull,
message:
"""Field '${name}' cannot have type 'Null', it must be `int`, `double`, `Pointer`, or a subtype of `Struct`.""",
arguments: {'name': name});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(String name)> templateFfiNotStatic = const Template<

View file

@ -62,6 +62,7 @@ export '../fasta/fasta_codes.dart'
templateFfiFieldCyclic,
templateFfiFieldInitializer,
templateFfiFieldNoAnnotation,
templateFfiFieldNull,
templateFfiNotStatic,
templateFfiStructGeneric,
templateFfiTypeInvalid,

View file

@ -327,6 +327,7 @@ FfiFieldAnnotation/analyzerCode: Fail
FfiFieldCyclic/analyzerCode: Fail
FfiFieldInitializer/analyzerCode: Fail
FfiFieldNoAnnotation/analyzerCode: Fail
FfiFieldNull/analyzerCode: Fail
FfiNotStatic/analyzerCode: Fail
FfiStructAnnotation/analyzerCode: Fail
FfiStructGeneric/analyzerCode: Fail

View file

@ -4225,6 +4225,11 @@ FfiTypeInvalid:
template: "Expected type '#type' to be a valid and instantiated subtype of 'NativeType'."
external: test/ffi_test.dart
FfiFieldNull:
# Used by dart:ffi
template: "Field '#name' cannot have type 'Null', it must be `int`, `double`, `Pointer`, or a subtype of `Struct`."
external: test/ffi_test.dart
FfiFieldAnnotation:
# Used by dart:ffi
template: "Field '#name' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields."

View file

@ -10,6 +10,7 @@ import 'package:front_end/src/api_unstable/vm.dart'
show
templateFfiEmptyStruct,
templateFfiFieldAnnotation,
templateFfiFieldNull,
templateFfiFieldCyclic,
templateFfiFieldNoAnnotation,
templateFfiTypeMismatch,
@ -227,6 +228,14 @@ class _FfiDefinitionTransformer extends FfiTransformer {
if (type is InvalidType) {
return false;
}
if (type is NullType) {
return false;
}
if (type is InterfaceType) {
if (type.classNode == structClass) {
return false;
}
}
return env.isSubtypeOf(type, InterfaceType(structClass, Nullability.legacy),
SubtypeCheckMode.ignoringNullabilities);
}
@ -279,7 +288,15 @@ class _FfiDefinitionTransformer extends FfiTransformer {
}
final nativeTypeAnnos = _getNativeTypeAnnotations(f).toList();
final type = _structFieldMemberType(f);
if (_isPointerType(type) || _isStructSubtype(type)) {
if (type is NullType) {
diagnosticReporter.report(
templateFfiFieldNull.withArguments(f.name.text),
f.fileOffset,
f.name.text.length,
f.fileUri);
// This class is invalid, but continue reporting other errors on it.
success = false;
} else if (_isPointerType(type) || _isStructSubtype(type)) {
if (nativeTypeAnnos.length != 0) {
diagnosticReporter.report(
templateFfiFieldNoAnnotation.withArguments(f.name.text),

View file

@ -0,0 +1,15 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "dart:ffi";
class S2 extends Struct {
external Pointer<Int8> notEmpty;
external Struct? s; //# 01: compile-time error
}
void main() {
S2? s2;
}

View file

@ -0,0 +1,15 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "dart:ffi";
class S2 extends Struct {
external Pointer<Int8> notEmpty;
external Null s; //# 01: compile-time error
}
void main() {
S2? s2;
}

View file

@ -0,0 +1,15 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "dart:ffi";
class S2 extends Struct {
Pointer<Int8> notEmpty;
Struct s; //# 01: compile-time error
}
void main() {
S2 s2;
}

View file

@ -0,0 +1,15 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "dart:ffi";
class S2 extends Struct {
Pointer<Int8> notEmpty;
Null s; //# 01: compile-time error
}
void main() {
S2 s2;
}