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:
Stef Walter 2011-11-06 13:41:21 +01:00 committed by Stef Walter
parent e670fe5645
commit 4893c73c5b
23 changed files with 6479 additions and 58 deletions

8
.gitignore vendored
View File

@ -3,6 +3,7 @@
*.la
*.lo
*.pyc
*.gcov
*.gcno
*.gcda
.deps
@ -19,7 +20,6 @@ install-sh
INSTALL
libtool
ltmain.sh
m4
Makefile
Makefile.in
Makefile.in.in
@ -29,9 +29,12 @@ stamp*
.project
.cproject
/coverage
/build/coverage
/build/m4
/build/valgrind-built.supp
/po/POTFILES
/po/gsecret.pot
/egg/tests/test-dh
/egg/tests/test-hkdf
@ -40,3 +43,4 @@ stamp*
/library/gsecret-dbus-generated.[ch]
/library/tests/test-*
!/library/tests/test-*.c

View File

@ -1,9 +1,9 @@
## Process this file with automake to produce Makefile.in
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 = \
--enable-debug=yes \
@ -23,13 +23,19 @@ dist-hook:
echo A git clone is required to generate a ChangeLog >&2; \
fi
check-memory:
@for subdir in $(SUBDIRS); do \
test -d $(builddir)/$$subdir/tests && \
make -C $(builddir)/$$subdir/tests check-memory; \
done
if WITH_COVERAGE
coverage:
mkdir -p coverage
$(LCOV) --directory . --capture --output-file coverage/coverage.info
$(GENHTML) --output-directory coverage coverage/coverage.info
mkdir -p build/coverage
$(LCOV) --directory . --capture --output-file build/coverage/coverage.info
$(GENHTML) --output-directory coverage build/coverage/coverage.info
$(LCOV) --directory . --zerocounters
@echo "file://$(abs_top_builddir)/coverage/index.html"
@echo "file://$(abs_top_builddir)/build/coverage/index.html"
clear-coverage:
$(LCOV) --directory . --zerocounters

View File

@ -1 +1,11 @@
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
View 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
View 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
View 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
View File

@ -0,0 +1,7 @@
{
_dl_allocate_tls
Memcheck:Leak
...
fun:_dl_allocate_tls
fun:pthread_create*
}

346
build/unknown.supp Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
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])
@ -192,6 +192,7 @@ AC_SUBST(GENHTML)
AC_CONFIG_FILES([
Makefile
build/Makefile
egg/Makefile
egg/tests/Makefile
po/Makefile.in

View File

@ -6,7 +6,9 @@ noinst_LTLIBRARIES = \
EXTRA_DIST = egg-testing.h
INCLUDES = \
-I$(top_srcdir)
-I$(top_srcdir) \
-I$(top_srcdir)/build \
-DWITH_VALGRIND
if WITH_GCRYPT
ENCRYPTION_SRCS = egg-dh.c egg-dh.h

View File

@ -337,8 +337,8 @@ egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
#if DEBUG_DH_SECRET
g_printerr ("DH SECRET: ");
gcry_mpi_dump (k);
gcry_mpi_release (k);
#endif
gcry_mpi_release (k);
*bytes = n_value;

View File

@ -105,5 +105,6 @@ egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input,
g_free (alloc);
gcry_free (buffer);
gcry_md_close (md2);
return TRUE;
}

View File

@ -46,12 +46,6 @@
#include <valgrind/memcheck.h>
#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
#if DEBUG_SECURE_MEMORY
@ -212,11 +206,11 @@ pool_alloc (void)
++pool->used;
ASSERT (unused_peek (&pool->unused));
item = unused_pop (&pool->unused);
#ifdef WITH_VALGRIND
VALGRIND_MEMPOOL_ALLOC (pool, item, sizeof (Item));
#endif
return memset (item, 0, sizeof (Item));
}
@ -246,20 +240,20 @@ pool_free (void* item)
/* No more meta cells used in this block, remove from list, destroy */
if (pool->used == 1) {
*at = pool->next;
#ifdef WITH_VALGRIND
VALGRIND_DESTROY_MEMPOOL (pool);
#endif
munmap (pool, pool->length);
return;
}
#ifdef WITH_VALGRIND
VALGRIND_MEMPOOL_FREE (pool, item);
VALGRIND_MAKE_MEM_UNDEFINED (item, sizeof (Item));
#endif
--pool->used;
memset (item, 0xCD, sizeof (Item));
unused_push (&pool->unused, item);
@ -404,12 +398,33 @@ sec_is_valid_word (Block *block, word_t *word)
return (word >= block->words && word < block->words + block->n_words);
}
static inline void*
sec_clear_memory (void *memory, size_t from, size_t to)
static inline void
sec_clear_undefined (void *memory,
size_t from,
size_t to)
{
char *ptr = memory;
ASSERT (from <= to);
memset ((char*)memory + from, 0, to - from);
return memory;
#ifdef WITH_VALGRIND
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*
@ -567,7 +582,7 @@ sec_free (Block *block, void *memory)
#endif
sec_check_guards (cell);
sec_clear_memory (memory, 0, cell->requested);
sec_clear_noaccess (memory, 0, cell->requested);
sec_check_guards (cell);
ASSERT (cell->requested > 0);
@ -611,6 +626,34 @@ sec_free (Block *block, void *memory)
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*
sec_realloc (Block *block,
const char *tag,
@ -658,19 +701,15 @@ sec_realloc (Block *block,
cell->requested = length;
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
* mean that the allocation is shrinking. It could have shrunk
* and is now expanding back some.
*/
if (length < valid)
return sec_clear_memory (alloc, length, valid);
else
return alloc;
sec_clear_undefined (alloc, length, valid);
return alloc;
}
/* Need braaaaaiiiiiinsss... */
@ -702,18 +741,14 @@ sec_realloc (Block *block,
cell->requested = length;
cell->tag = tag;
alloc = sec_cell_to_memory (cell);
#ifdef WITH_VALGRIND
VALGRIND_MAKE_MEM_DEFINED (alloc, length);
#endif
return sec_clear_memory (alloc, valid, length);
sec_clear_undefined (alloc, valid, length);
return alloc;
}
/* That didn't work, try alloc/free */
alloc = sec_alloc (block, tag, length);
if (alloc) {
memcpy (alloc, memory, valid);
memcpy_with_vbits (alloc, memory, valid);
sec_free (block, memory);
}
@ -758,7 +793,10 @@ sec_validate (Block *block)
{
Cell *cell;
word_t *word, *last;
if (RUNNING_ON_VALGRIND)
return;
word = block->words;
last = word + block->n_words;
@ -781,7 +819,7 @@ sec_validate (Block *block)
ASSERT (cell->prev->next == cell);
ASSERT (cell->requested <= (cell->n_words - 2) * sizeof (word_t));
/* An unused block */
/* An unused block */
} else {
ASSERT (cell->tag == NULL);
ASSERT (cell->next != NULL);
@ -884,11 +922,10 @@ sec_block_create (size_t size,
ASSERT (during_tag);
#if FORCE_FALLBACK_MEMORY
/* We can force all all memory to be malloced */
return NULL;
#endif
if (getenv ("SECMEM_FORCE_FALLBACK"))
return NULL;
block = pool_alloc ();
if (!block)
return NULL;
@ -1103,7 +1140,7 @@ egg_secure_realloc_full (const char *tag,
if (donew) {
alloc = egg_secure_alloc_full (tag, length, flags);
if (alloc) {
memcpy (alloc, memory, previous);
memcpy_with_vbits (alloc, memory, previous);
egg_secure_free_full (memory, flags);
}
}
@ -1138,7 +1175,7 @@ egg_secure_free_full (void *memory, int flags)
#ifdef WITH_VALGRIND
/* 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));
#endif

View File

@ -56,6 +56,25 @@ hex_dump (const guchar *data, gsize n_data)
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
egg_assertion_message_cmpmem (const char *domain,
const char *file,

View File

@ -37,6 +37,16 @@
G_STRFUNC, #a "[" #na"] " #cmp " " #b "[" #nb "]", \
__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,
int line, const char *func,
const char *expr, gconstpointer arg1,

View File

@ -1,3 +1,4 @@
include $(top_srcdir)/Makefile.decl
INCLUDES = \
-I$(top_builddir) \
@ -24,4 +25,6 @@ test: $(TEST_PROGS)
check-local: test
check-memory: perform-memcheck
all-local: $(check_PROGRAMS)

View File

@ -97,6 +97,8 @@ test_realloc_across (void)
p2 = egg_secure_realloc_full ("tests", p, 16200, 0);
g_assert (p2 != NULL);
g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (p2, 16200));
egg_secure_free (p2);
}
static void
@ -212,6 +214,7 @@ test_multialloc (void)
}
g_assert (memory->len == 0);
g_ptr_array_set_free_func (memory, egg_secure_free);
g_ptr_array_free (memory, TRUE);
egg_secure_warnings = 1;

View File

@ -26,4 +26,8 @@ test: $(TEST_PROGS)
all-local: $(check_PROGRAMS)
check-local: test
check-local: test
check-memory: perform-memcheck
.PHONY: check-memory

View File

@ -58,6 +58,8 @@ teardown (Test *test,
gconstpointer unused)
{
g_clear_object (&test->service);
egg_assert_not_object (test->service);
g_clear_object (&test->connection);
g_assert (test->pid);
@ -87,17 +89,17 @@ test_instance (void)
g_assert (service1 == service2);
g_object_unref (service1);
g_assert (GSECRET_IS_SERVICE (service1));
g_assert (G_IS_OBJECT (service1));
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 */
service3 = _gsecret_service_bare_instance (connection, MOCK_NAME);
g_assert (GSECRET_IS_SERVICE (service3));
g_object_unref (service3);
g_assert (!GSECRET_IS_SERVICE (service3));
egg_assert_not_object (service3);
g_object_unref (connection);
}

View File

@ -58,13 +58,18 @@ static void
teardown (Test *test,
gconstpointer unused)
{
GError *error = NULL;
g_clear_object (&test->service);
g_clear_object (&test->connection);
g_assert (test->pid);
if (kill (test->pid, SIGTERM) < 0)
g_error ("kill() failed: %s", g_strerror (errno));
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

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\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"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -22,8 +22,8 @@ msgstr ""
msgid "Received invalid secret from the secret storage"
msgstr ""
#: ../library/gsecret-service.c:344 ../library/gsecret-service.c:384
#: ../library/gsecret-service.c:544
#: ../library/gsecret-service.c:354 ../library/gsecret-service.c:394
#: ../library/gsecret-service.c:554
#, c-format
msgid "Couldn't communicate with the secret storage"
msgstr ""