mirror of
https://gitlab.gnome.org/GNOME/libsecret.git
synced 2024-12-22 12:48:51 +00:00
Valgrind integration, refactor build process
* Cleanup secure memory allocator for valgrind. * Bring valgrind headers in. * Add lots of suppressions for glib, gdbus, gcrypt * Fix up a bunch of bugs where things weren't getting freed * Add new 'make check-memory' target
This commit is contained in:
parent
e670fe5645
commit
4893c73c5b
8
.gitignore
vendored
8
.gitignore
vendored
@ -3,6 +3,7 @@
|
|||||||
*.la
|
*.la
|
||||||
*.lo
|
*.lo
|
||||||
*.pyc
|
*.pyc
|
||||||
|
*.gcov
|
||||||
*.gcno
|
*.gcno
|
||||||
*.gcda
|
*.gcda
|
||||||
.deps
|
.deps
|
||||||
@ -19,7 +20,6 @@ install-sh
|
|||||||
INSTALL
|
INSTALL
|
||||||
libtool
|
libtool
|
||||||
ltmain.sh
|
ltmain.sh
|
||||||
m4
|
|
||||||
Makefile
|
Makefile
|
||||||
Makefile.in
|
Makefile.in
|
||||||
Makefile.in.in
|
Makefile.in.in
|
||||||
@ -29,9 +29,12 @@ stamp*
|
|||||||
.project
|
.project
|
||||||
.cproject
|
.cproject
|
||||||
|
|
||||||
/coverage
|
/build/coverage
|
||||||
|
/build/m4
|
||||||
|
/build/valgrind-built.supp
|
||||||
|
|
||||||
/po/POTFILES
|
/po/POTFILES
|
||||||
|
/po/gsecret.pot
|
||||||
|
|
||||||
/egg/tests/test-dh
|
/egg/tests/test-dh
|
||||||
/egg/tests/test-hkdf
|
/egg/tests/test-hkdf
|
||||||
@ -40,3 +43,4 @@ stamp*
|
|||||||
/library/gsecret-dbus-generated.[ch]
|
/library/gsecret-dbus-generated.[ch]
|
||||||
/library/tests/test-*
|
/library/tests/test-*
|
||||||
!/library/tests/test-*.c
|
!/library/tests/test-*.c
|
||||||
|
|
||||||
|
18
Makefile.am
18
Makefile.am
@ -1,9 +1,9 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
## Process this file with automake to produce Makefile.in
|
||||||
include $(top_srcdir)/Makefile.decl
|
include $(top_srcdir)/Makefile.decl
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
ACLOCAL_AMFLAGS = -I build/m4 ${ACLOCAL_FLAGS}
|
||||||
|
|
||||||
SUBDIRS = po egg library
|
SUBDIRS = build po egg library
|
||||||
|
|
||||||
DISTCHECK_CONFIGURE_FLAGS = \
|
DISTCHECK_CONFIGURE_FLAGS = \
|
||||||
--enable-debug=yes \
|
--enable-debug=yes \
|
||||||
@ -23,13 +23,19 @@ dist-hook:
|
|||||||
echo A git clone is required to generate a ChangeLog >&2; \
|
echo A git clone is required to generate a ChangeLog >&2; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
check-memory:
|
||||||
|
@for subdir in $(SUBDIRS); do \
|
||||||
|
test -d $(builddir)/$$subdir/tests && \
|
||||||
|
make -C $(builddir)/$$subdir/tests check-memory; \
|
||||||
|
done
|
||||||
|
|
||||||
if WITH_COVERAGE
|
if WITH_COVERAGE
|
||||||
coverage:
|
coverage:
|
||||||
mkdir -p coverage
|
mkdir -p build/coverage
|
||||||
$(LCOV) --directory . --capture --output-file coverage/coverage.info
|
$(LCOV) --directory . --capture --output-file build/coverage/coverage.info
|
||||||
$(GENHTML) --output-directory coverage coverage/coverage.info
|
$(GENHTML) --output-directory coverage build/coverage/coverage.info
|
||||||
$(LCOV) --directory . --zerocounters
|
$(LCOV) --directory . --zerocounters
|
||||||
@echo "file://$(abs_top_builddir)/coverage/index.html"
|
@echo "file://$(abs_top_builddir)/build/coverage/index.html"
|
||||||
|
|
||||||
clear-coverage:
|
clear-coverage:
|
||||||
$(LCOV) --directory . --zerocounters
|
$(LCOV) --directory . --zerocounters
|
||||||
|
@ -1 +1,11 @@
|
|||||||
NULL =
|
NULL =
|
||||||
|
|
||||||
|
perform-memcheck: $(TEST_PROGS) $(top_builddir)/build/valgrind-built.supp
|
||||||
|
@for test in $(TEST_PROGS); do \
|
||||||
|
G_SLICE=always-malloc libtool --mode=execute \
|
||||||
|
valgrind --trace-children=no --gen-suppressions=all \
|
||||||
|
--suppressions=$(top_builddir)/build/valgrind-built.supp \
|
||||||
|
--leak-check=full --show-reachable=yes --num-callers=16 \
|
||||||
|
--quiet --error-exitcode=33 \
|
||||||
|
$(builddir)/$$test; \
|
||||||
|
done
|
||||||
|
19
build/Makefile.am
Normal file
19
build/Makefile.am
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
VALGRIND_CONTRIB = \
|
||||||
|
valgrind.h \
|
||||||
|
memcheck.h
|
||||||
|
|
||||||
|
SUPPRESSIONS = \
|
||||||
|
gcrypt.supp \
|
||||||
|
glib.supp \
|
||||||
|
pthread.supp \
|
||||||
|
unknown.supp
|
||||||
|
|
||||||
|
valgrind-built.supp: $(SUPPRESSIONS)
|
||||||
|
$(AM_V_GEN) cat $(SUPPRESSIONS) > $@
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
$(VALGRIND_CONTRIB) \
|
||||||
|
$(SUPPRESSIONS)
|
||||||
|
|
||||||
|
all-local: valgrind-built.supp
|
12
build/gcrypt.supp
Normal file
12
build/gcrypt.supp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
gpg_err_init
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:gpg_err_init
|
||||||
|
}
|
||||||
|
{
|
||||||
|
_gcry_module_add
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:_gcry_module_add
|
||||||
|
}
|
303
build/glib.supp
Normal file
303
build/glib.supp
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
{
|
||||||
|
g_type_register_static_1
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_type_register_static
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_type_register_fundamental
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_type_register_fundamental
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_type_init_with_debug_flags
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_type_init_with_debug_flags
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_type_class_ref_1
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:type_iface_vtable_base_init_Wm
|
||||||
|
...
|
||||||
|
fun:g_type_class_ref
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_type_class_ref_2
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:type_class_init_Wm
|
||||||
|
...
|
||||||
|
fun:g_type_class_ref
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_type_add_interface_static
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_type_add_interface_static
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_param_spec_internal
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_type_class_ref
|
||||||
|
fun:g_type_create_instance
|
||||||
|
fun:g_param_spec_internal
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_param_spec_enum
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_type_class_ref
|
||||||
|
fun:g_param_spec_enum
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_param_spec_flags
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_type_class_ref
|
||||||
|
fun:g_param_spec_flags
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_quark_from_static_string
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_quark_from_static_string
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_quark_from_string
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_quark_from_string
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_value_register_transform_func
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_value_register_transform_func
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_run_seed
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_rand_new_with_seed_array
|
||||||
|
fun:test_run_seed
|
||||||
|
...
|
||||||
|
fun:g_test_run_suite
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_test_init
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_rand_new_with_seed_array
|
||||||
|
...
|
||||||
|
fun:g_test_init
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_intern_static_string
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_intern_static_string
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_main_context_push_thread_default
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_queue_new
|
||||||
|
fun:g_main_context_push_thread_default
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_dbus_error_register_error
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_dbus_error_register_error
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_param_spec_pool_insert
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_param_spec_pool_insert
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_main_context_default
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_main_context_default
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_main_context_check
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_ptr_array_add
|
||||||
|
fun:g_main_context_check
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_test_run_suite
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_slist_copy
|
||||||
|
fun:g_test_run_suite_internal
|
||||||
|
fun:g_test_run_suite
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_dbus_interface_info_cache_build
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_dbus_interface_info_cache_build
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_cancellable_push_current
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:thread_memory_from_self
|
||||||
|
...
|
||||||
|
fun:g_cancellable_push_current
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_io_scheduler_push_job
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:init_scheduler
|
||||||
|
fun:g_once_impl
|
||||||
|
fun:g_io_scheduler_push_job
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_io_scheduler_push_job_2
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_system_thread_new
|
||||||
|
...
|
||||||
|
fun:g_io_scheduler_push_job
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_bus_get_sync__available_connections
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_hash_table_new
|
||||||
|
fun:initable_init
|
||||||
|
fun:g_initable_init
|
||||||
|
fun:g_bus_get_sync
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_socket_connection_factory_register_type
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_socket_connection_factory_register_type
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_test_add_vtable
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_test_add_vtable
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_mutex_lock
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_mutex_impl_new
|
||||||
|
fun:g_mutex_get_impl
|
||||||
|
fun:g_mutex_lock
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_thread_self
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_thread_self
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_rec_mutex_lock
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_rec_mutex_impl_new
|
||||||
|
fun:g_rec_mutex_get_impl
|
||||||
|
fun:g_rec_mutex_lock
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_case_run
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_malloc0
|
||||||
|
fun:test_case_run
|
||||||
|
...
|
||||||
|
fun:g_test_run_suite
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_get_charset
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_get_charset
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_test_run_suite__timer_new
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_timer_new
|
||||||
|
fun:test_case_run
|
||||||
|
...
|
||||||
|
fun:g_test_run_suite
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_test_run_suite__strconcat
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_strconcat
|
||||||
|
fun:test_case_run
|
||||||
|
...
|
||||||
|
fun:g_test_run_suite
|
||||||
|
fun:g_test_run
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_type_interface_add_prerequisite
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_type_interface_add_prerequisite
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_slist_copy
|
||||||
|
fun:g_test_run_suite_internal
|
||||||
|
...
|
||||||
|
fun:g_test_run_suite
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_set_prgname
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_set_prgname
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_test_run_suite__strconcat_2
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_strconcat
|
||||||
|
fun:g_test_run_suite_internal
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_test_run_suite__strdup
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_strdup
|
||||||
|
fun:g_test_run_suite_internal
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_private_get
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_private_get
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_private_set
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_private_set
|
||||||
|
}
|
||||||
|
{
|
||||||
|
g_static_mutex_get_mutex_impl
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_static_mutex_get_mutex_impl
|
||||||
|
}
|
7
build/pthread.supp
Normal file
7
build/pthread.supp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
_dl_allocate_tls
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:_dl_allocate_tls
|
||||||
|
fun:pthread_create*
|
||||||
|
}
|
346
build/unknown.supp
Normal file
346
build/unknown.supp
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
{
|
||||||
|
_g_dbus_shared_thread_ref
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:_g_dbus_shared_thread_ref
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:standard_malloc
|
||||||
|
fun:g_malloc
|
||||||
|
fun:g_slice_alloc
|
||||||
|
fun:g_slice_alloc0
|
||||||
|
fun:g_type_create_instance
|
||||||
|
fun:g_object_constructor
|
||||||
|
fun:g_object_newv
|
||||||
|
fun:g_object_new
|
||||||
|
fun:g_dbus_message_new
|
||||||
|
fun:g_dbus_message_new_from_blob
|
||||||
|
fun:_g_dbus_worker_do_read_cb
|
||||||
|
fun:g_simple_async_result_complete
|
||||||
|
fun:complete_in_idle_cb
|
||||||
|
fun:g_idle_dispatch
|
||||||
|
fun:g_main_dispatch
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
...
|
||||||
|
obj:/lib64/libgcrypt.so.11.7.0
|
||||||
|
fun:egg_dh_gen_pair
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:parse_value_from_blob
|
||||||
|
fun:g_dbus_message_new_from_blob
|
||||||
|
fun:_g_dbus_worker_do_read_cb
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_dbus_message_new
|
||||||
|
fun:g_dbus_message_new_from_blob
|
||||||
|
fun:_g_dbus_worker_do_read_cb
|
||||||
|
fun:g_simple_async_result_complete
|
||||||
|
fun:complete_in_idle_cb
|
||||||
|
fun:g_idle_dispatch
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_variant_get
|
||||||
|
fun:g_dbus_message_to_gerror
|
||||||
|
fun:decode_method_reply
|
||||||
|
fun:g_dbus_connection_call_done
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_dbus_message_set_header
|
||||||
|
fun:g_dbus_message_new_from_blob
|
||||||
|
fun:_g_dbus_worker_do_read_cb
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:standard_malloc
|
||||||
|
fun:g_malloc
|
||||||
|
fun:g_malloc_n
|
||||||
|
fun:g_main_context_iterate
|
||||||
|
fun:g_main_loop_run
|
||||||
|
fun:gdbus_shared_thread_func
|
||||||
|
fun:g_thread_proxy
|
||||||
|
fun:start_thread
|
||||||
|
fun:clone
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:standard_malloc
|
||||||
|
fun:g_malloc
|
||||||
|
fun:g_slice_alloc
|
||||||
|
fun:g_list_prepend
|
||||||
|
fun:g_queue_push_head
|
||||||
|
fun:g_main_context_push_thread_default
|
||||||
|
fun:gdbus_shared_thread_func
|
||||||
|
fun:g_thread_proxy
|
||||||
|
fun:start_thread
|
||||||
|
fun:clone
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:standard_malloc
|
||||||
|
fun:g_malloc
|
||||||
|
fun:g_slice_alloc
|
||||||
|
fun:g_slice_alloc0
|
||||||
|
fun:get_dispatch
|
||||||
|
fun:g_main_dispatch
|
||||||
|
fun:g_main_context_dispatch
|
||||||
|
fun:g_main_context_iterate
|
||||||
|
fun:g_main_loop_run
|
||||||
|
fun:g_dbus_connection_send_message_with_reply_sync
|
||||||
|
fun:g_dbus_connection_call_sync_internal
|
||||||
|
fun:g_dbus_connection_call_sync
|
||||||
|
fun:initable_init
|
||||||
|
fun:g_initable_init
|
||||||
|
fun:g_bus_get_sync
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:standard_malloc
|
||||||
|
fun:g_malloc
|
||||||
|
fun:g_slice_alloc
|
||||||
|
fun:g_slice_alloc0
|
||||||
|
fun:get_dispatch
|
||||||
|
fun:g_main_dispatch
|
||||||
|
fun:g_main_context_dispatch
|
||||||
|
fun:g_main_context_iterate
|
||||||
|
fun:g_main_loop_run
|
||||||
|
fun:gdbus_shared_thread_func
|
||||||
|
fun:g_thread_proxy
|
||||||
|
fun:start_thread
|
||||||
|
fun:clone
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:standard_malloc
|
||||||
|
fun:g_malloc
|
||||||
|
fun:g_malloc_n
|
||||||
|
fun:g_main_context_iterate
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:realloc
|
||||||
|
fun:standard_realloc
|
||||||
|
fun:g_realloc
|
||||||
|
fun:_g_dbus_worker_do_read_unlocked
|
||||||
|
fun:_g_dbus_worker_do_initial_read
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:_g_socket_output_stream_new
|
||||||
|
fun:g_socket_connection_get_output_stream
|
||||||
|
fun:g_io_stream_get_output_stream
|
||||||
|
fun:_g_dbus_auth_run_client
|
||||||
|
}
|
||||||
|
{
|
||||||
|
_g_dbus_worker_do_initial_read
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:_g_dbus_worker_do_read_unlocked
|
||||||
|
fun:_g_dbus_worker_do_initial_read
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_unix_socket_address_new_with_type
|
||||||
|
fun:g_dbus_address_connect
|
||||||
|
fun:g_dbus_address_try_connect_one
|
||||||
|
fun:g_dbus_address_get_stream_sync
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:_g_socket_input_stream_new
|
||||||
|
fun:g_socket_connection_get_input_stream
|
||||||
|
fun:g_io_stream_get_input_stream
|
||||||
|
fun:_g_dbus_auth_run_client
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:_g_dbus_worker_close
|
||||||
|
fun:_g_dbus_worker_stop
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_simple_async_result_complete_in_idle
|
||||||
|
fun:_g_socket_read_with_control_messages_ready
|
||||||
|
fun:_g_socket_read_with_control_messages
|
||||||
|
fun:_g_dbus_worker_do_read_unlocked
|
||||||
|
fun:_g_dbus_worker_do_read_cb
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_source_new
|
||||||
|
fun:g_idle_source_new
|
||||||
|
fun:g_simple_async_result_complete_in_idle
|
||||||
|
fun:g_socket_connection_close_async
|
||||||
|
fun:g_io_stream_close_async
|
||||||
|
...
|
||||||
|
fun:gdbus_shared_thread_func
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_simple_async_result_new
|
||||||
|
fun:g_socket_connection_close_async
|
||||||
|
fun:g_io_stream_close_async
|
||||||
|
fun:maybe_write_next_message
|
||||||
|
fun:write_message_in_idle_cb
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_socket_connection_factory_create_connection
|
||||||
|
...
|
||||||
|
fun:initable_init
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_socket_client_connect
|
||||||
|
fun:g_dbus_address_connect
|
||||||
|
fun:g_dbus_address_try_connect_one
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:_g_dbus_worker_new
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:_g_socket_read_with_control_messages
|
||||||
|
fun:_g_dbus_worker_do_read_unlocked
|
||||||
|
fun:_g_dbus_worker_do_read_cb
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_socket_receive_message
|
||||||
|
fun:_g_socket_read_with_control_messages_ready
|
||||||
|
fun:_g_socket_read_with_control_messages
|
||||||
|
fun:_g_dbus_worker_do_read_unlocked
|
||||||
|
fun:_g_dbus_worker_do_read_cb
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:maybe_write_next_message
|
||||||
|
...
|
||||||
|
fun:gdbus_shared_thread_func
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:remove_match_rule
|
||||||
|
fun:unsubscribe_id_internal
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_object_new
|
||||||
|
fun:get_uninitialized_connection
|
||||||
|
fun:g_bus_get_sync
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_dbus_connection_signal_subscribe
|
||||||
|
fun:async_initable_init_first
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_dbus_connection_send_message_with_reply_unlocked
|
||||||
|
fun:g_dbus_connection_send_message_with_reply
|
||||||
|
fun:g_dbus_connection_send_message_with_reply_sync
|
||||||
|
fun:g_dbus_connection_call_sync_internal
|
||||||
|
fun:g_dbus_connection_call_sync
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:_g_dbus_auth_new
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:_g_dbus_auth_run_client
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:_g_dbus_auth_init
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_variant_dup_string
|
||||||
|
...
|
||||||
|
fun:g_variant_get
|
||||||
|
...
|
||||||
|
fun:g_initable_init
|
||||||
|
fun:g_bus_get_sync
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:g_main_context_push_thread_default
|
||||||
|
...
|
||||||
|
fun:gdbus_shared_thread_func
|
||||||
|
}
|
283
build/valgrind/memcheck.h
Normal file
283
build/valgrind/memcheck.h
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
Notice that the following BSD-style license applies to this one
|
||||||
|
file (memcheck.h) only. The rest of Valgrind is licensed under the
|
||||||
|
terms of the GNU General Public License, version 2, unless
|
||||||
|
otherwise indicated. See the COPYING file in the source
|
||||||
|
distribution for details.
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
This file is part of MemCheck, a heavyweight Valgrind tool for
|
||||||
|
detecting memory errors.
|
||||||
|
|
||||||
|
Copyright (C) 2000-2010 Julian Seward. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. The origin of this software must not be misrepresented; you must
|
||||||
|
not claim that you wrote the original software. If you use this
|
||||||
|
software in a product, an acknowledgment in the product
|
||||||
|
documentation would be appreciated but is not required.
|
||||||
|
|
||||||
|
3. Altered source versions must be plainly marked as such, and must
|
||||||
|
not be misrepresented as being the original software.
|
||||||
|
|
||||||
|
4. The name of the author may not be used to endorse or promote
|
||||||
|
products derived from this software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||||
|
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||||
|
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
Notice that the above BSD-style license applies to this one file
|
||||||
|
(memcheck.h) only. The entire rest of Valgrind is licensed under
|
||||||
|
the terms of the GNU General Public License, version 2. See the
|
||||||
|
COPYING file in the source distribution for details.
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __MEMCHECK_H
|
||||||
|
#define __MEMCHECK_H
|
||||||
|
|
||||||
|
|
||||||
|
/* This file is for inclusion into client (your!) code.
|
||||||
|
|
||||||
|
You can use these macros to manipulate and query memory permissions
|
||||||
|
inside your own programs.
|
||||||
|
|
||||||
|
See comment near the top of valgrind.h on how to use them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "valgrind.h"
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# define VG_UNUSED __attribute__((unused))
|
||||||
|
#else
|
||||||
|
# define VG_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
|
||||||
|
This enum comprises an ABI exported by Valgrind to programs
|
||||||
|
which use client requests. DO NOT CHANGE THE ORDER OF THESE
|
||||||
|
ENTRIES, NOR DELETE ANY -- add new ones at the end. */
|
||||||
|
typedef
|
||||||
|
enum {
|
||||||
|
VG_USERREQ__MAKE_MEM_NOACCESS = VG_USERREQ_TOOL_BASE('M','C'),
|
||||||
|
VG_USERREQ__MAKE_MEM_UNDEFINED,
|
||||||
|
VG_USERREQ__MAKE_MEM_DEFINED,
|
||||||
|
VG_USERREQ__DISCARD,
|
||||||
|
VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,
|
||||||
|
VG_USERREQ__CHECK_MEM_IS_DEFINED,
|
||||||
|
VG_USERREQ__DO_LEAK_CHECK,
|
||||||
|
VG_USERREQ__COUNT_LEAKS,
|
||||||
|
|
||||||
|
VG_USERREQ__GET_VBITS,
|
||||||
|
VG_USERREQ__SET_VBITS,
|
||||||
|
|
||||||
|
VG_USERREQ__CREATE_BLOCK,
|
||||||
|
|
||||||
|
VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE,
|
||||||
|
|
||||||
|
/* Not next to VG_USERREQ__COUNT_LEAKS because it was added later. */
|
||||||
|
VG_USERREQ__COUNT_LEAK_BLOCKS,
|
||||||
|
|
||||||
|
/* This is just for memcheck's internal use - don't use it */
|
||||||
|
_VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR
|
||||||
|
= VG_USERREQ_TOOL_BASE('M','C') + 256
|
||||||
|
} Vg_MemCheckClientRequest;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Client-code macros to manipulate the state of memory. */
|
||||||
|
|
||||||
|
/* Mark memory at _qzz_addr as unaddressable for _qzz_len bytes. */
|
||||||
|
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr,_qzz_len) \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
|
||||||
|
VG_USERREQ__MAKE_MEM_NOACCESS, \
|
||||||
|
(_qzz_addr), (_qzz_len), 0, 0, 0)
|
||||||
|
|
||||||
|
/* Similarly, mark memory at _qzz_addr as addressable but undefined
|
||||||
|
for _qzz_len bytes. */
|
||||||
|
#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr,_qzz_len) \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
|
||||||
|
VG_USERREQ__MAKE_MEM_UNDEFINED, \
|
||||||
|
(_qzz_addr), (_qzz_len), 0, 0, 0)
|
||||||
|
|
||||||
|
/* Similarly, mark memory at _qzz_addr as addressable and defined
|
||||||
|
for _qzz_len bytes. */
|
||||||
|
#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr,_qzz_len) \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
|
||||||
|
VG_USERREQ__MAKE_MEM_DEFINED, \
|
||||||
|
(_qzz_addr), (_qzz_len), 0, 0, 0)
|
||||||
|
|
||||||
|
/* Similar to VALGRIND_MAKE_MEM_DEFINED except that addressability is
|
||||||
|
not altered: bytes which are addressable are marked as defined,
|
||||||
|
but those which are not addressable are left unchanged. */
|
||||||
|
#define VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(_qzz_addr,_qzz_len) \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
|
||||||
|
VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE, \
|
||||||
|
(_qzz_addr), (_qzz_len), 0, 0, 0)
|
||||||
|
|
||||||
|
/* Create a block-description handle. The description is an ascii
|
||||||
|
string which is included in any messages pertaining to addresses
|
||||||
|
within the specified memory range. Has no other effect on the
|
||||||
|
properties of the memory range. */
|
||||||
|
#define VALGRIND_CREATE_BLOCK(_qzz_addr,_qzz_len, _qzz_desc) \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
|
||||||
|
VG_USERREQ__CREATE_BLOCK, \
|
||||||
|
(_qzz_addr), (_qzz_len), (_qzz_desc), \
|
||||||
|
0, 0)
|
||||||
|
|
||||||
|
/* Discard a block-description-handle. Returns 1 for an
|
||||||
|
invalid handle, 0 for a valid handle. */
|
||||||
|
#define VALGRIND_DISCARD(_qzz_blkindex) \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
|
||||||
|
VG_USERREQ__DISCARD, \
|
||||||
|
0, (_qzz_blkindex), 0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
|
/* Client-code macros to check the state of memory. */
|
||||||
|
|
||||||
|
/* Check that memory at _qzz_addr is addressable for _qzz_len bytes.
|
||||||
|
If suitable addressibility is not established, Valgrind prints an
|
||||||
|
error message and returns the address of the first offending byte.
|
||||||
|
Otherwise it returns zero. */
|
||||||
|
#define VALGRIND_CHECK_MEM_IS_ADDRESSABLE(_qzz_addr,_qzz_len) \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
|
||||||
|
VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE, \
|
||||||
|
(_qzz_addr), (_qzz_len), 0, 0, 0)
|
||||||
|
|
||||||
|
/* Check that memory at _qzz_addr is addressable and defined for
|
||||||
|
_qzz_len bytes. If suitable addressibility and definedness are not
|
||||||
|
established, Valgrind prints an error message and returns the
|
||||||
|
address of the first offending byte. Otherwise it returns zero. */
|
||||||
|
#define VALGRIND_CHECK_MEM_IS_DEFINED(_qzz_addr,_qzz_len) \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
|
||||||
|
VG_USERREQ__CHECK_MEM_IS_DEFINED, \
|
||||||
|
(_qzz_addr), (_qzz_len), 0, 0, 0)
|
||||||
|
|
||||||
|
/* Use this macro to force the definedness and addressibility of an
|
||||||
|
lvalue to be checked. If suitable addressibility and definedness
|
||||||
|
are not established, Valgrind prints an error message and returns
|
||||||
|
the address of the first offending byte. Otherwise it returns
|
||||||
|
zero. */
|
||||||
|
#define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) \
|
||||||
|
VALGRIND_CHECK_MEM_IS_DEFINED( \
|
||||||
|
(volatile unsigned char *)&(__lvalue), \
|
||||||
|
(unsigned long)(sizeof (__lvalue)))
|
||||||
|
|
||||||
|
|
||||||
|
/* Do a full memory leak check (like --leak-check=full) mid-execution. */
|
||||||
|
#define VALGRIND_DO_LEAK_CHECK \
|
||||||
|
{unsigned long _qzz_res VG_UNUSED; \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
|
||||||
|
VG_USERREQ__DO_LEAK_CHECK, \
|
||||||
|
0, 0, 0, 0, 0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do a summary memory leak check (like --leak-check=summary) mid-execution. */
|
||||||
|
#define VALGRIND_DO_QUICK_LEAK_CHECK \
|
||||||
|
{unsigned long _qzz_res; \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
|
||||||
|
VG_USERREQ__DO_LEAK_CHECK, \
|
||||||
|
1, 0, 0, 0, 0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return number of leaked, dubious, reachable and suppressed bytes found by
|
||||||
|
all previous leak checks. They must be lvalues. */
|
||||||
|
#define VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed) \
|
||||||
|
/* For safety on 64-bit platforms we assign the results to private
|
||||||
|
unsigned long variables, then assign these to the lvalues the user
|
||||||
|
specified, which works no matter what type 'leaked', 'dubious', etc
|
||||||
|
are. We also initialise '_qzz_leaked', etc because
|
||||||
|
VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as
|
||||||
|
defined. */ \
|
||||||
|
{unsigned long _qzz_res; \
|
||||||
|
unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \
|
||||||
|
unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
|
||||||
|
VG_USERREQ__COUNT_LEAKS, \
|
||||||
|
&_qzz_leaked, &_qzz_dubious, \
|
||||||
|
&_qzz_reachable, &_qzz_suppressed, 0); \
|
||||||
|
leaked = _qzz_leaked; \
|
||||||
|
dubious = _qzz_dubious; \
|
||||||
|
reachable = _qzz_reachable; \
|
||||||
|
suppressed = _qzz_suppressed; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return number of leaked, dubious, reachable and suppressed bytes found by
|
||||||
|
all previous leak checks. They must be lvalues. */
|
||||||
|
#define VALGRIND_COUNT_LEAK_BLOCKS(leaked, dubious, reachable, suppressed) \
|
||||||
|
/* For safety on 64-bit platforms we assign the results to private
|
||||||
|
unsigned long variables, then assign these to the lvalues the user
|
||||||
|
specified, which works no matter what type 'leaked', 'dubious', etc
|
||||||
|
are. We also initialise '_qzz_leaked', etc because
|
||||||
|
VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as
|
||||||
|
defined. */ \
|
||||||
|
{unsigned long _qzz_res; \
|
||||||
|
unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \
|
||||||
|
unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
|
||||||
|
VG_USERREQ__COUNT_LEAK_BLOCKS, \
|
||||||
|
&_qzz_leaked, &_qzz_dubious, \
|
||||||
|
&_qzz_reachable, &_qzz_suppressed, 0); \
|
||||||
|
leaked = _qzz_leaked; \
|
||||||
|
dubious = _qzz_dubious; \
|
||||||
|
reachable = _qzz_reachable; \
|
||||||
|
suppressed = _qzz_suppressed; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get the validity data for addresses [zza..zza+zznbytes-1] and copy it
|
||||||
|
into the provided zzvbits array. Return values:
|
||||||
|
0 if not running on valgrind
|
||||||
|
1 success
|
||||||
|
2 [previously indicated unaligned arrays; these are now allowed]
|
||||||
|
3 if any parts of zzsrc/zzvbits are not addressable.
|
||||||
|
The metadata is not copied in cases 0, 2 or 3 so it should be
|
||||||
|
impossible to segfault your system by using this call.
|
||||||
|
*/
|
||||||
|
#define VALGRIND_GET_VBITS(zza,zzvbits,zznbytes) \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
|
||||||
|
VG_USERREQ__GET_VBITS, \
|
||||||
|
(char*)(zza), (char*)(zzvbits), \
|
||||||
|
(zznbytes), 0, 0)
|
||||||
|
|
||||||
|
/* Set the validity data for addresses [zza..zza+zznbytes-1], copying it
|
||||||
|
from the provided zzvbits array. Return values:
|
||||||
|
0 if not running on valgrind
|
||||||
|
1 success
|
||||||
|
2 [previously indicated unaligned arrays; these are now allowed]
|
||||||
|
3 if any parts of zza/zzvbits are not addressable.
|
||||||
|
The metadata is not copied in cases 0, 2 or 3 so it should be
|
||||||
|
impossible to segfault your system by using this call.
|
||||||
|
*/
|
||||||
|
#define VALGRIND_SET_VBITS(zza,zzvbits,zznbytes) \
|
||||||
|
VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
|
||||||
|
VG_USERREQ__SET_VBITS, \
|
||||||
|
(char*)(zza), (char*)(zzvbits), \
|
||||||
|
(zznbytes), 0, 0 )
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
5344
build/valgrind/valgrind.h
Normal file
5344
build/valgrind/valgrind.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
AC_PREREQ(2.65)
|
AC_PREREQ(2.65)
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([build/m4])
|
||||||
|
|
||||||
AC_INIT([gsecret],[0.1],[http://bugzilla.gnome.org/enter_bug.cgi?product=gsecret])
|
AC_INIT([gsecret],[0.1],[http://bugzilla.gnome.org/enter_bug.cgi?product=gsecret])
|
||||||
|
|
||||||
@ -192,6 +192,7 @@ AC_SUBST(GENHTML)
|
|||||||
|
|
||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
|
build/Makefile
|
||||||
egg/Makefile
|
egg/Makefile
|
||||||
egg/tests/Makefile
|
egg/tests/Makefile
|
||||||
po/Makefile.in
|
po/Makefile.in
|
||||||
|
@ -6,7 +6,9 @@ noinst_LTLIBRARIES = \
|
|||||||
EXTRA_DIST = egg-testing.h
|
EXTRA_DIST = egg-testing.h
|
||||||
|
|
||||||
INCLUDES = \
|
INCLUDES = \
|
||||||
-I$(top_srcdir)
|
-I$(top_srcdir) \
|
||||||
|
-I$(top_srcdir)/build \
|
||||||
|
-DWITH_VALGRIND
|
||||||
|
|
||||||
if WITH_GCRYPT
|
if WITH_GCRYPT
|
||||||
ENCRYPTION_SRCS = egg-dh.c egg-dh.h
|
ENCRYPTION_SRCS = egg-dh.c egg-dh.h
|
||||||
|
@ -337,8 +337,8 @@ egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
|
|||||||
#if DEBUG_DH_SECRET
|
#if DEBUG_DH_SECRET
|
||||||
g_printerr ("DH SECRET: ");
|
g_printerr ("DH SECRET: ");
|
||||||
gcry_mpi_dump (k);
|
gcry_mpi_dump (k);
|
||||||
gcry_mpi_release (k);
|
|
||||||
#endif
|
#endif
|
||||||
|
gcry_mpi_release (k);
|
||||||
|
|
||||||
*bytes = n_value;
|
*bytes = n_value;
|
||||||
|
|
||||||
|
@ -105,5 +105,6 @@ egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input,
|
|||||||
|
|
||||||
g_free (alloc);
|
g_free (alloc);
|
||||||
gcry_free (buffer);
|
gcry_free (buffer);
|
||||||
|
gcry_md_close (md2);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -46,12 +46,6 @@
|
|||||||
#include <valgrind/memcheck.h>
|
#include <valgrind/memcheck.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Use this to force all memory through malloc
|
|
||||||
* for use with valgrind and the like
|
|
||||||
*/
|
|
||||||
#define FORCE_FALLBACK_MEMORY 0
|
|
||||||
|
|
||||||
#define DEBUG_SECURE_MEMORY 0
|
#define DEBUG_SECURE_MEMORY 0
|
||||||
|
|
||||||
#if DEBUG_SECURE_MEMORY
|
#if DEBUG_SECURE_MEMORY
|
||||||
@ -404,12 +398,33 @@ sec_is_valid_word (Block *block, word_t *word)
|
|||||||
return (word >= block->words && word < block->words + block->n_words);
|
return (word >= block->words && word < block->words + block->n_words);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void*
|
static inline void
|
||||||
sec_clear_memory (void *memory, size_t from, size_t to)
|
sec_clear_undefined (void *memory,
|
||||||
|
size_t from,
|
||||||
|
size_t to)
|
||||||
{
|
{
|
||||||
|
char *ptr = memory;
|
||||||
ASSERT (from <= to);
|
ASSERT (from <= to);
|
||||||
memset ((char*)memory + from, 0, to - from);
|
#ifdef WITH_VALGRIND
|
||||||
return memory;
|
VALGRIND_MAKE_MEM_UNDEFINED (ptr + from, to - from);
|
||||||
|
#endif
|
||||||
|
memset (ptr + from, 0, to - from);
|
||||||
|
#ifdef WITH_VALGRIND
|
||||||
|
VALGRIND_MAKE_MEM_UNDEFINED (ptr + from, to - from);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static inline void
|
||||||
|
sec_clear_noaccess (void *memory, size_t from, size_t to)
|
||||||
|
{
|
||||||
|
char *ptr = memory;
|
||||||
|
ASSERT (from <= to);
|
||||||
|
#ifdef WITH_VALGRIND
|
||||||
|
VALGRIND_MAKE_MEM_UNDEFINED (ptr + from, to - from);
|
||||||
|
#endif
|
||||||
|
memset (ptr + from, 0, to - from);
|
||||||
|
#ifdef WITH_VALGRIND
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS (ptr + from, to - from);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static Cell*
|
static Cell*
|
||||||
@ -567,7 +582,7 @@ sec_free (Block *block, void *memory)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
sec_check_guards (cell);
|
sec_check_guards (cell);
|
||||||
sec_clear_memory (memory, 0, cell->requested);
|
sec_clear_noaccess (memory, 0, cell->requested);
|
||||||
|
|
||||||
sec_check_guards (cell);
|
sec_check_guards (cell);
|
||||||
ASSERT (cell->requested > 0);
|
ASSERT (cell->requested > 0);
|
||||||
@ -611,6 +626,34 @@ sec_free (Block *block, void *memory)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
memcpy_with_vbits (void *dest,
|
||||||
|
void *src,
|
||||||
|
size_t length)
|
||||||
|
{
|
||||||
|
#ifdef WITH_VALGRIND
|
||||||
|
int vbits_setup = 0;
|
||||||
|
void *vbits = NULL;
|
||||||
|
|
||||||
|
if (RUNNING_ON_VALGRIND) {
|
||||||
|
vbits = malloc (length);
|
||||||
|
if (vbits != NULL)
|
||||||
|
vbits_setup = VALGRIND_GET_VBITS (src, vbits, length);
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED (src, length);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memcpy (dest, src, length);
|
||||||
|
|
||||||
|
#ifdef WITH_VALGRIND
|
||||||
|
if (vbits_setup == 1) {
|
||||||
|
VALGRIND_SET_VBITS (dest, vbits, length);
|
||||||
|
VALGRIND_SET_VBITS (src, vbits, length);
|
||||||
|
}
|
||||||
|
free (vbits);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void*
|
static void*
|
||||||
sec_realloc (Block *block,
|
sec_realloc (Block *block,
|
||||||
const char *tag,
|
const char *tag,
|
||||||
@ -658,18 +701,14 @@ sec_realloc (Block *block,
|
|||||||
cell->requested = length;
|
cell->requested = length;
|
||||||
alloc = sec_cell_to_memory (cell);
|
alloc = sec_cell_to_memory (cell);
|
||||||
|
|
||||||
#ifdef WITH_VALGRIND
|
|
||||||
VALGRIND_MAKE_MEM_DEFINED (alloc, length);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Even though we may be reusing the same cell, that doesn't
|
* Even though we may be reusing the same cell, that doesn't
|
||||||
* mean that the allocation is shrinking. It could have shrunk
|
* mean that the allocation is shrinking. It could have shrunk
|
||||||
* and is now expanding back some.
|
* and is now expanding back some.
|
||||||
*/
|
*/
|
||||||
if (length < valid)
|
if (length < valid)
|
||||||
return sec_clear_memory (alloc, length, valid);
|
sec_clear_undefined (alloc, length, valid);
|
||||||
else
|
|
||||||
return alloc;
|
return alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,18 +741,14 @@ sec_realloc (Block *block,
|
|||||||
cell->requested = length;
|
cell->requested = length;
|
||||||
cell->tag = tag;
|
cell->tag = tag;
|
||||||
alloc = sec_cell_to_memory (cell);
|
alloc = sec_cell_to_memory (cell);
|
||||||
|
sec_clear_undefined (alloc, valid, length);
|
||||||
#ifdef WITH_VALGRIND
|
return alloc;
|
||||||
VALGRIND_MAKE_MEM_DEFINED (alloc, length);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sec_clear_memory (alloc, valid, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* That didn't work, try alloc/free */
|
/* That didn't work, try alloc/free */
|
||||||
alloc = sec_alloc (block, tag, length);
|
alloc = sec_alloc (block, tag, length);
|
||||||
if (alloc) {
|
if (alloc) {
|
||||||
memcpy (alloc, memory, valid);
|
memcpy_with_vbits (alloc, memory, valid);
|
||||||
sec_free (block, memory);
|
sec_free (block, memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -759,6 +794,9 @@ sec_validate (Block *block)
|
|||||||
Cell *cell;
|
Cell *cell;
|
||||||
word_t *word, *last;
|
word_t *word, *last;
|
||||||
|
|
||||||
|
if (RUNNING_ON_VALGRIND)
|
||||||
|
return;
|
||||||
|
|
||||||
word = block->words;
|
word = block->words;
|
||||||
last = word + block->n_words;
|
last = word + block->n_words;
|
||||||
|
|
||||||
@ -884,10 +922,9 @@ sec_block_create (size_t size,
|
|||||||
|
|
||||||
ASSERT (during_tag);
|
ASSERT (during_tag);
|
||||||
|
|
||||||
#if FORCE_FALLBACK_MEMORY
|
|
||||||
/* We can force all all memory to be malloced */
|
/* We can force all all memory to be malloced */
|
||||||
|
if (getenv ("SECMEM_FORCE_FALLBACK"))
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
|
||||||
|
|
||||||
block = pool_alloc ();
|
block = pool_alloc ();
|
||||||
if (!block)
|
if (!block)
|
||||||
@ -1103,7 +1140,7 @@ egg_secure_realloc_full (const char *tag,
|
|||||||
if (donew) {
|
if (donew) {
|
||||||
alloc = egg_secure_alloc_full (tag, length, flags);
|
alloc = egg_secure_alloc_full (tag, length, flags);
|
||||||
if (alloc) {
|
if (alloc) {
|
||||||
memcpy (alloc, memory, previous);
|
memcpy_with_vbits (alloc, memory, previous);
|
||||||
egg_secure_free_full (memory, flags);
|
egg_secure_free_full (memory, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1138,7 +1175,7 @@ egg_secure_free_full (void *memory, int flags)
|
|||||||
|
|
||||||
#ifdef WITH_VALGRIND
|
#ifdef WITH_VALGRIND
|
||||||
/* We like valgrind's warnings, so give it a first whack at checking for errors */
|
/* We like valgrind's warnings, so give it a first whack at checking for errors */
|
||||||
if (block != NULL || !(flags & GKR_SECURE_USE_FALLBACK))
|
if (block != NULL || !(flags & EGG_SECURE_USE_FALLBACK))
|
||||||
VALGRIND_FREELIKE_BLOCK (memory, sizeof (word_t));
|
VALGRIND_FREELIKE_BLOCK (memory, sizeof (word_t));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -56,6 +56,25 @@ hex_dump (const guchar *data, gsize n_data)
|
|||||||
return g_string_free (result, FALSE);
|
return g_string_free (result, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
egg_assertion_not_object (const char *domain,
|
||||||
|
const char *file,
|
||||||
|
int line,
|
||||||
|
const char *func,
|
||||||
|
const char *expr,
|
||||||
|
gpointer was_object)
|
||||||
|
{
|
||||||
|
gchar *s;
|
||||||
|
|
||||||
|
if (RUNNING_ON_VALGRIND)
|
||||||
|
return;
|
||||||
|
if (G_IS_OBJECT (was_object)) {
|
||||||
|
s = g_strdup_printf ("assertion failed: %s is still referenced", expr);
|
||||||
|
g_assertion_message (domain, file, line, func, s);
|
||||||
|
g_free (s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
egg_assertion_message_cmpmem (const char *domain,
|
egg_assertion_message_cmpmem (const char *domain,
|
||||||
const char *file,
|
const char *file,
|
||||||
|
@ -37,6 +37,16 @@
|
|||||||
G_STRFUNC, #a "[" #na"] " #cmp " " #b "[" #nb "]", \
|
G_STRFUNC, #a "[" #na"] " #cmp " " #b "[" #nb "]", \
|
||||||
__p1, __n1, #cmp, __p2, __n2); } while (0)
|
__p1, __n1, #cmp, __p2, __n2); } while (0)
|
||||||
|
|
||||||
|
#define egg_assert_not_object(p) \
|
||||||
|
(egg_assertion_not_object (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, #p, (p)))
|
||||||
|
|
||||||
|
void egg_assertion_not_object (const char *domain,
|
||||||
|
const char *file,
|
||||||
|
int line,
|
||||||
|
const char *func,
|
||||||
|
const char *expr,
|
||||||
|
gpointer was_object);
|
||||||
|
|
||||||
void egg_assertion_message_cmpmem (const char *domain, const char *file,
|
void egg_assertion_message_cmpmem (const char *domain, const char *file,
|
||||||
int line, const char *func,
|
int line, const char *func,
|
||||||
const char *expr, gconstpointer arg1,
|
const char *expr, gconstpointer arg1,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
include $(top_srcdir)/Makefile.decl
|
||||||
|
|
||||||
INCLUDES = \
|
INCLUDES = \
|
||||||
-I$(top_builddir) \
|
-I$(top_builddir) \
|
||||||
@ -24,4 +25,6 @@ test: $(TEST_PROGS)
|
|||||||
|
|
||||||
check-local: test
|
check-local: test
|
||||||
|
|
||||||
|
check-memory: perform-memcheck
|
||||||
|
|
||||||
all-local: $(check_PROGRAMS)
|
all-local: $(check_PROGRAMS)
|
||||||
|
@ -97,6 +97,8 @@ test_realloc_across (void)
|
|||||||
p2 = egg_secure_realloc_full ("tests", p, 16200, 0);
|
p2 = egg_secure_realloc_full ("tests", p, 16200, 0);
|
||||||
g_assert (p2 != NULL);
|
g_assert (p2 != NULL);
|
||||||
g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (p2, 16200));
|
g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (p2, 16200));
|
||||||
|
|
||||||
|
egg_secure_free (p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -212,6 +214,7 @@ test_multialloc (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_assert (memory->len == 0);
|
g_assert (memory->len == 0);
|
||||||
|
g_ptr_array_set_free_func (memory, egg_secure_free);
|
||||||
g_ptr_array_free (memory, TRUE);
|
g_ptr_array_free (memory, TRUE);
|
||||||
|
|
||||||
egg_secure_warnings = 1;
|
egg_secure_warnings = 1;
|
||||||
|
@ -27,3 +27,7 @@ test: $(TEST_PROGS)
|
|||||||
all-local: $(check_PROGRAMS)
|
all-local: $(check_PROGRAMS)
|
||||||
|
|
||||||
check-local: test
|
check-local: test
|
||||||
|
|
||||||
|
check-memory: perform-memcheck
|
||||||
|
|
||||||
|
.PHONY: check-memory
|
@ -58,6 +58,8 @@ teardown (Test *test,
|
|||||||
gconstpointer unused)
|
gconstpointer unused)
|
||||||
{
|
{
|
||||||
g_clear_object (&test->service);
|
g_clear_object (&test->service);
|
||||||
|
egg_assert_not_object (test->service);
|
||||||
|
|
||||||
g_clear_object (&test->connection);
|
g_clear_object (&test->connection);
|
||||||
|
|
||||||
g_assert (test->pid);
|
g_assert (test->pid);
|
||||||
@ -87,17 +89,17 @@ test_instance (void)
|
|||||||
g_assert (service1 == service2);
|
g_assert (service1 == service2);
|
||||||
|
|
||||||
g_object_unref (service1);
|
g_object_unref (service1);
|
||||||
g_assert (GSECRET_IS_SERVICE (service1));
|
g_assert (G_IS_OBJECT (service1));
|
||||||
|
|
||||||
g_object_unref (service2);
|
g_object_unref (service2);
|
||||||
g_assert (!GSECRET_IS_SERVICE (service2));
|
egg_assert_not_object (service2);
|
||||||
|
|
||||||
/* Services were unreffed, so this should create a new one */
|
/* Services were unreffed, so this should create a new one */
|
||||||
service3 = _gsecret_service_bare_instance (connection, MOCK_NAME);
|
service3 = _gsecret_service_bare_instance (connection, MOCK_NAME);
|
||||||
g_assert (GSECRET_IS_SERVICE (service3));
|
g_assert (GSECRET_IS_SERVICE (service3));
|
||||||
|
|
||||||
g_object_unref (service3);
|
g_object_unref (service3);
|
||||||
g_assert (!GSECRET_IS_SERVICE (service3));
|
egg_assert_not_object (service3);
|
||||||
|
|
||||||
g_object_unref (connection);
|
g_object_unref (connection);
|
||||||
}
|
}
|
||||||
|
@ -58,13 +58,18 @@ static void
|
|||||||
teardown (Test *test,
|
teardown (Test *test,
|
||||||
gconstpointer unused)
|
gconstpointer unused)
|
||||||
{
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
g_clear_object (&test->service);
|
g_clear_object (&test->service);
|
||||||
g_clear_object (&test->connection);
|
|
||||||
|
|
||||||
g_assert (test->pid);
|
g_assert (test->pid);
|
||||||
if (kill (test->pid, SIGTERM) < 0)
|
if (kill (test->pid, SIGTERM) < 0)
|
||||||
g_error ("kill() failed: %s", g_strerror (errno));
|
g_error ("kill() failed: %s", g_strerror (errno));
|
||||||
g_spawn_close_pid (test->pid);
|
g_spawn_close_pid (test->pid);
|
||||||
|
|
||||||
|
g_dbus_connection_flush_sync (test->connection, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_clear_object (&test->connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2011-11-05 21:48+0100\n"
|
"POT-Creation-Date: 2011-11-06 13:40+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -22,8 +22,8 @@ msgstr ""
|
|||||||
msgid "Received invalid secret from the secret storage"
|
msgid "Received invalid secret from the secret storage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../library/gsecret-service.c:344 ../library/gsecret-service.c:384
|
#: ../library/gsecret-service.c:354 ../library/gsecret-service.c:394
|
||||||
#: ../library/gsecret-service.c:544
|
#: ../library/gsecret-service.c:554
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Couldn't communicate with the secret storage"
|
msgid "Couldn't communicate with the secret storage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
Loading…
Reference in New Issue
Block a user