aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis Lozano <llozano@google.com>2012-07-20 00:23:33 +0000
committerLuis Lozano <llozano@google.com>2012-07-20 00:23:33 +0000
commit53eb268f6ebac6a0ffaebfc02b1944a0fc8bde9f (patch)
treea3d7150dcf663b80f9f442f2dafc530a01e1494c
parent62a11687b028b13949205d25e5737bbdd356ecf4 (diff)
Fixed last know issue with multithreading.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/google/gcc-4_6-mobile@189696 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--vtable-security/ChangeLog.vtable-security16
-rw-r--r--vtable-security/libstdc++-v3/libsupc++/vtv_malloc.cc2
-rw-r--r--vtable-security/libstdc++-v3/libsupc++/vtv_malloc.h1
-rw-r--r--vtable-security/libstdc++-v3/libsupc++/vtv_rts.cc30
-rw-r--r--vtable-security/libstdc++-v3/libsupc++/vtv_threaded_hash.cc31
5 files changed, 52 insertions, 28 deletions
diff --git a/vtable-security/ChangeLog.vtable-security b/vtable-security/ChangeLog.vtable-security
index 021afa50179..78adedb6c6a 100644
--- a/vtable-security/ChangeLog.vtable-security
+++ b/vtable-security/ChangeLog.vtable-security
@@ -1,3 +1,19 @@
+2012-07-19 Luis Lozano <llozano@google.com>
+
+ * libstdc++-v3/libsupc++/vtv_malloc.cc: moved VTV_assert to header
+ file
+ * libstdc++-v3/libsupc++/vtv_malloc.cc: ditto.
+ * libstdc++-v3/libsupc++/vtv_rts.cc (log_register_pairs): Changed to
+ use snprintf insted of sprintf for better protection.
+ (__VLTRegisterPair): Be consistent about the use of volatile variable
+ * libstdc++-v3/libsupc++/vtv_threaded_hash.cc: Added some assert around
+ the code to help with multi-threaded triaging.
+ (grow_table): make sure that the update of the "data" field is the last
+ thing we do. This is important for consistency in the multithreaded case.
+ (vlt_hash_insert): fix the code to depend only on one field that could have
+ a race condition (table->data). The code is supposed to handle the race
+ condition. This fixes the last know issue regarding multi-threading.
+
2012-07-18 Caroline Tice <cmtice@google.com>
* libstdc++-v3/libsupc++/vtv_rts.cc (__VLTRegisterPair): Add
diff --git a/vtable-security/libstdc++-v3/libsupc++/vtv_malloc.cc b/vtable-security/libstdc++-v3/libsupc++/vtv_malloc.cc
index d1a8647ae34..8053e52e81f 100644
--- a/vtable-security/libstdc++-v3/libsupc++/vtv_malloc.cc
+++ b/vtable-security/libstdc++-v3/libsupc++/vtv_malloc.cc
@@ -51,8 +51,6 @@ VTV_error (void)
abort();
}
-#define VTV_assert(EXPR) ((void)(!(EXPR) ? VTV_error() : (void) 0))
-
void
VTV_malloc_protect (void)
{
diff --git a/vtable-security/libstdc++-v3/libsupc++/vtv_malloc.h b/vtable-security/libstdc++-v3/libsupc++/vtv_malloc.h
index e5a33b1257c..ade1951ed6e 100644
--- a/vtable-security/libstdc++-v3/libsupc++/vtv_malloc.h
+++ b/vtable-security/libstdc++-v3/libsupc++/vtv_malloc.h
@@ -49,6 +49,7 @@ extern void VTV_malloc_protect (void);
extern void VTV_malloc_unprotect (void);
extern void VTV_error (void);
+#define VTV_assert(EXPR) ((void)(!(EXPR) ? VTV_error() : (void) 0))
/* Name of the section where we put general VTV variables for protection */
#define VTV_PROTECTED_VARS_SECTION ".data.rel.ro.vtable_vars"
diff --git a/vtable-security/libstdc++-v3/libsupc++/vtv_rts.cc b/vtable-security/libstdc++-v3/libsupc++/vtv_rts.cc
index 9d4955a89f2..d4a4fa579cb 100644
--- a/vtable-security/libstdc++-v3/libsupc++/vtv_rts.cc
+++ b/vtable-security/libstdc++-v3/libsupc++/vtv_rts.cc
@@ -55,7 +55,7 @@ static const int debug_register_pairs = 0;
They are explicitly unprotected and protected again by calls to VTV_unprotect
and VTV_protect */
-static FILE *log_file_fp VTV_PROTECTED_VAR = NULL;
+static FILE * log_file_fp VTV_PROTECTED_VAR = NULL;
struct mprotect_data {
int prot_mode;
@@ -196,16 +196,16 @@ log_register_pairs (FILE *fp, const char *format_string_dummy, int format_arg1,
us to write out the string that is missing the '\0' at it's
end. */
- sprintf (format_string, format_string_dummy, format_arg1, format_arg2);
+ snprintf (format_string, sizeof(format_string), format_string_dummy, format_arg1, format_arg2);
fprintf (fp, format_string, base_var_name, vtable_name, vtbl_ptr);
}
- /* For some reason, when the char * names get passed into these
- functions, they are missing the '\0' at the end; therefore we
- also pass in the length of the string and make sure, when writing
- out the names, that we only write out the correct number of
- bytes. */
+/* For some reason, when the char * names get passed into these
+ functions, they are missing the '\0' at the end; therefore we
+ also pass in the length of the string and make sure, when writing
+ out the names, that we only write out the correct number of
+ bytes. */
void
print_debugging_message (const char *format_string_dummy, int format_arg1,
int format_arg2,
@@ -228,26 +228,26 @@ print_debugging_message (const char *format_string_dummy, int format_arg1,
fprintf (stdout, format_string, str_arg1, str_arg2);
}
-/* TODO: Why is this returning anything */
+/* TODO: Why is this returning anything
+ remove unnecessary arguments */
void *
__VLTRegisterPair (void **data_pointer, void *test_value, int size_hint,
char *base_ptr_var_name, int len1, char *vtable_name,
int len2)
{
- struct vlt_hashtable **base_vtbl_row_ptr =
- (struct vlt_hashtable **) data_pointer;
vptr vtbl_ptr = (vptr) test_value;
-
- struct vlt_hashtable * volatile *tmp_volatile_ptr = base_vtbl_row_ptr;
+ struct vlt_hashtable * volatile *tmp_volatile_ptr =
+ (struct vlt_hashtable **) data_pointer;
static pthread_mutex_t map_var_mutex VTV_PROTECTED_VAR
= PTHREAD_MUTEX_INITIALIZER;
-
if ((*tmp_volatile_ptr) == NULL)
{
pthread_mutex_lock (&map_var_mutex);
+
if ((*tmp_volatile_ptr) == NULL)
*tmp_volatile_ptr = vlt_hash_init_table (size_hint);
+
pthread_mutex_unlock (&map_var_mutex);
}
@@ -261,11 +261,11 @@ __VLTRegisterPair (void **data_pointer, void *test_value, int size_hint,
log_register_pairs (log_file_fp, "Registering %%.%ds : %%.%ds (%%p)\n",
len1, len2,
base_ptr_var_name, vtable_name, vtbl_ptr);
- if (*base_vtbl_row_ptr == NULL)
+ if (*tmp_volatile_ptr == NULL)
fprintf (log_file_fp, " vtable map variable is NULL.\n");
}
- vlt_hash_insert (*base_vtbl_row_ptr, test_value);
+ vlt_hash_insert (*tmp_volatile_ptr, test_value);
return NULL;
}
diff --git a/vtable-security/libstdc++-v3/libsupc++/vtv_threaded_hash.cc b/vtable-security/libstdc++-v3/libsupc++/vtv_threaded_hash.cc
index c3e9fb15964..d05b4c9ed07 100644
--- a/vtable-security/libstdc++-v3/libsupc++/vtv_threaded_hash.cc
+++ b/vtable-security/libstdc++-v3/libsupc++/vtv_threaded_hash.cc
@@ -26,6 +26,7 @@
#include <math.h>
#include <stdio.h>
#include <string.h>
+#include <assert.h>
#include "vtv_threaded_hash.h"
#include "vtv_malloc.h"
@@ -128,7 +129,6 @@ grow_table (struct vlt_hashtable *table)
table->num_elts = rehash_elements (old_data, new_data, old_size,
new_power_size);
- table->data = new_data;
table->data_size = new_size;
table->power_of_2 = new_power_size;
@@ -150,8 +150,11 @@ grow_table (struct vlt_hashtable *table)
before the action is taken.
*/
- table->data[-1] = (vlt_hash_bucket *)
+ new_data[-1] = (vlt_hash_bucket *)
(0xffffffffUL >> (32 - new_power_size));
+ assert(new_data[-1] != 0);
+
+ table->data = new_data;
/* TODO: Need to 'my_free' each allocated bucket in old_data... */
my_free (old_data);
@@ -211,6 +214,7 @@ vlt_hash_init_table (int initial_size_hint)
new_table->data[0] = (vlt_hash_bucket *)
(0xffffffffUL >> (32 - initial_power));
+ assert(new_table->data[0] != 0);
/* The very first element/bucket is reserved for the hash mask, so make
the main table start at the second element. */
@@ -224,13 +228,15 @@ void
vlt_hash_insert (struct vlt_hashtable *table, void *value)
{
uint32_t hash = vlt_hash_pointer (value);
- uint32_t table_size = table->data_size;
+ struct vlt_hash_bucket **data = table->data;
/* Reminder: table->data[-1] contains the hash mask. See comments in
vlt_hash_init_table for details. */
- uint64_t hash_mask = (uint64_t) (table->data[-1]);
+ uint64_t hash_mask = (uint64_t) data[-1];
+ assert(hash_mask != 0);
+
uint32_t index = hash & (uint32_t) hash_mask;
- vlt_hash_bucket *first_bucket = table->data[index];
+ vlt_hash_bucket *first_bucket = data[index];
void *slot = vlt_bucket_find (first_bucket, value, NULL);
/* Only do the insert if the value is not already in the table. */
@@ -245,20 +251,21 @@ vlt_hash_insert (struct vlt_hashtable *table, void *value)
inserting the element, see if anybody else inserted the
element since the last check (before we grabbed the
lock.) */
- uint64_t hash_mask = (uint64_t) table->data[-1];
- uint32_t new_size = table->data_size;
+ uint64_t new_hash_mask = (uint64_t) table->data[-1];
uint32_t new_index;
bool should_insert;
- if (table_size == new_size)
+ if (data == table->data) // hash table was not resized
{
+ assert(new_hash_mask == hash_mask);
new_index = index;
should_insert = !vlt_bucket_find (table->data[new_index], value,
first_bucket);
}
else
{
- new_index = hash & (uint32_t) hash_mask;
+ assert(new_hash_mask != hash_mask);
+ new_index = hash & (uint32_t) new_hash_mask;
should_insert = !vlt_bucket_find (table->data[new_index], value,
NULL);
}
@@ -268,13 +275,15 @@ vlt_hash_insert (struct vlt_hashtable *table, void *value)
if (table->num_elts >= (REHASH_LIMIT * table->data_size))
{
grow_table (table);
- hash_mask = (uint64_t) table->data[-1];
- new_index = hash & (uint32_t) hash_mask;
+ new_hash_mask = (uint64_t) table->data[-1];
+ assert(new_hash_mask != 0);
+ new_index = hash & (uint32_t) new_hash_mask;
}
bucket_insert (&(table->data[new_index]), value);
table->num_elts++;
}
+
pthread_mutex_unlock (&(table->mutex));
}
}