Skip to content

Commit

Permalink
fix(linux): Null pointer on clear
Browse files Browse the repository at this point in the history
  • Loading branch information
dnys1 committed Jul 25, 2024
1 parent 77a3e0b commit 9a1780b
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 44 deletions.
12 changes: 9 additions & 3 deletions packages/native/storage/ffigen.glib.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ language: c
output: lib/src/native/linux/glib.ffi.dart
headers:
entry-points:
- /usr/include/glib-2.0/glib.h
- /usr/include/glib-2.0/glib-object.h
- /usr/include/glib-2.0/gio/gio.h
- /opt/homebrew/Cellar/glib/2.80.3/include/glib-2.0/glib.h
- /opt/homebrew/Cellar/glib/2.80.3/include/glib-2.0/glib-object.h
- /opt/homebrew/Cellar/glib/2.80.3/include/glib-2.0/gio/gio.h
compiler-opts:
# Suppress nullability warnings on macOS
- "-Wno-nullability-completeness"
# Ignore warnings about availability macro
- "-Wno-availability"
preamble: |
// ignore_for_file: type=lint
// ignore_for_file: return_of_invalid_type
Expand All @@ -31,6 +36,7 @@ functions:
- g_hash_table_insert
- g_hash_table_destroy
- g_list_.*
- g_object_unref
- g_application_get_default
- g_application_get_application_id
- g_get_user_config_dir
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import 'package:native_storage/native_storage.dart';
import 'package:native_storage/src/local/local_storage.android.dart';
import 'package:native_storage/src/local/local_storage.linux.dart';
import 'package:native_storage/src/local/local_storage.windows.dart';
import 'package:native_storage/src/local/local_storage_darwin.dart';
import 'package:native_storage/src/native_storage_base.dart';
import 'package:native_storage/src/secure/secure_storage_platform.vm.dart';
import 'package:native_storage/src/util/rescope.dart';
Expand All @@ -18,16 +17,16 @@ abstract base class NativeLocalStoragePlatform extends NativeStorageBase
String? namespace,
String? scope,
}) {
if (Platform.isMacOS || Platform.isIOS) {
return LocalStoragePlatformDarwin(namespace: namespace, scope: scope);
}
// if (Platform.isMacOS || Platform.isIOS) {
// return LocalStoragePlatformDarwin(namespace: namespace, scope: scope);
// }
if (Platform.isAndroid) {
return LocalStoragePlatformAndroid(namespace: namespace, scope: scope);
}
if (Platform.isWindows) {
return LocalStorageWindows(namespace: namespace, scope: scope);
}
if (Platform.isLinux) {
if (Platform.isLinux || Platform.isMacOS) {
return LocalStorageLinux(namespace: namespace, scope: scope);
}
throw UnsupportedError('This platform is not yet supported.');
Expand Down
72 changes: 58 additions & 14 deletions packages/native/storage/lib/src/native/linux/glib.ffi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,20 @@ class Glib {
late final _g_list_pop_allocator =
_g_list_pop_allocatorPtr.asFunction<void Function()>();

void g_object_unref(
gpointer object,
) {
return _g_object_unref(
object,
);
}

late final _g_object_unrefPtr =
_lookup<ffi.NativeFunction<ffi.Void Function(gpointer)>>(
'g_object_unref');
late final _g_object_unref =
_g_object_unrefPtr.asFunction<void Function(gpointer)>();

ffi.Pointer<pkg_ffi.Utf8> g_application_get_application_id(
ffi.Pointer<_GApplication> application,
) {
Expand Down Expand Up @@ -1151,6 +1165,50 @@ class Glib {
gboolean Function(
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>,
ffi.Pointer<ffi.UnsignedInt>)>();

int g_list_store_find_with_equal_func_full(
ffi.Pointer<_GListStore> store,
gpointer item,
ffi.Pointer<
ffi.NativeFunction<
gboolean Function(
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, gpointer)>>
equal_func,
gpointer user_data,
ffi.Pointer<ffi.UnsignedInt> position,
) {
return _g_list_store_find_with_equal_func_full(
store,
item,
equal_func,
user_data,
position,
);
}

late final _g_list_store_find_with_equal_func_fullPtr = _lookup<
ffi.NativeFunction<
gboolean Function(
ffi.Pointer<_GListStore>,
gpointer,
ffi.Pointer<
ffi.NativeFunction<
gboolean Function(ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.Void>, gpointer)>>,
gpointer,
ffi.Pointer<ffi.UnsignedInt>)>>(
'g_list_store_find_with_equal_func_full');
late final _g_list_store_find_with_equal_func_full =
_g_list_store_find_with_equal_func_fullPtr.asFunction<
int Function(
ffi.Pointer<_GListStore>,
gpointer,
ffi.Pointer<
ffi.NativeFunction<
gboolean Function(ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.Void>, gpointer)>>,
gpointer,
ffi.Pointer<ffi.UnsignedInt>)>();
}

final class GError extends ffi.Struct {
Expand Down Expand Up @@ -1182,20 +1240,6 @@ typedef gboolean = gint;

final class _GAllocator extends ffi.Opaque {}

/// GObject:
///
/// The base object type.
///
/// All the fields in the `GObject` structure are private to the implementation
/// and should never be accessed directly.
///
/// Since GLib 2.72, all #GObjects are guaranteed to be aligned to at least the
/// alignment of the largest basic GLib type (typically this is #guint64 or
/// #gdouble). If you need larger alignment for an element in a #GObject, you
/// should allocate it on the heap (aligned), or arrange for your #GObject to be
/// appropriately padded. This guarantee applies to the #GObject (or derived)
/// struct, the #GObjectClass (or derived) struct, and any private data allocated
/// by G_ADD_PRIVATE().
final class GObject extends ffi.Struct {
external _GTypeInstance g_type_instance;

Expand Down
24 changes: 18 additions & 6 deletions packages/native/storage/lib/src/native/linux/linux.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import 'dart:ffi';
import 'dart:io';

import 'package:ffi/ffi.dart';
import 'package:path/path.dart' as p;
import 'package:native_storage/src/native/linux/glib.ffi.dart';
import 'package:native_storage/src/native/linux/libsecret.ffi.dart';
import 'package:native_storage/src/util/functional.dart';
import 'package:native_storage/src/util/native.dart';
import 'package:path/path.dart' as p;
import 'package:xdg_directories/xdg_directories.dart' as xdg;

final linux = LinuxCommon._();
Expand All @@ -15,18 +15,30 @@ final class LinuxCommon {
LinuxCommon._();

late final Glib glib = Glib(_glibDylib);
late final DynamicLibrary _glibDylib =
DynamicLibrary.open('libglib-2.0.so.0');
late final DynamicLibrary _glibDylib = searchDylib('glib', [
'libglib-2.0.so.0',
if (Platform.isMacOS) '/opt/homebrew/lib/libglib-2.0.dylib',
]);
late final gStrHashPointer =
_glibDylib.lookup<NativeFunction<UnsignedInt Function(Pointer<Void>)>>(
'g_str_hash');
late final gObjectUnrefPointer = _glibDylib
.lookup<NativeFunction<Void Function(gpointer)>>('g_object_unref');

late final Glib gio = Glib(DynamicLibrary.open('libgio-2.0.so.0'));
late final Glib gio = Glib(searchDylib('gio', [
'libgio-2.0.so.0',
if (Platform.isMacOS) '/opt/homebrew/lib/libgio-2.0.dylib',
]));

late final Libsecret libSecret =
Libsecret(DynamicLibrary.open('libsecret-1.so.0'));
late final Libsecret libSecret = Libsecret(searchDylib('libsecret', [
'libsecret-1.so.0',
if (Platform.isMacOS) '/opt/homebrew/lib/libsecret-1.dylib',
]));

late final String applicationId = lazy(() {
if (Platform.isMacOS) {
return p.basenameWithoutExtension(Platform.resolvedExecutable);
}
final exeName = p.basenameWithoutExtension(
File('/proc/self/exe').resolveSymbolicLinksSync());
try {
Expand Down
20 changes: 7 additions & 13 deletions packages/native/storage/lib/src/secure/secure_storage.linux.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import 'dart:ffi';
import 'dart:io';

import 'package:ffi/ffi.dart';
import 'package:native_storage/src/native/linux/glib.ffi.dart';
import 'package:native_storage/src/native/linux/libsecret.ffi.dart';
import 'package:native_storage/src/native/linux/linux.dart';
import 'package:native_storage/src/secure/secure_storage_exception.dart';
import 'package:native_storage/src/secure/secure_storage_platform.vm.dart';
import 'package:native_storage/src/util/functional.dart';

final class SecureStorageLinux extends NativeSecureStoragePlatform {
SecureStorageLinux({
Expand All @@ -18,18 +16,8 @@ final class SecureStorageLinux extends NativeSecureStoragePlatform {

final String? _namespace;

late final String _appName = lazy(() {
final application = linux.gio.g_application_get_default();
if (application == nullptr) {
return File('/proc/self/exe').resolveSymbolicLinksSync();
}
return linux.gio
.g_application_get_application_id(application)
.toDartString();
});

@override
late final String namespace = _namespace ?? _appName;
late final String namespace = _namespace ?? linux.applicationId;

late final String _prefix = scope == null ? '' : '$scope/';

Expand Down Expand Up @@ -90,6 +78,12 @@ final class SecureStorageLinux extends NativeSecureStoragePlatform {
if (secrets == nullptr) {
return;
}
arena.onReleaseAll(
() => linux.glib.g_list_free_full(
secrets,
linux.gObjectUnrefPointer,
),
);
final count = linux.glib.g_list_length(secrets);
for (var i = 0; i < count; i++) {
final secret =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ abstract base class NativeSecureStoragePlatform extends NativeStorageBase
String? namespace,
String? scope,
}) {
if (Platform.isLinux || Platform.isMacOS) {
return SecureStorageLinux(namespace: namespace, scope: scope);
}
if (Platform.isIOS || Platform.isMacOS) {
return SecureStorageDarwin(namespace: namespace, scope: scope);
}
if (Platform.isAndroid) {
return SecureStorageAndroid(namespace: namespace, scope: scope);
}
if (Platform.isLinux) {
return SecureStorageLinux(namespace: namespace, scope: scope);
}
if (Platform.isWindows) {
return SecureStorageWindows(namespace: namespace, scope: scope);
}
Expand Down
13 changes: 13 additions & 0 deletions packages/native/storage/lib/src/util/native.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,16 @@ DynamicLibrary? tryOpenDylib(String name) {
return null;
}
}

DynamicLibrary searchDylib(String name, List<String> paths) {
for (final path in paths) {
final dylib = tryOpenDylib(path);
if (dylib != null) {
return dylib;
}
}
throw Exception(
'Could not find dylib for "$name". Tried paths:\n'
'${paths.map((it) => '- $it').join('\n')}',
);
}

0 comments on commit 9a1780b

Please sign in to comment.