summaryrefslogtreecommitdiffstats
path: root/dbus
diff options
context:
space:
mode:
Diffstat (limited to 'dbus')
-rw-r--r--dbus/dbus-internals.c52
-rw-r--r--dbus/dbus-internals.h11
-rw-r--r--dbus/dbus-memory.c12
-rw-r--r--dbus/dbus-mempool.c25
-rw-r--r--dbus/dbus-message.c6
5 files changed, 103 insertions, 3 deletions
diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c
index 78a1b687..d51f5a97 100644
--- a/dbus/dbus-internals.c
+++ b/dbus/dbus-internals.c
@@ -391,4 +391,56 @@ _dbus_type_to_string (int type)
}
}
+#ifdef DBUS_BUILD_TESTS
+static int fail_alloc_counter = _DBUS_INT_MAX;
+/**
+ * Sets the number of allocations until we simulate a failed
+ * allocation. If set to 0, the next allocation to run
+ * fails; if set to 1, one succeeds then the next fails; etc.
+ * Set to _DBUS_INT_MAX to not fail anything.
+ *
+ * @param until_next_fail number of successful allocs before one fails
+ */
+void
+_dbus_set_fail_alloc_counter (int until_next_fail)
+{
+ fail_alloc_counter = until_next_fail;
+}
+
+/**
+ * Gets the number of successful allocs until we'll simulate
+ * a failed alloc.
+ *
+ * @returns current counter value
+ */
+int
+_dbus_get_fail_alloc_counter (void)
+{
+ return fail_alloc_counter;
+}
+
+/**
+ * Called when about to alloc some memory; if
+ * it returns #TRUE, then the allocation should
+ * fail. If it returns #FALSE, then the allocation
+ * should not fail.
+ *
+ * @returns #TRUE if this alloc should fail
+ */
+dbus_bool_t
+_dbus_decrement_fail_alloc_counter (void)
+{
+ if (fail_alloc_counter <= 0)
+ {
+ fail_alloc_counter = _DBUS_INT_MAX;
+ return TRUE;
+ }
+ else
+ {
+ fail_alloc_counter -= 1;
+ return FALSE;
+ }
+}
+#endif /* DBUS_BUILD_TESTS */
+
/** @} */
diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
index f0baf46b..29dd41ce 100644
--- a/dbus/dbus-internals.h
+++ b/dbus/dbus-internals.h
@@ -142,6 +142,17 @@ void _dbus_verbose_bytes_of_string (const DBusString *str,
const char* _dbus_type_to_string (int type);
+#ifdef DBUS_BUILD_TESTS
+/* Memory debugging */
+void _dbus_set_fail_alloc_counter (int until_next_fail);
+int _dbus_get_fail_alloc_counter (void);
+dbus_bool_t _dbus_decrement_fail_alloc_counter (void);
+#else
+#define _dbus_set_fail_alloc_counter(n)
+#define _dbus_get_fail_alloc_counter _DBUS_INT_MAX
+#define _dbus_decrement_fail_alloc_counter FALSE
+#endif /* !DBUS_BUILD_TESTS */
+
DBUS_END_DECLS;
#endif /* DBUS_INTERNALS_H */
diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c
index 52a563e9..357e8be6 100644
--- a/dbus/dbus-memory.c
+++ b/dbus/dbus-memory.c
@@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-memory.c D-BUS memory handling
*
- * Copyright (C) 2002 Red Hat Inc.
+ * Copyright (C) 2002, 2003 Red Hat Inc.
*
* Licensed under the Academic Free License version 1.2
*
@@ -22,6 +22,7 @@
*/
#include "dbus-memory.h"
+#include "dbus-internals.h"
#include <stdlib.h>
/**
@@ -82,6 +83,9 @@
void*
dbus_malloc (size_t bytes)
{
+ if (_dbus_decrement_fail_alloc_counter ())
+ return NULL;
+
if (bytes == 0) /* some system mallocs handle this, some don't */
return NULL;
else
@@ -100,6 +104,9 @@ dbus_malloc (size_t bytes)
void*
dbus_malloc0 (size_t bytes)
{
+ if (_dbus_decrement_fail_alloc_counter ())
+ return NULL;
+
if (bytes == 0)
return NULL;
else
@@ -120,6 +127,9 @@ void*
dbus_realloc (void *memory,
size_t bytes)
{
+ if (_dbus_decrement_fail_alloc_counter ())
+ return NULL;
+
if (bytes == 0) /* guarantee this is safe */
{
dbus_free (memory);
diff --git a/dbus/dbus-mempool.c b/dbus/dbus-mempool.c
index 05e3749b..3b233dd1 100644
--- a/dbus/dbus-mempool.c
+++ b/dbus/dbus-mempool.c
@@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-mempool.h Memory pools
*
- * Copyright (C) 2002 Red Hat, Inc.
+ * Copyright (C) 2002, 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
@@ -195,6 +195,9 @@ _dbus_mem_pool_free (DBusMemPool *pool)
void*
_dbus_mem_pool_alloc (DBusMemPool *pool)
{
+ if (_dbus_decrement_fail_alloc_counter ())
+ return NULL;
+
if (pool->free_elements)
{
DBusFreedElement *element = pool->free_elements;
@@ -216,7 +219,10 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
/* Need a new block */
DBusMemBlock *block;
int alloc_size;
-
+#ifdef DBUS_BUILD_TESTS
+ int saved_counter;
+#endif
+
if (pool->block_size <= _DBUS_INT_MAX / 4) /* avoid overflow */
{
/* use a larger block size for our next block */
@@ -226,12 +232,27 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
}
alloc_size = sizeof (DBusMemBlock) - ELEMENT_PADDING + pool->block_size;
+
+#ifdef DBUS_BUILD_TESTS
+ /* We save/restore the counter, so that memory pools won't
+ * cause a given function to have different number of
+ * allocations on different invocations. i.e. when testing
+ * we want consistent alloc patterns. So we skip our
+ * malloc here for purposes of failed alloc simulation.
+ */
+ saved_counter = _dbus_get_fail_alloc_counter ();
+ _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
+#endif
if (pool->zero_elements)
block = dbus_malloc0 (alloc_size);
else
block = dbus_malloc (alloc_size);
+#ifdef DBUS_BUILD_TESTS
+ _dbus_set_fail_alloc_counter (saved_counter);
+#endif
+
if (block == NULL)
return NULL;
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index 4287bd95..4ea2a631 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -2006,6 +2006,12 @@ decode_header_data (const DBusString *data,
* in. This function must always be called, even if no bytes were
* successfully read.
*
+ * @todo if we run out of memory in here, we offer no way for calling
+ * code to handle it, i.e. they can't re-run the message parsing
+ * attempt. Perhaps much of this code could be moved to pop_message()?
+ * But then that may need to distinguish NULL return for no messages
+ * from NULL return for errors.
+ *
* @param loader the loader.
* @param buffer the buffer.
* @param bytes_read number of bytes that were read into the buffer.