Skip to content
This repository has been archived by the owner on Apr 29, 2024. It is now read-only.

Fix buffer overflow issue when converting strings from JNI to Dart #416

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions jni/lib/src/jni.dart
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,7 @@ extension ProtectedJniExtensions on Jni {
}

extension AdditionalEnvMethods on GlobalJniEnv {
/// Convenience method for converting a [JStringPtr]
/// to dart string.
/// Convenience method for converting a [JStringPtr] to dart string.
/// if [releaseOriginal] is specified, jstring passed will be deleted using
/// DeleteGlobalRef.
String toDartString(JStringPtr jstringPtr, {bool releaseOriginal = false}) {
Expand All @@ -342,7 +341,8 @@ extension AdditionalEnvMethods on GlobalJniEnv {
if (chars == nullptr) {
throw ArgumentError('Not a valid jstring pointer.');
}
final result = chars.cast<Utf16>().toDartString();
final length = GetStringLength(jstringPtr);
final result = chars.cast<Utf16>().toDartString(length: length);
ReleaseStringChars(jstringPtr, chars);
if (releaseOriginal) {
DeleteGlobalRef(jstringPtr);
Expand Down Expand Up @@ -377,7 +377,7 @@ extension StringMethodsForJni on String {

extension CharPtrMethodsForJni on Pointer<Char> {
/// Same as calling `cast<Utf8>` followed by `toDartString`.
String toDartString() {
return cast<Utf8>().toDartString();
String toDartString({int? length}) {
return cast<Utf8>().toDartString(length: length);
}
}
5 changes: 1 addition & 4 deletions jni/lib/src/lang/jstring.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,7 @@ class JString extends JObject {
/// after conversion and this object will be marked as released.
String toDartString({bool releaseOriginal = false}) {
ensureNotNull();
final length = Jni.env.GetStringLength(reference);
final chars = Jni.env.GetStringChars(reference, nullptr);
final result = chars.cast<Utf16>().toDartString(length: length);
HosseinYousefi marked this conversation as resolved.
Show resolved Hide resolved
Jni.env.ReleaseStringChars(reference, chars);
final result = Jni.env.toDartString(reference);
if (releaseOriginal) {
release();
}
Expand Down
20 changes: 17 additions & 3 deletions jni/test/global_env_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'dart:io';

import 'package:ffi/ffi.dart';
import 'package:jni/jni.dart';
import 'package:jni/src/jvalues.dart';
import 'package:test/test.dart';
Expand Down Expand Up @@ -118,18 +119,31 @@ void run({required TestRunnerCallback testRunner}) {
}));

testRunner(
"Convert back & forth between Dart & Java strings",
"Convert back & forth between Dart & Java strings (UTF-8)",
() => using((arena) {
const str = "ABCD EFGH";
// This is what asJString and asDartString do internally
final jstr = env.NewStringUTF(str.toNativeChars(arena));
final jchars = env.GetStringUTFChars(jstr, nullptr);
final dstr = jchars.toDartString();
final jlen = env.GetStringUTFLength(jstr);
final dstr = jchars.toDartString(length: jlen);
env.ReleaseStringUTFChars(jstr, jchars);
expect(str, equals(dstr));
env.DeleteGlobalRef(jstr);
}));

testRunner(
"Convert back & forth between Dart & Java strings (UTF-16)",
() => using((arena) {
const str = "ABCD EFGH";
final jstr = env.NewString(str.toNativeUtf16().cast(), str.length);
final jchars = env.GetStringChars(jstr, nullptr);
final jlen = env.GetStringLength(jstr);
final dstr = jchars.cast<Utf16>().toDartString(length: jlen);
env.ReleaseStringChars(jstr, jchars);
expect(str, equals(dstr));
env.DeleteGlobalRef(jstr);
}));

testRunner(
"Print something from Java",
() => using((arena) {
Expand Down
Loading