Check that receiver is not nullptr on Pointer extension methods. (#106)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1f15135..ea60851 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog
+## 1.1.1
+
+Adds a sanity check to `Pointer<Utf8>` and `Pointer<Utf16>` extension methods
+that receiver is not `nullptr`.
+
## 1.1.0
Adds the `arena` allocator.
diff --git a/lib/src/utf16.dart b/lib/src/utf16.dart
index f5bea5b..25c22ed 100644
--- a/lib/src/utf16.dart
+++ b/lib/src/utf16.dart
@@ -22,12 +22,9 @@
/// The UTF-16 code units of the strings are the non-zero code units up to
/// the first zero code unit.
int get length {
- final Pointer<Uint16> array = cast<Uint16>();
- int length = 0;
- while (array[length] != 0) {
- length++;
- }
- return length;
+ _ensureNotNullptr('length');
+ final codeUnits = cast<Uint16>();
+ return _length(codeUnits);
}
/// Converts this UTF-16 encoded string to a Dart string.
@@ -38,12 +35,17 @@
///
/// If [length] is provided, zero-termination is ignored and the result can
/// contain NUL characters.
+ ///
+ /// If [length] is not provided, the returned string is the string up til
+ /// but not including the first NUL character.
String toDartString({int? length}) {
+ _ensureNotNullptr('toDartString');
+ final codeUnits = cast<Uint16>();
if (length == null) {
- return _toUnknownLengthString(cast<Uint16>());
+ return _toUnknownLengthString(codeUnits);
} else {
RangeError.checkNotNegative(length, 'length');
- return _toKnownLengthString(cast<Uint16>(), length);
+ return _toKnownLengthString(codeUnits, length);
}
}
@@ -62,6 +64,21 @@
i++;
}
}
+
+ static int _length(Pointer<Uint16> codeUnits) {
+ var length = 0;
+ while (codeUnits[length] != 0) {
+ length++;
+ }
+ return length;
+ }
+
+ void _ensureNotNullptr(String operation) {
+ if (this == nullptr) {
+ throw UnsupportedError(
+ "Operation '$operation' not allowed on a 'nullptr'.");
+ }
+ }
}
/// Extension method for converting a [String] to a `Pointer<Utf16>`.
diff --git a/lib/src/utf8.dart b/lib/src/utf8.dart
index 04dd7a7..49c1cd3 100644
--- a/lib/src/utf8.dart
+++ b/lib/src/utf8.dart
@@ -22,12 +22,9 @@
/// The UTF-8 code units of the strings are the non-zero code units up to the
/// first zero code unit.
int get length {
- final Pointer<Uint8> array = cast<Uint8>();
- int length = 0;
- while (array[length] != 0) {
- length++;
- }
- return length;
+ _ensureNotNullptr('length');
+ final codeUnits = cast<Uint8>();
+ return _length(codeUnits);
}
/// Converts this UTF-8 encoded string to a Dart string.
@@ -38,13 +35,33 @@
///
/// If [length] is provided, zero-termination is ignored and the result can
/// contain NUL characters.
+ ///
+ /// If [length] is not provided, the returned string is the string up til
+ /// but not including the first NUL character.
String toDartString({int? length}) {
+ _ensureNotNullptr('toDartString');
+ final codeUnits = cast<Uint8>();
if (length != null) {
RangeError.checkNotNegative(length, 'length');
} else {
- length = this.length;
+ length = _length(codeUnits);
}
- return utf8.decode(cast<Uint8>().asTypedList(length));
+ return utf8.decode(codeUnits.asTypedList(length));
+ }
+
+ static int _length(Pointer<Uint8> codeUnits) {
+ var length = 0;
+ while (codeUnits[length] != 0) {
+ length++;
+ }
+ return length;
+ }
+
+ void _ensureNotNullptr(String operation) {
+ if (this == nullptr) {
+ throw UnsupportedError(
+ "Operation '$operation' not allowed on a 'nullptr'.");
+ }
}
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 11dd576..89e6180 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: ffi
-version: 1.1.0
+version: 1.1.1
homepage: https://github.com/dart-lang/ffi
description: Utilities for working with Foreign Function Interface (FFI) code.
diff --git a/test/utf16_test.dart b/test/utf16_test.dart
index 615056a..c962b46 100644
--- a/test/utf16_test.dart
+++ b/test/utf16_test.dart
@@ -60,7 +60,29 @@
});
test('fromUtf8 with negative length', () {
- final Pointer<Utf16> utf16 = Pointer.fromAddress(0);
+ final string = 'Hello';
+ final utf16 = string.toNativeUtf16();
expect(() => utf16.toDartString(length: -1), throwsRangeError);
+ calloc.free(utf16);
+ });
+
+ test('nullptr.toDartString()', () {
+ final Pointer<Utf16> utf16 = nullptr;
+ try {
+ utf16.toDartString();
+ } on UnsupportedError {
+ return;
+ }
+ fail('Expected an error.');
+ });
+
+ test('nullptr.length', () {
+ final Pointer<Utf16> utf16 = nullptr;
+ try {
+ utf16.length;
+ } on UnsupportedError {
+ return;
+ }
+ fail('Expected an error.');
});
}
diff --git a/test/utf8_test.dart b/test/utf8_test.dart
index 9c0486a..d3f2fee 100644
--- a/test/utf8_test.dart
+++ b/test/utf8_test.dart
@@ -96,4 +96,24 @@
expect(utf8Pointer.length, 5);
calloc.free(utf8Pointer);
});
+
+ test('nullptr.toDartString()', () {
+ final Pointer<Utf8> utf8 = nullptr;
+ try {
+ utf8.toDartString();
+ } on UnsupportedError {
+ return;
+ }
+ fail('Expected an error.');
+ });
+
+ test('nullptr.length', () {
+ final Pointer<Utf8> utf8 = nullptr;
+ try {
+ utf8.length;
+ } on UnsupportedError {
+ return;
+ }
+ fail('Expected an error.');
+ });
}