From 26a49f96443cf2039834ea4793482021f68a4885 Mon Sep 17 00:00:00 2001 From: lmat Date: Wed, 11 Jun 2014 09:17:09 -0400 Subject: [PATCH 1/9] Implement GUID using boost's implementation Since we're maintaining a C api, the implementation is sometimes less than intuitive from either a C or C++ perspective. I am trying to use as much boost as possible while making all the guarantees that the C code makes. One function was declared deprecated because it "wasn't thread safe". This was straightforward to repair, and is no longer marked deprecated, and there are now two ways to convert GUID to String: passing your own character buffer, and having one returned to you that you need to free. --- src/libqof/qof/guid.cpp | 716 ++++++---------------------------------- src/libqof/qof/guid.h | 34 +- 2 files changed, 122 insertions(+), 628 deletions(-) diff --git a/src/libqof/qof/guid.cpp b/src/libqof/qof/guid.cpp index 235f04b268..72912d85fb 100644 --- a/src/libqof/qof/guid.cpp +++ b/src/libqof/qof/guid.cpp @@ -1,6 +1,7 @@ /********************************************************************\ * guid.c -- globally unique ID implementation * * Copyright (C) 2000 Dave Peticolas * + * Copyright (C) 2014 Aaron Laws * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -21,10 +22,8 @@ * * \********************************************************************/ -#ifdef __cplusplus extern "C" { -#endif #ifdef HAVE_CONFIG_H # include @@ -53,30 +52,16 @@ extern "C" #include "qof.h" #include "md5.h" -#ifdef __cplusplus } -#endif +#include +#include +#include +#include +#include -# ifndef P_tmpdir -# define P_tmpdir "/tmp" -# endif +using namespace std; -/* Constants *******************************************************/ -#define DEBUG_GUID 0 -#define BLOCKSIZE 4096 -#ifdef G_PLATFORM_WIN32 -/* Win32 has a smaller pool of random bits, but the displayed warning confuses - * really a lot of people. Hence, I think we'd better switch off this warning - * for this particular known case. */ -# define THRESHOLD 1500 -#else -# define THRESHOLD (2 * BLOCKSIZE) -#endif - - -/* Static global variables *****************************************/ -static gboolean guid_initialized = FALSE; -static struct md5_ctx guid_context; +typedef boost::uuids::uuid gg; /* This static indicates the debugging module that this .o belongs to. */ static QofLogModule log_module = QOF_MOD_ENGINE; @@ -101,12 +86,22 @@ gnc_value_get_guid (const GValue *value) return val; } - /* Memory management routines ***************************************/ + +GncGUID * +guid_new_ptr_return (void) +{ + return reinterpret_cast (new boost::uuids::uuid); +} + +/* Deprecated*/ GncGUID * guid_malloc (void) { - return g_slice_new(GncGUID); + /*We need to actually construct here (not just ::operator new (size_t) -- allocate) + because in guid_new, we assume that the object has already been constructed. + Note the boost UUID is a POD, so its constructor is trivial.*/ + return reinterpret_cast (new boost::uuids::uuid); } void @@ -114,425 +109,36 @@ guid_free (GncGUID *guid) { if (!guid) return; - - g_slice_free(GncGUID, guid); + delete reinterpret_cast (guid); } GncGUID * guid_copy (const GncGUID *guid) { - GncGUID *copy; - - g_return_val_if_fail(guid, NULL); - copy = guid_malloc(); - *copy = *guid; - return copy; + const boost::uuids::uuid * old {reinterpret_cast (guid)}; + boost::uuids::uuid * ret {new boost::uuids::uuid (*old)}; + return reinterpret_cast(ret); } +static GncGUID * nullguid {reinterpret_cast(new boost::uuids::uuid{0})}; + +/*It looks like we are expected to provide the same pointer every time from this function*/ const GncGUID * guid_null(void) { - static int null_inited = 0; - static GncGUID null_guid; - - if (!null_inited) - { - int i; - - for (i = 0; i < GUID_DATA_SIZE; i++) - null_guid.data[i] = '\0'; - - null_inited = 1; - } - - return &null_guid; + //static boost::uuids::nil_generator nil; + //boost::uuids::uuid * ret {new boost::uuids::uuid {0}}; + //return reinterpret_cast (ret); + return nullguid; } /* Function implementations ****************************************/ -/* This code is based on code in md5.c in GNU textutils. */ -static size_t -init_from_stream(FILE *stream, size_t max_size) -{ - char buffer[BLOCKSIZE + 72]; - size_t sum, block_size, total; - - ENTER(""); - - if (max_size <= 0) - { - LEAVE("max_size is 0 or less, skipping stream"); - return 0; - } - - total = 0; - - /* Iterate over file contents. */ - while (1) - { - /* We read the file in blocks of BLOCKSIZE bytes. One call of the - * computation function processes the whole buffer so that with the - * next round of the loop another block can be read. */ - size_t n; - sum = 0; - - if (max_size < BLOCKSIZE) - block_size = max_size; - else - block_size = BLOCKSIZE; - - /* Read block. Take care for partial reads. */ - do - { - n = fread (buffer + sum, 1, block_size - sum, stream); - - sum += n; - } - while (sum < block_size && n != 0); - - max_size -= sum; - - if (n == 0 && ferror (stream)) - { - LEAVE("error while reading stream"); - return total; - } - - /* If end of file or max_size is reached, end the loop. */ - if ((n == 0) || (max_size == 0)) - break; - - /* Process buffer with BLOCKSIZE bytes. Note that - * BLOCKSIZE % 64 == 0 */ - md5_process_block (buffer, BLOCKSIZE, &guid_context); - - total += sum; - } - - /* Add the last bytes if necessary. */ - if (sum > 0) - { - md5_process_bytes (buffer, sum, &guid_context); - total += sum; - } - - LEAVE(""); - return total; -} - -static size_t -init_from_file(const char *filename, size_t max_size) -{ - struct stat stats; - size_t total = 0; - size_t file_bytes; - FILE *fp; - - ENTER("filename: %s", filename); - - memset(&stats, 0, sizeof(stats)); - if (g_stat(filename, &stats) != 0) - { - LEAVE("unable to read file stats on %s", filename); - return 0; - } - - md5_process_bytes(&stats, sizeof(stats), &guid_context); - total += sizeof(stats); - - if (max_size <= 0) - { - LEAVE("no bytes in file %s", filename); - return total; - } - - fp = g_fopen (filename, "r"); - if (fp == NULL) - { - LEAVE("unable to open file %s", filename); - return total; - } - - file_bytes = init_from_stream(fp, max_size); - -#ifdef HAVE_SCANF_LLD - PINFO ("guid_init got %" G_GUINT64_FORMAT " bytes from %s", - (uint64_t) file_bytes, - filename); -#else - PINFO ("guid_init got %lu bytes from %s", (unsigned long int) file_bytes, - filename); -#endif - - total += file_bytes; - - fclose(fp); - - LEAVE("file %s processed successfully", filename); - return total; -} - -static size_t -init_from_dir(const char *dirname, unsigned int max_files) -{ - char filename[1024]; - const gchar *de; - struct stat stats; - size_t total; - int result; - GDir *dir; - - ENTER("dirname: %s", dirname); - if (max_files <= 0) - { - LEAVE("max_files is 0 or less, skipping directory %s", dirname); - return 0; - } - - dir = g_dir_open(dirname, 0, NULL); - if (dir == NULL) - { - LEAVE("unable to open directory %s", dirname); - return 0; - } - - total = 0; - - do - { - de = g_dir_read_name(dir); - if (de == NULL) - break; - - md5_process_bytes(de, strlen(de), &guid_context); - total += strlen(de); - - result = g_snprintf(filename, sizeof(filename), - "%s/%s", dirname, de); - if ((result < 0) || (result >= (int)sizeof(filename))) - continue; - - memset(&stats, 0, sizeof(stats)); - if (g_stat(filename, &stats) != 0) - continue; - md5_process_bytes(&stats, sizeof(stats), &guid_context); - total += sizeof(stats); - - max_files--; - } - while (max_files > 0); - - g_dir_close(dir); - - LEAVE(""); - return total; -} - -static size_t -init_from_time(void) -{ - size_t total; - time64 time; -#ifdef HAVE_SYS_TIMES_H - clock_t clocks; - struct tms tms_buf; -#endif - - ENTER(""); - - total = 0; - - time = gnc_time (NULL); - md5_process_bytes(&time, sizeof(time), &guid_context); - total += sizeof(time); - -#ifdef HAVE_SYS_TIMES_H - clocks = times(&tms_buf); - md5_process_bytes(&clocks, sizeof(clocks), &guid_context); - md5_process_bytes(&tms_buf, sizeof(tms_buf), &guid_context); - total += sizeof(clocks) + sizeof(tms_buf); -#endif - - LEAVE(""); - return total; -} - -static size_t -init_from_int(int val) -{ - ENTER(""); - md5_process_bytes(&val, sizeof(val), &guid_context); - LEAVE(""); - return sizeof(int); -} - -static size_t -init_from_buff(unsigned char * buf, size_t buflen) -{ - ENTER(""); - md5_process_bytes(buf, buflen, &guid_context); - LEAVE(""); - return buflen; -} - void guid_init(void) { - size_t bytes = 0; - - ENTER(""); - - /* Not needed; taken care of on first malloc. - * guid_memchunk_init(); */ - - md5_init_ctx(&guid_context); - - /* entropy pool - * FIXME /dev/urandom doesn't exist on Windows. We should - * use the Windows native CryptGenRandom or RtlGenRandom - * functions. See - * http://en.wikipedia.org/wiki/CryptGenRandom */ - bytes += init_from_file ("/dev/urandom", 512); - - /* files - * FIXME none of these directories make sense on - * Windows. We should figure out some proper - * alternatives there. */ - { - const char * files[] = - { - "/etc/passwd", - "/proc/loadavg", - "/proc/meminfo", - "/proc/net/dev", - "/proc/rtc", - "/proc/self/environ", - "/proc/self/stat", - "/proc/stat", - "/proc/uptime", - NULL - }; - int i; - - for (i = 0; files[i] != NULL; i++) - bytes += init_from_file(files[i], BLOCKSIZE); - } - - /* directories - * Note: P_tmpdir is set to "\" by mingw (Windows) This seems to - * trigger unwanted network access attempts (see bug #521817). - * So on Windows we explicitly set the temporary directory. - * FIXME other than "c:/temp" none of these directories make sense on - * Windows. We should figure out some proper - * alternatives there. */ - { - const char * dirname; - const char * dirs[] = - { - "/proc", -#ifndef G_OS_WIN32 - P_tmpdir, -#else - "c:/temp", -#endif - "/var/lock", - "/var/log", - "/var/mail", - "/var/spool/mail", - "/var/run", - NULL - }; - int i; - - for (i = 0; dirs[i] != NULL; i++) - bytes += init_from_dir(dirs[i], 32); - - dirname = g_get_home_dir(); - if (dirname != NULL) - bytes += init_from_dir(dirname, 32); - } - - /* process and parent ids */ - { -#ifdef HAVE_UNISTD_H - pid_t pid; - - pid = getpid(); - md5_process_bytes(&pid, sizeof(pid), &guid_context); - bytes += sizeof(pid); - -#ifdef HAVE_GETPPID - pid = getppid(); - md5_process_bytes(&pid, sizeof(pid), &guid_context); - bytes += sizeof(pid); -#endif -#endif - } - - /* user info */ - { -#ifdef HAVE_GETUID - uid_t uid; - gid_t gid; - char *s; - - s = getlogin(); - if (s != NULL) - { - md5_process_bytes(s, strlen(s), &guid_context); - bytes += strlen(s); - } - - uid = getuid(); - md5_process_bytes(&uid, sizeof(uid), &guid_context); - bytes += sizeof(uid); - - gid = getgid(); - md5_process_bytes(&gid, sizeof(gid), &guid_context); - bytes += sizeof(gid); -#endif - } - - /* host info */ - { -#ifdef HAVE_GETHOSTNAME - char string[1024]; - - memset(string, 0, sizeof(string)); - gethostname(string, sizeof(string)); - md5_process_bytes(string, sizeof(string), &guid_context); - bytes += sizeof(string); -#endif - } - - /* plain old random */ - { - int n, i; - - srand((unsigned int) gnc_time (NULL)); - - for (i = 0; i < 32; i++) - { - n = rand(); - - md5_process_bytes(&n, sizeof(n), &guid_context); - bytes += sizeof(n); - } - } - - /* time in secs and clock ticks */ - bytes += init_from_time(); - - PINFO ("got %" G_GUINT64_FORMAT " bytes", (uint64_t) bytes); - - if (bytes < THRESHOLD) - PWARN("only got %" G_GUINT64_FORMAT " bytes.\n" - "The identifiers might not be very random.\n", - (uint64_t)bytes); - - guid_initialized = TRUE; - LEAVE(); + /*Boost takes care of this*/ } void @@ -540,208 +146,105 @@ guid_shutdown (void) { } -#define GUID_PERIOD 5000 - +/*Takes an already-constructed guid pointer and re-constructs it in place*/ void guid_new(GncGUID *guid) { - static int counter = 0; - struct md5_ctx ctx; - - if (guid == NULL) - return; - - if (!guid_initialized) - guid_init(); - - /* make the id */ - ctx = guid_context; - md5_finish_ctx(&ctx, guid->data); - - /* update the global context */ - init_from_time(); - - /* Make it a little extra salty. I think init_from_time was buggy, - * or something, since duplicate id's actually happened. Or something - * like that. I think this is because init_from_time kept returning - * the same values too many times in a row. So we'll do some 'block - * chaining', and feed in the old guid as new random data. - * - * Anyway, I think the whole fact that I saw a bunch of duplicate - * id's at one point, but can't reproduce the bug is rather alarming. - * Something must be broken somewhere, and merely adding more salt - * is just hiding the problem, not fixing it. - */ - init_from_int (433781 * counter); - init_from_buff (guid->data, GUID_DATA_SIZE); - - if (counter == 0) - { - FILE *fp; - - fp = g_fopen ("/dev/urandom", "r"); - if (fp == NULL) - return; - - init_from_stream(fp, 32); - - fclose(fp); - - counter = GUID_PERIOD; - } - - counter--; + static boost::uuids::random_generator gen; + boost::uuids::uuid * val {reinterpret_cast (guid)}; + val->boost::uuids::uuid::~uuid(); + new (val) boost::uuids::uuid (gen ()); } GncGUID guid_new_return(void) { - GncGUID guid; - - guid_new (&guid); - - return guid; + /*we need to construct our value as a boost guid so that + it can be deconstructed (in place) in guid_new*/ + boost::uuids::uuid guid; + GncGUID * ret {reinterpret_cast (&guid)}; + guid_new (ret); + /*return a copy*/ + return *ret; } -/* needs 32 bytes exactly, doesn't print a null char */ -static void -encode_md5_data(const unsigned char *data, char *buffer) -{ - size_t count; - - for (count = 0; count < GUID_DATA_SIZE; count++, buffer += 2) - sprintf(buffer, "%02x", data[count]); -} - -/* returns true if the first 32 bytes of buffer encode - * a hex number. returns false otherwise. Decoded number - * is packed into data in little endian order. */ -static gboolean -decode_md5_string(const gchar *string, unsigned char *data) -{ - unsigned char n1, n2; - size_t count = -1; - unsigned char c1, c2; - - if (NULL == data) return FALSE; - if (NULL == string) goto badstring; - - for (count = 0; count < GUID_DATA_SIZE; count++) - { - /* check for a short string e.g. null string ... */ - if ((0 == string[2*count]) || (0 == string[2*count+1])) goto badstring; - - c1 = tolower(string[2 * count]); - if (!isxdigit(c1)) goto badstring; - - c2 = tolower(string[2 * count + 1]); - if (!isxdigit(c2)) goto badstring; - - if (isdigit(c1)) - n1 = c1 - '0'; - else - n1 = c1 - 'a' + 10; - - if (isdigit(c2)) - n2 = c2 - '0'; - else - n2 = c2 - 'a' + 10; - - data[count] = (n1 << 4) | n2; - } - return TRUE; - -badstring: - for (count = 0; count < GUID_DATA_SIZE; count++) - { - data[count] = 0; - } - return FALSE; -} - -/* Allocate the key */ - const char * -guid_to_string(const GncGUID * guid) +guid_to_string (const GncGUID * guid) { -#ifdef G_THREADS_ENABLED -#ifndef HAVE_GLIB_2_32 - static GStaticPrivate guid_buffer_key = G_STATIC_PRIVATE_INIT; - gchar *string; - - string = static_cast(g_static_private_get (&guid_buffer_key)); - if (string == NULL) - { - string = static_cast(malloc(GUID_ENCODING_LENGTH + 1)); - g_static_private_set (&guid_buffer_key, string, g_free); + /* We need to malloc here, not 'new' because it will be freed + by the caller which will use free (not delete).*/ + char * ret {reinterpret_cast (malloc (sizeof (char)*GUID_ENCODING_LENGTH+1))}; + gchar * temp {guid_to_string_buff(guid, ret)}; + if (!temp){ + delete[] ret; + return temp; } -#else - static GPrivate guid_buffer_key = G_PRIVATE_INIT(g_free); - gchar *string; - - string = static_cast(g_private_get (&guid_buffer_key)); - if (string == NULL) - { - string = static_cast(malloc(GUID_ENCODING_LENGTH + 1)); - g_private_set (&guid_buffer_key, string); - } -#endif -#else - static char string[64]; -#endif - - encode_md5_data(guid->data, string); - string[GUID_ENCODING_LENGTH] = '\0'; - - return string; + return ret; } -char * -guid_to_string_buff(const GncGUID * guid, char *string) +gchar * +guid_to_string_buff(const GncGUID * guid, char *str) { - if (!string || !guid) return NULL; + if (!str || !guid) return NULL; - encode_md5_data(guid->data, string); - - string[GUID_ENCODING_LENGTH] = '\0'; - return &string[GUID_ENCODING_LENGTH]; + static boost::uuids::string_generator str_gen; + stringstream ostr; + boost::uuids::uuid const & tempg = *reinterpret_cast(guid); + ostr << tempg; + string const & val (ostr.str()); + /*unsigned size {val.size()}; + size must equal GUID_ENCODING_LENGTH*/ + unsigned stringspot{0}; + for (unsigned destspot{0}; destspot < GUID_ENCODING_LENGTH; ++destspot, ++stringspot){ + switch (stringspot){ + /*there are hyphens in boost's output, and we need to skip them in our output*/ + case 8: + case 13: + case 18: + case 23: + ++stringspot; + } + str[destspot] = val[stringspot]; + } + str[GUID_ENCODING_LENGTH] = '\0'; + return &str[GUID_ENCODING_LENGTH]; } gboolean -string_to_guid(const char * string, GncGUID * guid) +string_to_guid(const char * str, GncGUID * guid) { - return decode_md5_string(string, (guid != NULL) ? guid->data : NULL); + static boost::uuids::string_generator strgen; + boost::uuids::uuid * converted {reinterpret_cast (guid)}; + new (converted) boost::uuids::uuid (strgen(str)); + return true; } gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2) { - if (guid_1 && guid_2) - return (memcmp(guid_1, guid_2, GUID_DATA_SIZE) == 0); - else - return FALSE; + if (!guid_1 || !guid_2) + return false; + boost::uuids::uuid const * g1 {reinterpret_cast (guid_1)}; + boost::uuids::uuid const * g2 {reinterpret_cast (guid_2)}; + return *g1 == *g2; } gint guid_compare(const GncGUID *guid_1, const GncGUID *guid_2) { - if (guid_1 == guid_2) - return 0; - - /* nothing is always less than something */ - if (!guid_1 && guid_2) + boost::uuids::uuid const * g1 {reinterpret_cast (guid_1)}; + boost::uuids::uuid const * g2 {reinterpret_cast (guid_2)}; + if (*g1 < *g2) return -1; - - if (guid_1 && !guid_2) - return 1; - - return memcmp (guid_1, guid_2, GUID_DATA_SIZE); + if (*g1 == *g2) + return 0; + return 1; } guint guid_hash_to_guint (gconstpointer ptr) { - const GncGUID *guid = static_cast(ptr); + const boost::uuids::uuid * guid = reinterpret_cast(ptr); if (!guid) { @@ -749,33 +252,22 @@ guid_hash_to_guint (gconstpointer ptr) return 0; } - if (sizeof(guint) <= sizeof(guid->data)) - { - const guint* ptr_data = (const guint *) guid->data; - return (*ptr_data); - } - else - { - guint hash = 0; - unsigned int i, j; - - for (i = 0, j = 0; i < sizeof(guint); i++, j++) - { - if (j == GUID_DATA_SIZE) j = 0; - - hash <<= 4; - hash |= guid->data[j]; - } - - return hash; + guint hash {0}; + unsigned retspot {0}; + boost::uuids::uuid::const_iterator guidspot {guid->begin()}; + while (guidspot != guid->end()){ + hash <<= 4; + hash |= *guidspot; + ++guidspot; } + return hash; } gint guid_g_hash_table_equal (gconstpointer guid_a, gconstpointer guid_b) { - return guid_equal (static_cast(guid_a), - static_cast(guid_b)); + return guid_equal (reinterpret_cast(guid_a), + reinterpret_cast(guid_b)); } GHashTable * diff --git a/src/libqof/qof/guid.h b/src/libqof/qof/guid.h index 0dabd4221b..46aa6bdc65 100644 --- a/src/libqof/qof/guid.h +++ b/src/libqof/qof/guid.h @@ -29,6 +29,10 @@ extern "C" { #endif +typedef struct _gncGuid { + unsigned char reserved[16]; +} GncGUID; + #include #include @@ -56,14 +60,6 @@ extern "C" /** The type used to store guids */ #define GUID_DATA_SIZE 16 -typedef union GNC_INTERNAL_GUID -{ - guchar data[GUID_DATA_SIZE]; - - gint __align_me; /* this just ensures that GUIDs are 32-bit - * aligned on systems that need them to be. */ -} GncGUID; - #define GNC_TYPE_GUID (gnc_guid_get_type()) #define GNC_VALUE_HOLDS_GUID(value) G_VALUE_HOLDS(value, GNC_TYPE_GUID) @@ -105,7 +101,7 @@ void guid_shutdown (void); * you'd still have less than a one-in-a-million chance of coming up * with a duplicate id. 2^128 == 10^38 is a really really big number.) */ -void guid_new(GncGUID *guid); +void guid_new (GncGUID *guid); /** Generate a new id. If no initialization function has been called, * guid_init() will be called before the id is created. @@ -113,16 +109,24 @@ void guid_new(GncGUID *guid); * @return guid A data structure containing a newly allocated GncGUID. * Caller is responsible for calling guid_free(). */ -GncGUID guid_new_return(void); +GncGUID guid_new_return (void); /** Returns a GncGUID which is guaranteed to never reference any entity. */ const GncGUID * guid_null (void); -/** Efficiently allocate & free memory for GUIDs */ +/** Efficiently allocate & free memory for GUIDs + * XXX This routine is deprecated. Please use guid_new_return_ptr + * instead. +*/ GncGUID * guid_malloc (void); -/* Return a guid set to all zero's */ +/** Allocate and initialize a new guid, and return +a pointer to it. Caller must call guid_free after to +release this pointer*/ +GncGUID * guid_new_ptr_return (void); + +/*Free the guid pointed to. Do not use this guid any more.*/ void guid_free (GncGUID *guid); GncGUID *guid_copy (const GncGUID *guid); @@ -133,9 +137,6 @@ GncGUID *guid_copy (const GncGUID *guid); * 'a' through 'f'. The encoding will always be GUID_ENCODING_LENGTH * characters long. * - * XXX This routine is not thread safe and is deprecated. Please - * use the routine guid_to_string_buff() instead. - * * @param guid The guid to print. * * @return A pointer to the starting character of the string. The @@ -155,7 +156,8 @@ const gchar * guid_to_string (const GncGUID * guid); * * @param buff The buffer to print it into. * - * @return A pointer to the terminating null character of the string. + * @return A pointer to the terminating null character of the string, + * or, if no copy took place, NULL. */ gchar * guid_to_string_buff (const GncGUID * guid, /*@ out @*/ gchar *buff); From 9c82a1e9bc217cc2c12482c3e23b0d442a5f0661 Mon Sep 17 00:00:00 2001 From: lmat Date: Fri, 25 Jul 2014 08:26:54 -0400 Subject: [PATCH 2/9] Rename guid_new to guid_replace `new` implies some allocation. Since guid_new was actually constructing a guid in place rather than allocating it, it makes much more sense to call it guid_replace (or guid_construct). We went with guid_replace. --- src/doc/design/engine.texi | 4 ++-- src/engine/test-core/test-engine-stuff.c | 2 +- src/engine/test/test-customer.c | 2 +- src/engine/test/test-employee.c | 2 +- src/engine/test/test-guid.c | 4 ++-- src/engine/test/test-job.c | 2 +- src/engine/test/test-vendor.c | 2 +- src/experimental/cgi-bin/gnc-server.c | 2 +- src/gnome/dialog-print-check.c | 2 +- src/gnome/dialog-print-check2.c | 2 +- src/libqof/qof/guid.cpp | 10 +++++----- src/libqof/qof/guid.h | 15 +++------------ src/libqof/qof/qofinstance.cpp | 2 +- src/libqof/qof/test/test-gnc-guid.cpp | 8 ++++---- src/libqof/qof/test/test-kvp_frame.c | 20 ++++++++++---------- src/libqof/qof/test/test-qofinstance.c | 2 +- 16 files changed, 36 insertions(+), 45 deletions(-) diff --git a/src/doc/design/engine.texi b/src/doc/design/engine.texi index a33c31c376..dc1de55944 100644 --- a/src/doc/design/engine.texi +++ b/src/doc/design/engine.texi @@ -353,7 +353,7 @@ entities such as Accounts and Transactions. Generate a new guid. This function is guaranteed to return a guid that is unique within the scope of all GnuCash entities being managed by the the current invocation of GnuCash. GnuCash routines should always use -this function and not @code{guid_new}! +this function and not @code{guid_replace}! @end deftypefun @deftypefun {void *} xaccLookupEntity (const GUID * @var{guid}, GNCIdType @var{entity_type}) @@ -394,7 +394,7 @@ binary data. This provides a way to reliably obtain a given sequence of GUIDs. @end deftypefun -@deftypefun void guid_new (GUID * @var{guid}) +@deftypefun void guid_replace (GUID * @var{guid}) Create a new GUID and store it in @var{guid}. This is a low-level function! GnuCash code should use @code{xaccGUIDNew}. @end deftypefun diff --git a/src/engine/test-core/test-engine-stuff.c b/src/engine/test-core/test-engine-stuff.c index 77086f0f4d..7e5b57ea89 100644 --- a/src/engine/test-core/test-engine-stuff.c +++ b/src/engine/test-core/test-engine-stuff.c @@ -243,7 +243,7 @@ get_random_guid(void) GncGUID *ret; ret = g_new(GncGUID, 1); - guid_new(ret); + guid_replace(ret); return ret; } diff --git a/src/engine/test/test-customer.c b/src/engine/test/test-customer.c index fe8fb2f6b7..fd84729188 100644 --- a/src/engine/test/test-customer.c +++ b/src/engine/test/test-customer.c @@ -90,7 +90,7 @@ test_customer (void) do_test (gncCustomerGetAddr (customer) != NULL, "Addr"); do_test (gncCustomerGetShipAddr (customer) != NULL, "ShipAddr"); - guid_new (&guid); + guid_replace (&guid); customer = gncCustomerCreate (book); count++; gncCustomerSetGUID (customer, &guid); diff --git a/src/engine/test/test-employee.c b/src/engine/test/test-employee.c index 1835bbf21c..3f3fdb3a7a 100644 --- a/src/engine/test/test-employee.c +++ b/src/engine/test/test-employee.c @@ -96,7 +96,7 @@ test_employee (void) do_test (gncEmployeeGetAddr (employee) != NULL, "Addr"); - guid_new (&guid); + guid_replace (&guid); employee = gncEmployeeCreate (book); count++; gncEmployeeSetGUID (employee, &guid); diff --git a/src/engine/test/test-guid.c b/src/engine/test/test-guid.c index 20c234a13d..0cacf0b140 100644 --- a/src/engine/test/test-guid.c +++ b/src/engine/test/test-guid.c @@ -43,7 +43,7 @@ static void test_null_guid(void) g = guid_new_return(); gp = guid_malloc(); - guid_new(gp); + guid_replace(gp); do_test(guid_equal(guid_null(), guid_null()), "null guids equal"); do_test(!guid_equal(&g, gp), "two guids equal"); @@ -70,7 +70,7 @@ run_test (void) for (i = 0; i < NENT; i++) { ent = g_object_new(QOF_TYPE_INSTANCE, NULL); - guid_new(&guid); + guid_replace(&guid); ent = g_object_new(QOF_TYPE_INSTANCE, "guid", &guid, NULL); do_test ((NULL == qof_collection_lookup_entity (col, &guid)), "duplicate guid"); diff --git a/src/engine/test/test-job.c b/src/engine/test/test-job.c index 243307fff0..2b5b4f8155 100644 --- a/src/engine/test/test-job.c +++ b/src/engine/test/test-job.c @@ -91,7 +91,7 @@ test_job (void) test_bool_fcn (book, "Active", gncJobSetActive, gncJobGetActive); - guid_new (&guid); + guid_replace (&guid); job = gncJobCreate (book); count++; gncJobSetGUID (job, &guid); diff --git a/src/engine/test/test-vendor.c b/src/engine/test/test-vendor.c index c36ff72b1f..3f030e5c8e 100644 --- a/src/engine/test/test-vendor.c +++ b/src/engine/test/test-vendor.c @@ -96,7 +96,7 @@ test_vendor (void) do_test (gncVendorGetAddr (vendor) != NULL, "Addr"); - guid_new (&guid); + guid_replace (&guid); vendor = gncVendorCreate (book); count++; gncVendorSetGUID (vendor, &guid); diff --git a/src/experimental/cgi-bin/gnc-server.c b/src/experimental/cgi-bin/gnc-server.c index 4e19a76172..53f96aed90 100644 --- a/src/experimental/cgi-bin/gnc-server.c +++ b/src/experimental/cgi-bin/gnc-server.c @@ -116,7 +116,7 @@ auth_user (const char * name, const char *passwd) if (!name || !passwd) return NULL; guid = g_new (GncGUID, 1); - guid_new (guid); + guid_replace (guid); logged_in_users = g_list_prepend (logged_in_users, guid); session_auth_string = guid_to_string (guid); /* THREAD UNSAFE */ return session_auth_string; diff --git a/src/gnome/dialog-print-check.c b/src/gnome/dialog-print-check.c index 3ee4f0f2a8..b024b4bc4b 100644 --- a/src/gnome/dialog-print-check.c +++ b/src/gnome/dialog-print-check.c @@ -767,7 +767,7 @@ pcd_save_custom_data(PrintCheckDialog *pcd, const gchar *title) multip = pcd_get_custom_multip(pcd); key_file = g_key_file_new(); - guid_new(&guid); + guid_replace(&guid); guid_to_string_buff(&guid, buf); g_key_file_set_string(key_file, KF_GROUP_TOP, KF_KEY_GUID, buf); g_key_file_set_string(key_file, KF_GROUP_TOP, KF_KEY_TITLE, title); diff --git a/src/gnome/dialog-print-check2.c b/src/gnome/dialog-print-check2.c index b9a2cc4ffc..0f707fd2a0 100644 --- a/src/gnome/dialog-print-check2.c +++ b/src/gnome/dialog-print-check2.c @@ -767,7 +767,7 @@ pcd_save_custom_data(PrintCheckDialog *pcd, const gchar *title) multip = pcd_get_custom_multip(pcd); key_file = g_key_file_new(); - guid_new(&guid); + guid_replace(&guid); guid_to_string_buff(&guid, buf); g_key_file_set_string(key_file, KF_GROUP_TOP, KF_KEY_GUID, buf); g_key_file_set_string(key_file, KF_GROUP_TOP, KF_KEY_TITLE, title); diff --git a/src/libqof/qof/guid.cpp b/src/libqof/qof/guid.cpp index 72912d85fb..bbda68c64e 100644 --- a/src/libqof/qof/guid.cpp +++ b/src/libqof/qof/guid.cpp @@ -99,7 +99,7 @@ GncGUID * guid_malloc (void) { /*We need to actually construct here (not just ::operator new (size_t) -- allocate) - because in guid_new, we assume that the object has already been constructed. + because in guid_replace, we assume that the object has already been constructed. Note the boost UUID is a POD, so its constructor is trivial.*/ return reinterpret_cast (new boost::uuids::uuid); } @@ -146,9 +146,9 @@ guid_shutdown (void) { } -/*Takes an already-constructed guid pointer and re-constructs it in place*/ +/*Takes an allocated guid pointer and constructs it in place*/ void -guid_new(GncGUID *guid) +guid_replace(GncGUID *guid) { static boost::uuids::random_generator gen; boost::uuids::uuid * val {reinterpret_cast (guid)}; @@ -160,10 +160,10 @@ GncGUID guid_new_return(void) { /*we need to construct our value as a boost guid so that - it can be deconstructed (in place) in guid_new*/ + it can be deconstructed (in place) in guid_replace*/ boost::uuids::uuid guid; GncGUID * ret {reinterpret_cast (&guid)}; - guid_new (ret); + guid_replace (ret); /*return a copy*/ return *ret; } diff --git a/src/libqof/qof/guid.h b/src/libqof/qof/guid.h index 46aa6bdc65..06443807c0 100644 --- a/src/libqof/qof/guid.h +++ b/src/libqof/qof/guid.h @@ -87,21 +87,12 @@ void guid_init(void); * GUIDs at once. */ void guid_shutdown (void); -/** Generate a new id. If no initialization function has been called, - * guid_init() will be called before the id is created. +/** Generate a new guid. * - * @param guid A pointer to an existing guid data structure. The + * @param guid A pointer to an allocated guid data structure. The * existing value will be replaced with a new value. - * - * This routine uses the md5 algorithm to build strong random guids. - * Note that while guid's are generated randomly, the odds of this - * routine returning a non-unique id are astronomically small. - * (Literally astronomically: If you had Cray's on every solar - * system in the universe running for the entire age of the universe, - * you'd still have less than a one-in-a-million chance of coming up - * with a duplicate id. 2^128 == 10^38 is a really really big number.) */ -void guid_new (GncGUID *guid); +void guid_replace (GncGUID *guid); /** Generate a new id. If no initialization function has been called, * guid_init() will be called before the id is created. diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp index b5ac003554..26ec5b87f1 100644 --- a/src/libqof/qof/qofinstance.cpp +++ b/src/libqof/qof/qofinstance.cpp @@ -303,7 +303,7 @@ qof_instance_init_data (QofInstance *inst, QofIdType type, QofBook *book) do { - guid_new(&priv->guid); + guid_replace(&priv->guid); if (NULL == qof_collection_lookup_entity (col, &priv->guid)) break; diff --git a/src/libqof/qof/test/test-gnc-guid.cpp b/src/libqof/qof/test/test-gnc-guid.cpp index 5369a2168c..447e71e73d 100644 --- a/src/libqof/qof/test/test-gnc-guid.cpp +++ b/src/libqof/qof/test/test-gnc-guid.cpp @@ -47,7 +47,7 @@ static const gchar * suitename {"/qof/gnc-guid"}; static void test_create_gnc_guid (void){ GncGUID * guid {guid_malloc ()}; g_assert (guid != nullptr); - guid_new (guid); + guid_replace (guid); /*We apparently don't need to free guid_null (based on its being const)*/ const GncGUID * guidnull {guid_null ()}; g_assert (!guid_equal (guid, guidnull)); @@ -58,7 +58,7 @@ static void test_create_gnc_guid (void){ static void test_gnc_guid_copy (void) { GncGUID * guid {guid_malloc ()}; g_assert (guid != nullptr); - guid_new (guid); + guid_replace (guid); GncGUID * cp {guid_copy (guid)}; g_assert (guid_equal (guid, cp)); guid_free (cp); @@ -70,7 +70,7 @@ defined in the guid api. We then compare them.*/ static void test_gnc_guid_to_string (void) { GncGUID * guid {guid_malloc()}; g_assert (guid != nullptr); - guid_new (guid); + guid_replace (guid); string message {" using guid_to_string (deprecated): "}; /*don't free the return value of guid_to_string!*/ string guidstr {guid_to_string (guid)}; @@ -135,7 +135,7 @@ static void test_gnc_guid_roundtrip (void) { g_assert (guid1 != nullptr); GncGUID * guid2 {guid_malloc ()}; g_assert (guid2 != nullptr); - guid_new (guid1); + guid_replace (guid1); gchar guidstrp [GUID_ENCODING_LENGTH+1]; gchar * temp {guid_to_string_buff (guid1, guidstrp)}; diff --git a/src/libqof/qof/test/test-kvp_frame.c b/src/libqof/qof/test/test-kvp_frame.c index ce356375c5..688f97a0a2 100644 --- a/src/libqof/qof/test/test-kvp_frame.c +++ b/src/libqof/qof/test/test-kvp_frame.c @@ -102,7 +102,7 @@ populate_frame (KvpFrame *frame) ts.tv_sec = 1; ts.tv_nsec = 1; guid = guid_malloc (); - guid_new (guid); + guid_replace (guid); g_date_set_dmy (&gdate, 26, 1, 1957); kvp_frame_set_gint64( frame, "gint64-type", 100 ); @@ -164,7 +164,7 @@ test_kvp_frame_copy( Fixture *fixture, gconstpointer pData ) test_ts.tv_nsec = 1; test_str = "abcdefghijklmnop"; test_guid = guid_malloc(); - guid_new( test_guid ); + guid_replace( test_guid ); test_frame = kvp_frame_new(); g_assert( fixture->frame ); @@ -224,7 +224,7 @@ test_kvp_frame_set_foo( Fixture *fixture, gconstpointer pData ) test_ts.tv_sec = 1; test_ts.tv_nsec = 1; test_guid = guid_malloc(); - guid_new( test_guid ); + guid_replace( test_guid ); g_assert( fixture->frame ); g_assert( kvp_frame_is_empty( fixture->frame ) ); @@ -513,7 +513,7 @@ test_kvp_value_copy( void ) gnc_numeric_orig = gnc_numeric_zero(); guid_orig = guid_malloc(); - guid_new( guid_orig ); + guid_replace( guid_orig ); ts_orig.tv_sec = 1; ts_orig.tv_nsec = 1; list_orig = NULL; @@ -632,7 +632,7 @@ test_kvp_glist_copy( void ) gnc_numeric_orig = gnc_numeric_zero(); guid_orig = guid_malloc(); - guid_new( guid_orig ); + guid_replace( guid_orig ); ts_orig.tv_sec = 1; ts_orig.tv_nsec = 1; list_orig = NULL; @@ -704,7 +704,7 @@ test_kvp_glist_compare( void ) gnc_numeric_orig = gnc_numeric_zero(); guid_orig = guid_malloc(); - guid_new( guid_orig ); + guid_replace( guid_orig ); ts_orig.tv_sec = 1; ts_orig.tv_nsec = 1; list_orig = NULL; @@ -798,9 +798,9 @@ test_kvp_value_compare( void ) gnc_numeric_orig = gnc_numeric_zero(); gnc_numeric_copy = gnc_numeric_zero(); guid_orig = guid_malloc(); - guid_new( guid_orig ); + guid_replace( guid_orig ); guid_copy = guid_malloc(); - guid_new( guid_copy ); + guid_replace( guid_copy ); ts_orig.tv_sec = 1; ts_orig.tv_nsec = 1; ts_copy.tv_sec = 2; @@ -1008,7 +1008,7 @@ test_kvp_value_to_string( void ) gnc_numeric_orig = gnc_numeric_zero(); guid_orig = guid_malloc(); - guid_new( guid_orig ); + guid_replace( guid_orig ); ts_orig.tv_sec = 1; ts_orig.tv_nsec = 1; list_orig = NULL; @@ -1094,7 +1094,7 @@ test_kvp_frame_to_string( Fixture *fixture, gconstpointer pData ) test_gnc_numeric = gnc_numeric_zero(); test_guid = guid_malloc(); - guid_new( test_guid ); + guid_replace( test_guid ); test_ts.tv_sec = 1; test_ts.tv_nsec = 1; test_frame = kvp_frame_new(); diff --git a/src/libqof/qof/test/test-qofinstance.c b/src/libqof/qof/test/test-qofinstance.c index a47a8adda0..390719c92e 100644 --- a/src/libqof/qof/test/test-qofinstance.c +++ b/src/libqof/qof/test/test-qofinstance.c @@ -98,7 +98,7 @@ test_instance_set_get_guid( Fixture *fixture, gconstpointer pData ) /* set up */ gncGuid = guid_malloc(); - guid_new( gncGuid ); + guid_replace( gncGuid ); g_assert( QOF_IS_INSTANCE( fixture->inst ) ); g_assert( gncGuid ); From 2a408ab9ef31031440d1877673baad509ab085c3 Mon Sep 17 00:00:00 2001 From: lmat Date: Fri, 25 Jul 2014 14:14:09 -0400 Subject: [PATCH 3/9] Cleared up GUID construction and allocation To allocate a GUID, use guid_malloc. To allocate and construct a guid (which is actually unique), use guid_new (and be sure to free it using guid_free). --- src/engine/test/test-guid.c | 5 +++-- src/libqof/qof/guid.cpp | 19 ++++++++-------- src/libqof/qof/guid.h | 17 ++++++++------- src/libqof/qof/test/test-kvp_frame.c | 30 +++++++++----------------- src/libqof/qof/test/test-qofinstance.c | 3 +-- 5 files changed, 32 insertions(+), 42 deletions(-) diff --git a/src/engine/test/test-guid.c b/src/engine/test/test-guid.c index 0cacf0b140..fdb2408eb3 100644 --- a/src/engine/test/test-guid.c +++ b/src/engine/test/test-guid.c @@ -42,11 +42,12 @@ static void test_null_guid(void) GncGUID *gp; g = guid_new_return(); - gp = guid_malloc(); - guid_replace(gp); + gp = guid_new(); do_test(guid_equal(guid_null(), guid_null()), "null guids equal"); do_test(!guid_equal(&g, gp), "two guids equal"); + + guid_free(gp); } static void diff --git a/src/libqof/qof/guid.cpp b/src/libqof/qof/guid.cpp index bbda68c64e..f69890c946 100644 --- a/src/libqof/qof/guid.cpp +++ b/src/libqof/qof/guid.cpp @@ -88,19 +88,10 @@ gnc_value_get_guid (const GValue *value) /* Memory management routines ***************************************/ -GncGUID * -guid_new_ptr_return (void) -{ - return reinterpret_cast (new boost::uuids::uuid); -} - -/* Deprecated*/ GncGUID * guid_malloc (void) { - /*We need to actually construct here (not just ::operator new (size_t) -- allocate) - because in guid_replace, we assume that the object has already been constructed. - Note the boost UUID is a POD, so its constructor is trivial.*/ + /*Note, the Boost uuid is a POD, so its constructor is trivial*/ return reinterpret_cast (new boost::uuids::uuid); } @@ -156,6 +147,14 @@ guid_replace(GncGUID *guid) new (val) boost::uuids::uuid (gen ()); } +GncGUID * +guid_new (void) +{ + GncGUID * ret {guid_malloc ()}; + guid_replace (ret); + return ret; +} + GncGUID guid_new_return(void) { diff --git a/src/libqof/qof/guid.h b/src/libqof/qof/guid.h index 06443807c0..fd32446c5b 100644 --- a/src/libqof/qof/guid.h +++ b/src/libqof/qof/guid.h @@ -106,16 +106,17 @@ GncGUID guid_new_return (void); to never reference any entity. */ const GncGUID * guid_null (void); -/** Efficiently allocate & free memory for GUIDs - * XXX This routine is deprecated. Please use guid_new_return_ptr - * instead. -*/ +/** + * Allocate memory for a GUID. The returned pointer must be freed with + * guid_free. + */ GncGUID * guid_malloc (void); -/** Allocate and initialize a new guid, and return -a pointer to it. Caller must call guid_free after to -release this pointer*/ -GncGUID * guid_new_ptr_return (void); +/** + * Allocate and construct a new GUID. The returned pointer must be + * released with guid_free. + */ +GncGUID * guid_new (void); /*Free the guid pointed to. Do not use this guid any more.*/ void guid_free (GncGUID *guid); diff --git a/src/libqof/qof/test/test-kvp_frame.c b/src/libqof/qof/test/test-kvp_frame.c index 688f97a0a2..ee70a75fa0 100644 --- a/src/libqof/qof/test/test-kvp_frame.c +++ b/src/libqof/qof/test/test-kvp_frame.c @@ -101,8 +101,7 @@ populate_frame (KvpFrame *frame) ts.tv_sec = 1; ts.tv_nsec = 1; - guid = guid_malloc (); - guid_replace (guid); + guid = guid_new (); g_date_set_dmy (&gdate, 26, 1, 1957); kvp_frame_set_gint64( frame, "gint64-type", 100 ); @@ -163,8 +162,7 @@ test_kvp_frame_copy( Fixture *fixture, gconstpointer pData ) test_ts.tv_sec = 1; test_ts.tv_nsec = 1; test_str = "abcdefghijklmnop"; - test_guid = guid_malloc(); - guid_replace( test_guid ); + test_guid = guid_new(); test_frame = kvp_frame_new(); g_assert( fixture->frame ); @@ -223,8 +221,7 @@ test_kvp_frame_set_foo( Fixture *fixture, gconstpointer pData ) test_gnc_numeric = gnc_numeric_zero(); test_ts.tv_sec = 1; test_ts.tv_nsec = 1; - test_guid = guid_malloc(); - guid_replace( test_guid ); + test_guid = guid_new(); g_assert( fixture->frame ); g_assert( kvp_frame_is_empty( fixture->frame ) ); @@ -512,8 +509,7 @@ test_kvp_value_copy( void ) KvpFrame *frame_orig, *frame_copy; gnc_numeric_orig = gnc_numeric_zero(); - guid_orig = guid_malloc(); - guid_replace( guid_orig ); + guid_orig = guid_new(); ts_orig.tv_sec = 1; ts_orig.tv_nsec = 1; list_orig = NULL; @@ -631,8 +627,7 @@ test_kvp_glist_copy( void ) KvpFrame *frame_orig; gnc_numeric_orig = gnc_numeric_zero(); - guid_orig = guid_malloc(); - guid_replace( guid_orig ); + guid_orig = guid_new(); ts_orig.tv_sec = 1; ts_orig.tv_nsec = 1; list_orig = NULL; @@ -703,8 +698,7 @@ test_kvp_glist_compare( void ) KvpFrame *frame_orig; gnc_numeric_orig = gnc_numeric_zero(); - guid_orig = guid_malloc(); - guid_replace( guid_orig ); + guid_orig = guid_new(); ts_orig.tv_sec = 1; ts_orig.tv_nsec = 1; list_orig = NULL; @@ -797,10 +791,8 @@ test_kvp_value_compare( void ) gnc_numeric_orig = gnc_numeric_zero(); gnc_numeric_copy = gnc_numeric_zero(); - guid_orig = guid_malloc(); - guid_replace( guid_orig ); - guid_copy = guid_malloc(); - guid_replace( guid_copy ); + guid_orig = guid_new(); + guid_copy = guid_new(); ts_orig.tv_sec = 1; ts_orig.tv_nsec = 1; ts_copy.tv_sec = 2; @@ -1007,8 +999,7 @@ test_kvp_value_to_string( void ) KvpFrame *frame_orig; gnc_numeric_orig = gnc_numeric_zero(); - guid_orig = guid_malloc(); - guid_replace( guid_orig ); + guid_orig = guid_new(); ts_orig.tv_sec = 1; ts_orig.tv_nsec = 1; list_orig = NULL; @@ -1093,8 +1084,7 @@ test_kvp_frame_to_string( Fixture *fixture, gconstpointer pData ) KvpFrame *test_frame; test_gnc_numeric = gnc_numeric_zero(); - test_guid = guid_malloc(); - guid_replace( test_guid ); + test_guid = guid_new(); test_ts.tv_sec = 1; test_ts.tv_nsec = 1; test_frame = kvp_frame_new(); diff --git a/src/libqof/qof/test/test-qofinstance.c b/src/libqof/qof/test/test-qofinstance.c index 390719c92e..b6b317f983 100644 --- a/src/libqof/qof/test/test-qofinstance.c +++ b/src/libqof/qof/test/test-qofinstance.c @@ -97,8 +97,7 @@ test_instance_set_get_guid( Fixture *fixture, gconstpointer pData ) g_assert( qof_entity_get_guid( NULL ) == guid_null() ); /* set up */ - gncGuid = guid_malloc(); - guid_replace( gncGuid ); + gncGuid = guid_new(); g_assert( QOF_IS_INSTANCE( fixture->inst ) ); g_assert( gncGuid ); From 30fac05e35b41d316ba9d8f93474879e196c3cbb Mon Sep 17 00:00:00 2001 From: lmat Date: Fri, 25 Jul 2014 17:02:44 -0400 Subject: [PATCH 4/9] Corrected uses of guid_to_string. Previously, guid_to_string had been marked deprecated with a note about it not being thread-safe. It was much worse than "not thread safe", it was only safe in a particular situation, and its safety was being violated throughout the code. It was clear that users of guid_to_string did not understand what it was purporting to do because of its varied uses. Most uses simply treated it like a Garbage-Collected Java String (use and forget). I actually found at least one instance where the string was being freed. (!!!) I made the method have a particular easy-to-understand semantic: it returns a pointer to a string which must be freed by the caller. I then tried to track down all uses of this function and correct them. Mostly, I just changed the usage to guid_to_string_buff with a stack-allocated string to avoid the the malloc/free cycle. --- src/app-utils/gnc-component-manager.c | 4 +- src/app-utils/gnc-state.c | 5 ++- src/app-utils/gnc-sx-instance-model.c | 10 +++-- src/app-utils/guile-util.c | 11 +++-- src/backend/sql/gnc-transaction-sql.c | 18 ++++---- src/backend/xml/gnc-bill-term-xml-v2.c | 44 ++++++++++++------- src/backend/xml/gnc-schedxaction-xml-v2.c | 11 +++-- src/backend/xml/gnc-tax-table-xml-v2.c | 20 +++++---- src/backend/xml/sixtp-dom-generators.c | 8 ++-- src/backend/xml/test/test-xml-transaction.c | 4 +- src/business/business-gnome/dialog-invoice.c | 13 +++--- src/doc/design/engine.texi | 4 +- src/engine/SchedXaction.c | 4 +- src/engine/Split.c | 4 +- src/engine/Transaction.c | 6 ++- src/engine/gncBillTerm.c | 5 ++- src/engine/test/utest-Split.cpp | 4 +- src/experimental/cgi-bin/gnc-server.c | 13 +++--- src/gnome/dialog-sx-editor.c | 4 +- src/gnome/dialog-sx-editor2.c | 3 +- src/gnome/gnc-budget-view.c | 9 +++- src/gnome/gnc-plugin-page-account-tree.c | 10 ++--- src/gnome/gnc-split-reg.c | 28 ++++++------ src/gnome/gnc-split-reg2.c | 37 +++++----------- src/gnome/top-level.c | 4 +- src/import-export/log-replay/gnc-log-replay.c | 9 ++-- src/libqof/qof/guid.cpp | 12 ++--- src/libqof/qof/guid.h | 8 ++-- src/libqof/qof/kvp_frame.cpp | 6 +-- src/libqof/qof/qofinstance.cpp | 5 ++- src/libqof/qof/qofquery.cpp | 6 +-- src/libqof/qof/test/test-gnc-guid.cpp | 7 +-- src/libqof/qof/test/test-kvp_frame.c | 6 +-- 33 files changed, 187 insertions(+), 155 deletions(-) diff --git a/src/app-utils/gnc-component-manager.c b/src/app-utils/gnc-component-manager.c index 9a47f6d475..030eb9ca00 100644 --- a/src/app-utils/gnc-component-manager.c +++ b/src/app-utils/gnc-component-manager.c @@ -260,8 +260,10 @@ gnc_cm_event_handler (QofInstance *entity, { const GncGUID *guid = qof_entity_get_guid(entity); #if CM_DEBUG + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff (guid, guidstr); fprintf (stderr, "event_handler: event %d, entity %p, guid %s\n", event_type, - entity, guid_to_string(guid)); + entity, guidstr); #endif add_event (&changes, guid, event_type, TRUE); diff --git a/src/app-utils/gnc-state.c b/src/app-utils/gnc-state.c index 2896717acb..801f311f33 100644 --- a/src/app-utils/gnc-state.c +++ b/src/app-utils/gnc-state.c @@ -71,7 +71,8 @@ gnc_state_set_base (const QofSession *session) { gchar *basename, *original = NULL, *filename, *file_guid; gchar *sf_extension = NULL, *newstyle_filename = NULL; - const gchar *uri, *guid_string; + const gchar *uri; + gchar guid_string[GUID_ENCODING_LENGTH+1]; QofBook *book; const GncGUID *guid; GKeyFile *key_file = NULL; @@ -94,7 +95,7 @@ gnc_state_set_base (const QofSession *session) /* Get the book GncGUID */ book = qof_session_get_book(session); guid = qof_entity_get_guid(QOF_INSTANCE(book)); - guid_string = guid_to_string(guid); + guid_to_string_buff(guid, guid_string); if (gnc_uri_is_file_uri (uri)) { diff --git a/src/app-utils/gnc-sx-instance-model.c b/src/app-utils/gnc-sx-instance-model.c index bfe2701ff6..119c8faec6 100644 --- a/src/app-utils/gnc-sx-instance-model.c +++ b/src/app-utils/gnc-sx-instance-model.c @@ -1490,6 +1490,8 @@ static void add_to_hash_amount(GHashTable* hash, const GncGUID* guid, const gnc_ * modify it in-place; if not, insert the new element into the * hash. */ gnc_numeric* elem = g_hash_table_lookup(hash, guid); + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(guid, guidstr); if (!elem) { elem = g_new0(gnc_numeric, 1); @@ -1503,7 +1505,7 @@ static void add_to_hash_amount(GHashTable* hash, const GncGUID* guid, const gnc_ g_critical("Oops, the given amount [%s] has the error code %d, at guid [%s].", gnc_num_dbg_to_string(*amount), gnc_numeric_check(*amount), - guid_to_string(guid)); + guidstr); return; } if (gnc_numeric_check(*elem) != GNC_ERROR_OK) @@ -1511,7 +1513,7 @@ static void add_to_hash_amount(GHashTable* hash, const GncGUID* guid, const gnc_ g_critical("Oops, the account's amount [%s] has the error code %d, at guid [%s].", gnc_num_dbg_to_string(*elem), gnc_numeric_check(*elem), - guid_to_string(guid)); + guidstr); return; } @@ -1527,7 +1529,7 @@ static void add_to_hash_amount(GHashTable* hash, const GncGUID* guid, const gnc_ if (gnc_numeric_check(*elem) != GNC_ERROR_OK) { g_critical("Oops, after addition at guid [%s] the resulting amount [%s] has the error code %d; added amount = [%s].", - guid_to_string(guid), + guidstr, gnc_num_dbg_to_string(*elem), gnc_numeric_check(*elem), gnc_num_dbg_to_string(*amount)); @@ -1536,7 +1538,7 @@ static void add_to_hash_amount(GHashTable* hash, const GncGUID* guid, const gnc_ /* In case anyone wants to see this in the debug log. */ g_debug("Adding to guid [%s] the value [%s]. Value now [%s].", - guid_to_string(guid), + guidstr, gnc_num_dbg_to_string(*amount), gnc_num_dbg_to_string(*elem)); } diff --git a/src/app-utils/guile-util.c b/src/app-utils/guile-util.c index 52307370db..dab9e3bd79 100644 --- a/src/app-utils/guile-util.c +++ b/src/app-utils/guile-util.c @@ -297,7 +297,7 @@ gnc_is_trans_scm(SCM scm) void gnc_split_scm_set_account(SCM split_scm, Account *account) { - const char *guid_string; + gchar guid_string[GUID_ENCODING_LENGTH+1]; SCM arg; initialize_scm_functions(); @@ -307,7 +307,7 @@ gnc_split_scm_set_account(SCM split_scm, Account *account) if (account == NULL) return; - guid_string = guid_to_string(xaccAccountGetGUID(account)); + guid_to_string_buff(xaccAccountGetGUID(account), guid_string); if (guid_string == NULL) return; @@ -657,6 +657,7 @@ gnc_copy_trans_scm_onto_trans_swap_accounts(SCM trans_scm, } else { + gchar guidstr[GUID_ENCODING_LENGTH+1]; SCM from, to; SCM map = SCM_EOL; SCM args = SCM_EOL; @@ -668,8 +669,10 @@ gnc_copy_trans_scm_onto_trans_swap_accounts(SCM trans_scm, args = scm_cons(commit, args); - from = scm_from_utf8_string(guid_to_string(guid_1)); - to = scm_from_utf8_string(guid_to_string(guid_2)); + guid_to_string_buff(guid_1, guidstr); + from = scm_from_utf8_string(guidstr); + guid_to_string_buff(guid_2, guidstr); + to = scm_from_utf8_string(guidstr); map = scm_cons(scm_cons(from, to), map); map = scm_cons(scm_cons(to, from), map); diff --git a/src/backend/sql/gnc-transaction-sql.c b/src/backend/sql/gnc-transaction-sql.c index 46fc3d9790..f48ce71d35 100644 --- a/src/backend/sql/gnc-transaction-sql.c +++ b/src/backend/sql/gnc-transaction-sql.c @@ -225,10 +225,11 @@ load_single_split( GncSqlBackend* be, GncSqlRow* row ) /*# -ifempty */ if (pSplit != xaccSplitLookup( &split_guid, be->book )) { - PERR("A malformed split with id %s was found in the dataset.", - guid_to_string(qof_instance_get_guid(pSplit))); - qof_backend_set_error( &be->be, ERR_BACKEND_DATA_CORRUPT); - pSplit = NULL; + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(qof_instance_get_guid(pSplit), guidstr); + PERR("A malformed split with id %s was found in the dataset.", guidstr); + qof_backend_set_error( &be->be, ERR_BACKEND_DATA_CORRUPT); + pSplit = NULL; } return pSplit; } @@ -305,10 +306,11 @@ load_single_tx( GncSqlBackend* be, GncSqlRow* row ) if (pTx != xaccTransLookup( &tx_guid, be->book )) { - PERR("A malformed transaction with id %s was found in the dataset.", - guid_to_string(qof_instance_get_guid(pTx))); - qof_backend_set_error( &be->be, ERR_BACKEND_DATA_CORRUPT); - pTx = NULL; + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(qof_instance_get_guid(pTx), guidstr); + PERR("A malformed transaction with id %s was found in the dataset.", guidstr); + qof_backend_set_error( &be->be, ERR_BACKEND_DATA_CORRUPT); + pTx = NULL; } return pTx; diff --git a/src/backend/xml/gnc-bill-term-xml-v2.c b/src/backend/xml/gnc-bill-term-xml-v2.c index f5d6b53fe0..fa4d421a47 100644 --- a/src/backend/xml/gnc-bill-term-xml-v2.c +++ b/src/backend/xml/gnc-bill-term-xml-v2.c @@ -588,8 +588,9 @@ billterm_scrub_cb (QofInstance *term_p, gpointer list_p) if (t) { /* Fix up the broken "copy" function */ - PWARN("Fixing broken child billterm: %s", - guid_to_string(qof_instance_get_guid(QOF_INSTANCE(term)))); + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(term)),guidstr); + PWARN("Fixing broken child billterm: %s", guidstr); gncBillTermBeginEdit(term); gncBillTermSetType(term, gncBillTermGetType(t)); @@ -624,8 +625,9 @@ billterm_scrub_invoices (QofInstance * invoice_p, gpointer ht_p) { if (billterm_is_grandchild(term)) { - PWARN("Fixing i-billterm on invoice %s\n", - guid_to_string(qof_instance_get_guid(QOF_INSTANCE(invoice)))); + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(invoice)),guidstr); + PWARN("Fixing i-billterm on invoice %s\n", guidstr); new_bt = billterm_find_senior(term); gncInvoiceBeginEdit(invoice); gncInvoiceSetTerms(invoice, new_bt); @@ -656,9 +658,13 @@ billterm_scrub_cust (QofInstance * cust_p, gpointer ht_p) count++; g_hash_table_insert(ht, term, GINT_TO_POINTER(count)); if (billterm_is_grandchild(term)) - PWARN("customer %s has grandchild billterm %s\n", - guid_to_string(qof_instance_get_guid(QOF_INSTANCE(cust))), - guid_to_string(qof_instance_get_guid(QOF_INSTANCE(term)))); + { + gchar custstr[GUID_ENCODING_LENGTH+1]; + gchar termstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(cust)),custstr); + guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(term)),termstr); + PWARN("customer %s has grandchild billterm %s\n", custstr,termstr); + } } } @@ -677,9 +683,13 @@ billterm_scrub_vendor (QofInstance * vendor_p, gpointer ht_p) count++; g_hash_table_insert(ht, term, GINT_TO_POINTER(count)); if (billterm_is_grandchild(term)) - PWARN("vendor %s has grandchild billterm %s\n", - guid_to_string(qof_instance_get_guid(QOF_INSTANCE(vendor))), - guid_to_string(qof_instance_get_guid(QOF_INSTANCE(term)))); + { + gchar vendstr[GUID_ENCODING_LENGTH+1]; + gchar termstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(vendor)),vendstr); + guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(term)),termstr); + PWARN("vendor %s has grandchild billterm %s\n", vendstr, termstr); + } } } @@ -691,9 +701,10 @@ billterm_reset_refcount (gpointer key, gpointer value, gpointer notused) if (count != gncBillTermGetRefcount(term) && !gncBillTermGetInvisible(term)) { + gchar termstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(term)),termstr); PWARN("Fixing refcount on billterm %s (%" G_GINT64_FORMAT " -> %d)\n", - guid_to_string(qof_instance_get_guid(QOF_INSTANCE(term))), - gncBillTermGetRefcount(term), count); + termstr, gncBillTermGetRefcount(term), count); gncBillTermSetRefcount(term, count); } } @@ -715,10 +726,11 @@ billterm_scrub (QofBook *book) /* destroy the list of "grandchildren" bill terms */ for (node = list; node; node = node->next) { + gchar termstr[GUID_ENCODING_LENGTH+1]; term = node->data; - PWARN ("deleting grandchild billterm: %s\n", - guid_to_string(qof_instance_get_guid(QOF_INSTANCE(term)))); + guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(term)), termstr); + PWARN ("deleting grandchild billterm: %s\n", termstr); /* Make sure the parent has no children */ parent = gncBillTermGetParent(term); @@ -770,11 +782,13 @@ GncBillTerm * gnc_billterm_xml_find_or_create(QofBook *book, GncGUID *guid) { GncBillTerm *term; + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(guid, guidstr); g_return_val_if_fail(book, NULL); g_return_val_if_fail(guid, NULL); term = gncBillTermLookup(book, guid); - DEBUG("looking for billterm %s, found %p", guid_to_string(guid), term); + DEBUG("looking for billterm %s, found %p", guidstr, term); if (!term) { term = gncBillTermCreate(book); diff --git a/src/backend/xml/gnc-schedxaction-xml-v2.c b/src/backend/xml/gnc-schedxaction-xml-v2.c index b6045560fa..2fd90caaa7 100644 --- a/src/backend/xml/gnc-schedxaction-xml-v2.c +++ b/src/backend/xml/gnc-schedxaction-xml-v2.c @@ -740,10 +740,10 @@ gnc_schedXaction_end_handler(gpointer data_for_children, if ( sx->template_acct == NULL ) { Account *ra = NULL; - const char *id = NULL; Account *acct = NULL; sixtp_gdv2 *sixdata = gdata->parsedata; QofBook *book; + gchar guidstr[GUID_ENCODING_LENGTH+1]; book = sixdata->book; @@ -751,8 +751,7 @@ gnc_schedXaction_end_handler(gpointer data_for_children, change re: storing template accounts. */ /* Fix: get account with name of our GncGUID from the template accounts. Make that our template_acct pointer. */ - /* THREAD-UNSAFE */ - id = guid_to_string( xaccSchedXactionGetGUID( sx ) ); + guid_to_string_buff( xaccSchedXactionGetGUID( sx ), guidstr ); ra = gnc_book_get_template_root(book); if ( ra == NULL ) { @@ -760,15 +759,15 @@ gnc_schedXaction_end_handler(gpointer data_for_children, xmlFreeNode( tree ); return FALSE; } - acct = gnc_account_lookup_by_name( ra, id ); + acct = gnc_account_lookup_by_name( ra, guidstr ); if ( acct == NULL ) { - g_warning("no template account with name [%s]", id); + g_warning("no template account with name [%s]", guidstr); xmlFreeNode( tree ); return FALSE; } g_debug("template account name [%s] for SX with GncGUID [%s]", - xaccAccountGetName( acct ), id ); + xaccAccountGetName( acct ), guidstr ); /* FIXME: free existing template account. * HUH????? We only execute this if there isn't diff --git a/src/backend/xml/gnc-tax-table-xml-v2.c b/src/backend/xml/gnc-tax-table-xml-v2.c index 0990e4b651..e427a2bfc9 100644 --- a/src/backend/xml/gnc-tax-table-xml-v2.c +++ b/src/backend/xml/gnc-tax-table-xml-v2.c @@ -576,8 +576,9 @@ taxtable_scrub_entries (QofInstance * entry_p, gpointer ht_p) { if (taxtable_is_grandchild(table)) { - PINFO("Fixing i-taxtable on entry %s\n", - guid_to_string(qof_instance_get_guid(QOF_INSTANCE(entry)))); + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(entry)),guidstr); + PINFO("Fixing i-taxtable on entry %s\n",guidstr); new_tt = taxtable_find_senior(table); gncEntryBeginEdit(entry); gncEntrySetInvTaxTable(entry, new_tt); @@ -597,8 +598,9 @@ taxtable_scrub_entries (QofInstance * entry_p, gpointer ht_p) { if (taxtable_is_grandchild(table)) { - PINFO("Fixing b-taxtable on entry %s\n", - guid_to_string(qof_instance_get_guid(QOF_INSTANCE(entry)))); + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(entry)),guidstr); + PINFO("Fixing b-taxtable on entry %s\n",guidstr); new_tt = taxtable_find_senior(table); gncEntryBeginEdit(entry); gncEntrySetBillTaxTable(entry, new_tt); @@ -656,9 +658,10 @@ taxtable_reset_refcount (gpointer key, gpointer value, gpointer notused) if (count != gncTaxTableGetRefcount(table) && !gncTaxTableGetInvisible(table)) { + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(table)),guidstr); PWARN("Fixing refcount on taxtable %s (%" G_GINT64_FORMAT " -> %d)\n", - guid_to_string(qof_instance_get_guid(QOF_INSTANCE(table))), - gncTaxTableGetRefcount(table), count); + guidstr,gncTaxTableGetRefcount(table), count); gncTaxTableSetRefcount(table, count); } } @@ -679,10 +682,11 @@ taxtable_scrub (QofBook *book) /* destroy the list of "grandchildren" tax tables */ for (node = list; node; node = node->next) { + gchar guidstr[GUID_ENCODING_LENGTH+1]; table = node->data; - PINFO ("deleting grandchild taxtable: %s\n", - guid_to_string(qof_instance_get_guid(QOF_INSTANCE(table)))); + guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(table)),guidstr); + PINFO ("deleting grandchild taxtable: %s\n", guidstr); /* Make sure the parent has no children */ parent = gncTaxTableGetParent(table); diff --git a/src/backend/xml/sixtp-dom-generators.c b/src/backend/xml/sixtp-dom-generators.c index 64ed084005..bb9c7ef20d 100644 --- a/src/backend/xml/sixtp-dom-generators.c +++ b/src/backend/xml/sixtp-dom-generators.c @@ -308,10 +308,12 @@ add_kvp_value_node(xmlNodePtr node, gchar *tag, kvp_value* val) xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "string"); break; case KVP_TYPE_GUID: - /* THREAD-UNSAFE */ - add_text_to_node(val_node, "guid", - g_strdup(guid_to_string(kvp_value_get_guid(val)))); + { + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(kvp_value_get_guid(val), guidstr); + add_text_to_node(val_node, "guid", guidstr); break; + } case KVP_TYPE_TIMESPEC: { Timespec ts = kvp_value_get_timespec (val); diff --git a/src/backend/xml/test/test-xml-transaction.c b/src/backend/xml/test/test-xml-transaction.c index 14edc799a6..3d58da21ad 100644 --- a/src/backend/xml/test/test-xml-transaction.c +++ b/src/backend/xml/test/test-xml-transaction.c @@ -218,7 +218,9 @@ equals_node_val_vs_splits(xmlNodePtr node, const Transaction *trn) if (!spl_node) { - g_print( "Split GUID %s", guid_to_string(xaccSplitGetGUID(spl_mark)) ); + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(xaccSplitGetGUID(spl_mark),guidstr); + g_print( "Split GUID %s", guidstr ); return "no matching split found"; } diff --git a/src/business/business-gnome/dialog-invoice.c b/src/business/business-gnome/dialog-invoice.c index a759eedf9e..c4374918da 100644 --- a/src/business/business-gnome/dialog-invoice.c +++ b/src/business/business-gnome/dialog-invoice.c @@ -2177,24 +2177,25 @@ gnc_invoice_save_page (InvoiceWindow *iw, GKeyFile *key_file, const gchar *group_name) { + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(&iw->invoice_guid, guidstr); g_key_file_set_string(key_file, group_name, KEY_INVOICE_TYPE, InvoiceDialogTypeasString(iw->dialog_type)); - g_key_file_set_string(key_file, group_name, KEY_INVOICE_GUID, - guid_to_string(&iw->invoice_guid)); + g_key_file_set_string(key_file, group_name, KEY_INVOICE_GUID, guidstr); if (gncOwnerGetJob (&(iw->job))) { g_key_file_set_string(key_file, group_name, KEY_OWNER_TYPE, qofOwnerGetType(&iw->job)); - g_key_file_set_string(key_file, group_name, KEY_OWNER_GUID, - guid_to_string(gncOwnerGetGUID(&iw->job))); + guid_to_string_buff(gncOwnerGetGUID(&iw->job), guidstr); + g_key_file_set_string(key_file, group_name, KEY_OWNER_GUID, guidstr); } else { g_key_file_set_string(key_file, group_name, KEY_OWNER_TYPE, qofOwnerGetType(&iw->owner)); - g_key_file_set_string(key_file, group_name, KEY_OWNER_GUID, - guid_to_string(gncOwnerGetGUID(&iw->owner))); + guid_to_string_buff(gncOwnerGetGUID(&iw->owner), guidstr); + g_key_file_set_string(key_file, group_name, KEY_OWNER_GUID, guidstr); } } diff --git a/src/doc/design/engine.texi b/src/doc/design/engine.texi index dc1de55944..e5a1ab4471 100644 --- a/src/doc/design/engine.texi +++ b/src/doc/design/engine.texi @@ -287,12 +287,12 @@ Return the @code{memcmp} of the two GUID's. You can encode and decode GUIDs and their string representations using the next two functions. -@deftypefun {const char *} guid_to_string (const GUID * @var{guid}) +@deftypefun {gchar *} guid_to_string (const GUID * @var{guid}) Return a null-terminated string encoding of @var{guid}. String encodings of identifiers are hex numbers printed only with the characters @code{0} through @code{9} and @code{a} through @code{f}. The encoding will always be @code{GUID_ENCODING_LENGTH} characters long. The returned -string must NOT be freed when no longer needed. +string must be freed when no longer needed using g_free. @end deftypefun @deftypefun {char *} guid_to_string_buff (const GUID * @var{guid}, char * @var{buff}) diff --git a/src/engine/SchedXaction.c b/src/engine/SchedXaction.c index c794bac407..2f8a47f359 100644 --- a/src/engine/SchedXaction.c +++ b/src/engine/SchedXaction.c @@ -380,6 +380,7 @@ xaccSchedXactionInit(SchedXaction *sx, QofBook *book) { Account *ra; const GncGUID *guid; + gchar guidstr[GUID_ENCODING_LENGTH+1]; qof_instance_init_data (&sx->inst, GNC_ID_SCHEDXACTION, book); @@ -387,7 +388,8 @@ xaccSchedXactionInit(SchedXaction *sx, QofBook *book) sx->template_acct = xaccMallocAccount(book); guid = qof_instance_get_guid( sx ); xaccAccountBeginEdit( sx->template_acct ); - xaccAccountSetName( sx->template_acct, guid_to_string( guid )); + guid_to_string_buff( guid, guidstr ); + xaccAccountSetName( sx->template_acct, guidstr); xaccAccountSetCommodity (sx->template_acct, gnc_commodity_table_lookup( gnc_commodity_table_get_table(book), diff --git a/src/engine/Split.c b/src/engine/Split.c index 53fa590474..1d539e428f 100644 --- a/src/engine/Split.c +++ b/src/engine/Split.c @@ -1450,8 +1450,10 @@ xaccSplitConvertAmount (const Split *split, const Account * account) xaccAccountGetCommodity(xaccSplitGetAccount(osplit)); if (!gnc_commodity_equal(to_commodity, split_comm)) { + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(xaccSplitGetGUID(osplit),guidstr); PERR("The split's (%s) amount can't be converted from %s into %s.", - guid_to_string(xaccSplitGetGUID(osplit)), + guidstr, gnc_commodity_get_mnemonic(split_comm), gnc_commodity_get_mnemonic(to_commodity) ); diff --git a/src/engine/Transaction.c b/src/engine/Transaction.c index 5146826b01..5a0d634de4 100644 --- a/src/engine/Transaction.c +++ b/src/engine/Transaction.c @@ -971,8 +971,10 @@ xaccTransEqual(const Transaction *ta, const Transaction *tb, if (!node_b) { - PINFO ("first has split %s and second does not", - guid_to_string (xaccSplitGetGUID (split_a))); + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff (xaccSplitGetGUID (split_a),guidstr); + + PINFO ("first has split %s and second does not",guidstr); return FALSE; } diff --git a/src/engine/gncBillTerm.c b/src/engine/gncBillTerm.c index 9f2c7b97dd..d65b1bd264 100644 --- a/src/engine/gncBillTerm.c +++ b/src/engine/gncBillTerm.c @@ -266,9 +266,10 @@ GncBillTerm * gncBillTermCreate (QofBook *book) void gncBillTermDestroy (GncBillTerm *term) { + gchar guidstr[GUID_ENCODING_LENGTH+1]; if (!term) return; - DEBUG("destroying bill term %s (%p)", - guid_to_string(qof_instance_get_guid(&term->inst)), term); + guid_to_string_buff(qof_instance_get_guid(&term->inst),guidstr); + DEBUG("destroying bill term %s (%p)", guidstr, term); qof_instance_set_destroying(term, TRUE); qof_instance_set_dirty (&term->inst); gncBillTermCommitEdit (term); diff --git a/src/engine/test/utest-Split.cpp b/src/engine/test/utest-Split.cpp index e4165e578c..fa149b95e1 100644 --- a/src/engine/test/utest-Split.cpp +++ b/src/engine/test/utest-Split.cpp @@ -974,6 +974,7 @@ test_xaccSplitConvertAmount (void) "GNCXX", "", 1000); gnc_commodity *gnm = gnc_commodity_new (book, "Gnome, Inc.", "NYSE", "GNM", "", 1000); + gchar guidstr[GUID_ENCODING_LENGTH+1]; Account *acc = xaccMallocAccount (book); Account *o_acc = xaccMallocAccount (book); @@ -991,7 +992,8 @@ test_xaccSplitConvertAmount (void) TestErrorStruct check = { loglevel, logdomain, NULL, 0 }; GLogFunc oldlogger = g_log_set_default_handler ((GLogFunc)test_null_handler, &check); - check.msg = g_strdup_printf ("[xaccSplitConvertAmount()] The split's (%s) amount can't be converted from GNCXX into GNM.", guid_to_string(xaccSplitGetGUID(o_split))); + guid_to_string_buff(xaccSplitGetGUID(o_split), guidstr); + check.msg = g_strdup_printf ("[xaccSplitConvertAmount()] The split's (%s) amount can't be converted from GNCXX into GNM.", guidstr); xaccAccountSetCommodity (acc, gnaira); xaccAccountSetCommodity (o_acc, gnaira); xaccAccountSetCommodity (ya_acc, gnm); diff --git a/src/experimental/cgi-bin/gnc-server.c b/src/experimental/cgi-bin/gnc-server.c index 53f96aed90..719bb67196 100644 --- a/src/experimental/cgi-bin/gnc-server.c +++ b/src/experimental/cgi-bin/gnc-server.c @@ -105,7 +105,7 @@ GList * logged_in_users = NULL; */ static const char * -auth_user (const char * name, const char *passwd) +auth_user (const char * name, const char *passwd, char *buff) { GncGUID *guid; const char *session_auth_string; @@ -115,11 +115,11 @@ auth_user (const char * name, const char *passwd) */ if (!name || !passwd) return NULL; - guid = g_new (GncGUID, 1); - guid_replace (guid); + guid = guid_new(); logged_in_users = g_list_prepend (logged_in_users, guid); - session_auth_string = guid_to_string (guid); /* THREAD UNSAFE */ - return session_auth_string; + + guid_to_string_buffer (guid, buff); + return buff; } /* @@ -244,6 +244,7 @@ main (int argc, char *argv[]) const char *user_agent; const char *auth_string; const char *content_length; + gchar guidstr[GUID_ENCODING_LENGTH+1]; int read_len = 0; int send_accts = 0; @@ -301,7 +302,7 @@ main (int argc, char *argv[]) char *name = NULL, *passwd = NULL; parse_for_login (request_bufp, &name, &passwd); - auth_string = auth_user (name, passwd); + auth_string = auth_user (name, passwd, guidstr); if (!auth_string) { reject_auth(); diff --git a/src/gnome/dialog-sx-editor.c b/src/gnome/dialog-sx-editor.c index cdc3e87d7f..2013a5e055 100644 --- a/src/gnome/dialog-sx-editor.c +++ b/src/gnome/dialog-sx-editor.c @@ -1285,9 +1285,7 @@ schedXact_editor_create_ledger( GncSxEditorDialog *sxed ) GtkWidget *main_vbox; /* Create the ledger */ - /* THREAD-UNSAFE */ - sxed->sxGUIDstr = g_strdup( guid_to_string( - xaccSchedXactionGetGUID(sxed->sx) ) ); + sxed->sxGUIDstr = guid_to_string( xaccSchedXactionGetGUID(sxed->sx) ); sxed->ledger = gnc_ledger_display_template_gl( sxed->sxGUIDstr ); splitreg = gnc_ledger_display_get_split_register( sxed->ledger ); diff --git a/src/gnome/dialog-sx-editor2.c b/src/gnome/dialog-sx-editor2.c index a5c5d61a11..1344f4402a 100644 --- a/src/gnome/dialog-sx-editor2.c +++ b/src/gnome/dialog-sx-editor2.c @@ -1276,8 +1276,7 @@ schedXact_editor_create_ledger (GncSxEditorDialog2 *sxed) GtkWidget *label; /* Create the ledger */ - /* THREAD-UNSAFE */ - sxed->sxGUIDstr = g_strdup (guid_to_string (xaccSchedXactionGetGUID (sxed->sx))); + sxed->sxGUIDstr = guid_to_string (xaccSchedXactionGetGUID (sxed->sx)); sxed->ledger = gnc_ledger_display2_template_gl (sxed->sxGUIDstr); model = gnc_ledger_display2_get_split_model_register (sxed->ledger); diff --git a/src/gnome/gnc-budget-view.c b/src/gnome/gnc-budget-view.c index 268699babb..a497cced2a 100644 --- a/src/gnome/gnc-budget-view.c +++ b/src/gnome/gnc-budget-view.c @@ -289,6 +289,7 @@ gbv_create_widget(GncBudgetView *view) GtkTreeIter iter; GtkWidget* h_separator; gchar *state_section; + gchar guidstr[GUID_ENCODING_LENGTH+1]; priv = GNC_BUDGET_VIEW_GET_PRIVATE(view); vbox = GTK_VBOX(view); @@ -315,7 +316,8 @@ gbv_create_widget(GncBudgetView *view) tree_view = gnc_tree_view_account_new(FALSE); gtk_container_add(GTK_CONTAINER(inner_scrolled_window), GTK_WIDGET(tree_view)); - state_section = g_strjoin(" ", STATE_SECTION_PREFIX, guid_to_string(&priv->key), NULL); + guid_to_string_buff(&priv->key, guidstr); + state_section = g_strjoin(" ", STATE_SECTION_PREFIX, guidstr, NULL); g_object_set(G_OBJECT(tree_view), "state-section", state_section, NULL); g_free (state_section); @@ -487,13 +489,16 @@ void gnc_budget_view_delete_budget(GncBudgetView *view) { GncBudgetViewPrivate *priv; + gchar guidstr[GUID_ENCODING_LENGTH+1]; g_return_if_fail(view != NULL); ENTER("view %p", view); priv = GNC_BUDGET_VIEW_GET_PRIVATE (view); - gnc_state_drop_sections_for (guid_to_string (&priv->key)); + + guid_to_string_buff(&priv->key, guidstr); + gnc_state_drop_sections_for (guidstr); g_object_set (G_OBJECT (priv->tree_view), "state-section", NULL, NULL); LEAVE(" "); diff --git a/src/gnome/gnc-plugin-page-account-tree.c b/src/gnome/gnc-plugin-page-account-tree.c index d191044bcf..9c3df362e5 100644 --- a/src/gnome/gnc-plugin-page-account-tree.c +++ b/src/gnome/gnc-plugin-page-account-tree.c @@ -1397,7 +1397,7 @@ gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPag { GList *acct_list, *ptr; const GncGUID *guid; - const gchar *guid_str; + gchar guidstr[GUID_ENCODING_LENGTH+1]; gnc_set_busy_cursor(NULL, TRUE); gnc_suspend_gui_refresh (); @@ -1435,16 +1435,16 @@ gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPag for (ptr = acct_list; ptr; ptr = g_list_next(ptr)) { guid = xaccAccountGetGUID (ptr->data); - guid_str = guid_to_string (guid); - gnc_state_drop_sections_for (guid_str); + guid_to_string_buff (guid, guidstr); + gnc_state_drop_sections_for (guidstr); } g_list_free(acct_list); /* Drop all references from the state file for this account */ guid = xaccAccountGetGUID (account); - guid_str = guid_to_string (guid); - gnc_state_drop_sections_for (guid_str); + guid_to_string_buff (guid, guidstr); + gnc_state_drop_sections_for (guidstr); /* * Finally, delete the account, any subaccounts it may still diff --git a/src/gnome/gnc-split-reg.c b/src/gnome/gnc-split-reg.c index e5e56ac745..544360b2e3 100644 --- a/src/gnome/gnc-split-reg.c +++ b/src/gnome/gnc-split-reg.c @@ -385,16 +385,15 @@ static void gsr_create_table( GNCSplitReg *gsr ) { - GtkWidget *register_widget; - SplitRegister *sr; + GtkWidget *register_widget = NULL; + SplitRegister *sr = NULL; - gchar *state_section; - const GncGUID * guid; - Account * account; - - account = gnc_ledger_display_leader(gsr->ledger); - guid = xaccAccountGetGUID(account); - state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", (gchar*)guid_to_string (guid), NULL); + Account * account = gnc_ledger_display_leader(gsr->ledger); + const GncGUID * guid = xaccAccountGetGUID(account); + gchar guidstr[GUID_ENCODING_LENGTH+1]; + gchar *state_section = NULL; + guid_to_string_buff(guid, guidstr); + state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr, NULL); ENTER("gsr=%p", gsr); @@ -693,13 +692,14 @@ gnc_split_reg_ld_destroy( GNCLedgerDisplay *ledger ) { GNCSplitReg *gsr = gnc_ledger_display_get_user_data( ledger ); + Account * account = gnc_ledger_display_leader(ledger); + const GncGUID * guid = xaccAccountGetGUID(account); + gchar guidstr[GUID_ENCODING_LENGTH+1]; gchar *state_section; - const GncGUID * guid; - Account * account; - account = gnc_ledger_display_leader(ledger); - guid = xaccAccountGetGUID(account); - state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ",(gchar*)guid_to_string (guid), NULL); + guid_to_string_buff(guid, guidstr); + + state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr, NULL); if (gsr) { diff --git a/src/gnome/gnc-split-reg2.c b/src/gnome/gnc-split-reg2.c index 429b983ec4..4dfa3533b2 100644 --- a/src/gnome/gnc-split-reg2.c +++ b/src/gnome/gnc-split-reg2.c @@ -262,9 +262,17 @@ gsr2_create_table (GNCSplitReg2 *gsr) if (ledger_type == LD2_GL && model->type == GENERAL_LEDGER2) state_section = g_strdup (STATE_SECTION_GEN_LEDGER); else if (ledger_type == LD2_SUBACCOUNT) - state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", (gchar*)guid_to_string (guid), " w/subaccounts", NULL); + { + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff (guid, guidstr); + state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr, " w/subaccounts", NULL); + } else - state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", (gchar*)guid_to_string (guid), NULL); + { + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff (guid, guidstr); + state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr, NULL); + } g_object_set (G_OBJECT (view), "state-section", state_section, "show-column-menu", FALSE, NULL); @@ -680,31 +688,6 @@ gsr2_redraw_all_cb (GncTreeViewSplitReg *view, gpointer user_data) static void gnc_split_reg2_ld_destroy (GNCLedgerDisplay2 *ledger) { - GNCSplitReg2 *gsr = gnc_ledger_display2_get_user_data (ledger); - - gchar *state_key; - const GncGUID * guid; - Account * account; - - account = gnc_ledger_display2_leader (ledger); - guid = xaccAccountGetGUID (account); - state_key = (gchar*)guid_to_string (guid); - - if (gsr) - { - GncTreeModelSplitReg *model; - - model = gnc_ledger_display2_get_split_model_register (ledger); - -/*FIXME This may not be required - if (model && model->table) - gnc_table_save_state (model->table, state_key); -*/ - /* - * Don't destroy the window here any more. The register no longer - * owns it. - */ - } gnc_ledger_display2_set_user_data (ledger, NULL); } diff --git a/src/gnome/top-level.c b/src/gnome/top-level.c index f9043e4981..9a145d638d 100644 --- a/src/gnome/top-level.c +++ b/src/gnome/top-level.c @@ -309,7 +309,7 @@ static void gnc_save_all_state (gpointer session, gpointer unused) { QofBook *book; - const gchar *guid_string; + gchar guid_string[GUID_ENCODING_LENGTH+1]; const GncGUID *guid; GError *error = NULL; GKeyFile *keyfile = NULL; @@ -338,7 +338,7 @@ gnc_save_all_state (gpointer session, gpointer unused) /* Store the book's GncGUID in the top level group */ book = qof_session_get_book(session); guid = qof_entity_get_guid(QOF_INSTANCE(book)); - guid_string = guid_to_string(guid); + guid_to_string_buff(guid, guid_string); g_key_file_set_string(keyfile, STATE_FILE_TOP, STATE_FILE_BOOK_GUID, guid_string); diff --git a/src/import-export/log-replay/gnc-log-replay.c b/src/import-export/log-replay/gnc-log-replay.c index bbd26d73e0..198964ba4f 100644 --- a/src/import-export/log-replay/gnc-log-replay.c +++ b/src/import-export/log-replay/gnc-log-replay.c @@ -284,11 +284,13 @@ static void dump_split_record(split_record record) } if (record.trans_guid_present) { - DEBUG("Transaction GncGUID: %s", guid_to_string (&(record.trans_guid))); + guid_to_string_buff(&record.trans_guid, string_buf); + DEBUG("Transaction GncGUID: %s", string_buf); } if (record.split_guid_present) { - DEBUG("Split GncGUID: %s", guid_to_string (&(record.split_guid))); + guid_to_string_buff(&record.split_guid, string_buf); + DEBUG("Split GncGUID: %s", string_buf); } if (record.log_date_present) { @@ -307,7 +309,8 @@ static void dump_split_record(split_record record) } if (record.acc_guid_present) { - DEBUG("Account GncGUID: %s", guid_to_string (&(record.acc_guid))); + guid_to_string_buff(&record.trans_guid, string_buf); + DEBUG("Account GncGUID: %s", string_buf); } if (record.acc_name_present) { diff --git a/src/libqof/qof/guid.cpp b/src/libqof/qof/guid.cpp index f69890c946..15e5245094 100644 --- a/src/libqof/qof/guid.cpp +++ b/src/libqof/qof/guid.cpp @@ -167,22 +167,22 @@ guid_new_return(void) return *ret; } -const char * +gchar * guid_to_string (const GncGUID * guid) { /* We need to malloc here, not 'new' because it will be freed by the caller which will use free (not delete).*/ - char * ret {reinterpret_cast (malloc (sizeof (char)*GUID_ENCODING_LENGTH+1))}; - gchar * temp {guid_to_string_buff(guid, ret)}; + gchar * ret {reinterpret_cast (g_malloc (sizeof (gchar)*GUID_ENCODING_LENGTH+1))}; + gchar * temp {guid_to_string_buff (guid, ret)}; if (!temp){ - delete[] ret; - return temp; + g_free (ret); + return nullptr; } return ret; } gchar * -guid_to_string_buff(const GncGUID * guid, char *str) +guid_to_string_buff (const GncGUID * guid, gchar *str) { if (!str || !guid) return NULL; diff --git a/src/libqof/qof/guid.h b/src/libqof/qof/guid.h index fd32446c5b..4c56841929 100644 --- a/src/libqof/qof/guid.h +++ b/src/libqof/qof/guid.h @@ -127,15 +127,15 @@ GncGUID *guid_copy (const GncGUID *guid); * encoding of the id. String encodings of identifiers are hex * numbers printed only with the characters '0' through '9' and * 'a' through 'f'. The encoding will always be GUID_ENCODING_LENGTH - * characters long. + * characters long (not including the null terminator). * * @param guid The guid to print. * * @return A pointer to the starting character of the string. The - * returned memory is owned by this routine and may not be freed by - * the caller. + * returned memory is owned by the calling routine and must be freed + * using g_free. */ -const gchar * guid_to_string (const GncGUID * guid); +gchar * guid_to_string (const GncGUID * guid); /** The guid_to_string_buff() routine puts a null-terminated string * encoding of the id into the memory pointed at by buff. The diff --git a/src/libqof/qof/kvp_frame.cpp b/src/libqof/qof/kvp_frame.cpp index 299eee5bdb..8d2fd84a0d 100644 --- a/src/libqof/qof/kvp_frame.cpp +++ b/src/libqof/qof/kvp_frame.cpp @@ -1568,9 +1568,9 @@ kvp_value_to_string(const KvpValue *val) break; case KVP_TYPE_GUID: - /* THREAD-UNSAFE */ - ctmp = guid_to_string(kvp_value_get_guid(val)); - tmp2 = g_strdup_printf("KVP_VALUE_GUID(%s)", ctmp ? ctmp : ""); + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(kvp_value_get_guid(val),guidstr); + tmp2 = g_strdup_printf("KVP_VALUE_GUID(%s)", guidstr); return tmp2; break; diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp index 26ec5b87f1..a8145790d4 100644 --- a/src/libqof/qof/qofinstance.cpp +++ b/src/libqof/qof/qofinstance.cpp @@ -691,8 +691,9 @@ qof_instance_print_dirty (const QofInstance *inst, gpointer dummy) priv = GET_PRIVATE(inst); if (priv->dirty) { - printf("%s instance %s is dirty.\n", inst->e_type, - guid_to_string(&priv->guid)); + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff(&priv->guid, guidstr); + printf("%s instance %s is dirty.\n", inst->e_type, guidstr); } } diff --git a/src/libqof/qof/qofquery.cpp b/src/libqof/qof/qofquery.cpp index fd2528caa1..7d2d0d6f1a 100644 --- a/src/libqof/qof/qofquery.cpp +++ b/src/libqof/qof/qofquery.cpp @@ -1779,9 +1779,9 @@ qof_query_printValueForParam (QofQueryPredData *pd, GString * gs) qof_query_printGuidMatch (pdata->options)); for (node = pdata->guids; node; node = node->next) { - /* THREAD-UNSAFE */ - g_string_append_printf (gs, ", guids: %s", - guid_to_string ((GncGUID *) node->data)); + gchar guidstr[GUID_ENCODING_LENGTH+1]; + guid_to_string_buff ((GncGUID *) node->data,guidstr); + g_string_append_printf (gs, ", guids: %s",guidstr); } return; } diff --git a/src/libqof/qof/test/test-gnc-guid.cpp b/src/libqof/qof/test/test-gnc-guid.cpp index 447e71e73d..82c1d711bf 100644 --- a/src/libqof/qof/test/test-gnc-guid.cpp +++ b/src/libqof/qof/test/test-gnc-guid.cpp @@ -69,16 +69,17 @@ static void test_gnc_guid_copy (void) { defined in the guid api. We then compare them.*/ static void test_gnc_guid_to_string (void) { GncGUID * guid {guid_malloc()}; + gchar guidstrp [GUID_ENCODING_LENGTH+1]; + gchar guidstrp2[GUID_ENCODING_LENGTH+1]; g_assert (guid != nullptr); guid_replace (guid); string message {" using guid_to_string (deprecated): "}; - /*don't free the return value of guid_to_string!*/ - string guidstr {guid_to_string (guid)}; + guid_to_string_buff (guid,guidstrp); + string guidstr {guidstrp}; g_assert (guidstr.size () == GUID_ENCODING_LENGTH); message += guidstr; g_test_message ("%s", message.c_str ()); message = " using guid_to_string_buff: "; - gchar guidstrp2 [GUID_ENCODING_LENGTH+1]; gchar * ret {guid_to_string_buff (guid, guidstrp2)}; g_assert (ret == guidstrp2 + GUID_ENCODING_LENGTH); string guidstr2 {guidstrp2}; diff --git a/src/libqof/qof/test/test-kvp_frame.c b/src/libqof/qof/test/test-kvp_frame.c index ee70a75fa0..d17306574a 100644 --- a/src/libqof/qof/test/test-kvp_frame.c +++ b/src/libqof/qof/test/test-kvp_frame.c @@ -980,7 +980,7 @@ test_binary_to_string( void ) static void test_kvp_value_to_string( void ) { - const gchar *str_tmp; + gchar guidstr[GUID_ENCODING_LENGTH+1]; gchar *str_tmp2, *str_tmp3; gchar *result; KvpValue *gint64_value; @@ -1038,8 +1038,8 @@ test_kvp_value_to_string( void ) result = kvp_value_to_string( guid_value ); g_assert( result ); - str_tmp = guid_to_string( kvp_value_get_guid( guid_value ) ); - str_tmp2 = g_strdup_printf("KVP_VALUE_GUID(%s)", str_tmp ? str_tmp : ""); + guid_to_string_buff( kvp_value_get_guid( guid_value ), guidstr); + str_tmp2 = g_strdup_printf("KVP_VALUE_GUID(%s)", guidstr); g_assert_cmpstr( result, == , str_tmp2 ); g_free( result ); g_free( str_tmp2 ); From f40a93c6e1b27acaf7fd32bfca4c64ea27a2a860 Mon Sep 17 00:00:00 2001 From: lmat Date: Fri, 25 Jul 2014 17:38:33 -0400 Subject: [PATCH 5/9] Remove guid_init and guid_shutdown They no longer do anything, and it's not probable that they ever will. --- src/app-utils/test/test-scm-query-string.c | 1 - src/doc/design/engine.texi | 16 ------------- src/libqof/qof/guid.cpp | 13 ----------- src/libqof/qof/guid.h | 26 +++++----------------- src/libqof/qof/qofutil.cpp | 2 -- src/libqof/qof/qofutil.h | 6 ++--- src/libqof/qof/test/test-gnc-guid.cpp | 2 -- 7 files changed, 9 insertions(+), 57 deletions(-) diff --git a/src/app-utils/test/test-scm-query-string.c b/src/app-utils/test/test-scm-query-string.c index bb4119196a..448f0e47f6 100644 --- a/src/app-utils/test/test-scm-query-string.c +++ b/src/app-utils/test/test-scm-query-string.c @@ -103,7 +103,6 @@ main_helper (void *closure, int argc, char **argv) kvp_exclude_type (KVP_TYPE_DOUBLE); /* Initialize to a known RNG position */ - guid_init(); srand(1); run_tests (); diff --git a/src/doc/design/engine.texi b/src/doc/design/engine.texi index e5a1ab4471..77097d31c3 100644 --- a/src/doc/design/engine.texi +++ b/src/doc/design/engine.texi @@ -378,22 +378,6 @@ entity is not changed in any way. GUIDs are created by the GUID generator. The API for this generator is low-level and should not be used by user-code. -@deftypefun void guid_init (void) -Initialize the GUID generator with a variety of random sources including -common system files and /dev/random. -@end deftypefun - -@deftypefun void guid_init_with_salt (const void * @var{salt}, size_t @var{salt_len}) -Initialize the GUID generator with guid_init() and with the given -sequence of arbitrary binary data. -@end deftypefun - -@deftypefun void guid_init_only_salt (const void * @var{salt}, size_t @var{salt_len}) -Initialize the GUID generator using only the given sequence of arbitrary -binary data. This provides a way to reliably obtain a given sequence of -GUIDs. -@end deftypefun - @deftypefun void guid_replace (GUID * @var{guid}) Create a new GUID and store it in @var{guid}. This is a low-level function! GnuCash code should use @code{xaccGUIDNew}. diff --git a/src/libqof/qof/guid.cpp b/src/libqof/qof/guid.cpp index 15e5245094..edd1fa2f97 100644 --- a/src/libqof/qof/guid.cpp +++ b/src/libqof/qof/guid.cpp @@ -124,19 +124,6 @@ guid_null(void) return nullguid; } -/* Function implementations ****************************************/ - -void -guid_init(void) -{ - /*Boost takes care of this*/ -} - -void -guid_shutdown (void) -{ -} - /*Takes an allocated guid pointer and constructs it in place*/ void guid_replace(GncGUID *guid) diff --git a/src/libqof/qof/guid.h b/src/libqof/qof/guid.h index 4c56841929..78040d28cf 100644 --- a/src/libqof/qof/guid.h +++ b/src/libqof/qof/guid.h @@ -71,22 +71,6 @@ const GncGUID* gnc_value_get_guid (const GValue *value); * not including the null terminator. */ #define GUID_ENCODING_LENGTH 32 - -/** Initialize the id generator with a variety of random - * sources. - * - * @note Only one of guid_init(), guid_init_with_salt() and - * guid_init_only_salt() should be called. Calling any - * initialization function a second time will reset the generator and - * erase the effect of the first call. - */ -void guid_init(void); - -/** Release the memory chunk associated with gui storage. Use this - * only when shutting down the program, as it invalidates *all* - * GUIDs at once. */ -void guid_shutdown (void); - /** Generate a new guid. * * @param guid A pointer to an allocated guid data structure. The @@ -94,11 +78,9 @@ void guid_shutdown (void); */ void guid_replace (GncGUID *guid); -/** Generate a new id. If no initialization function has been called, - * guid_init() will be called before the id is created. +/** Generate a new id. * - * @return guid A data structure containing a newly allocated GncGUID. - * Caller is responsible for calling guid_free(). + * @return guid A data structure containing a copy of a newly constructed GncGUID. */ GncGUID guid_new_return (void); @@ -121,6 +103,10 @@ GncGUID * guid_new (void); /*Free the guid pointed to. Do not use this guid any more.*/ void guid_free (GncGUID *guid); +/** + * Returns a newly allocated GncGUID that matches the passed-in GUID. + * The returned pointer must be freed using guid_free. + */ GncGUID *guid_copy (const GncGUID *guid); /** The guid_to_string() routine returns a null-terminated string diff --git a/src/libqof/qof/qofutil.cpp b/src/libqof/qof/qofutil.cpp index 2990fcea58..2881fd73d8 100644 --- a/src/libqof/qof/qofutil.cpp +++ b/src/libqof/qof/qofutil.cpp @@ -263,7 +263,6 @@ qof_init (void) #endif qof_log_init(); qof_string_cache_init(); - guid_init (); qof_object_initialize (); qof_query_init (); qof_book_register (); @@ -274,7 +273,6 @@ qof_close(void) { qof_query_shutdown (); qof_object_shutdown (); - guid_shutdown (); qof_finalize_backend_libraries(); qof_string_cache_destroy (); qof_log_shutdown(); diff --git a/src/libqof/qof/qofutil.h b/src/libqof/qof/qofutil.h index 3d61f6d179..0bb0a2d1df 100644 --- a/src/libqof/qof/qofutil.h +++ b/src/libqof/qof/qofutil.h @@ -154,15 +154,15 @@ extern "C" /** \brief Initialise the Query Object Framework -Use in place of separate init functions (like guid_init() -and qof_query_init() etc.) to protect against future changes. +Use in place of separate init functions (like qof_query_init(), +etc.) to protect against future changes. */ void qof_init (void); /** \brief Safely close down the Query Object Framework Use in place of separate close / shutdown functions -(like guid_shutdown(), qof_query_shutdown() etc.) to protect +(like qof_query_shutdown(), etc.) to protect against future changes. */ void qof_close (void); diff --git a/src/libqof/qof/test/test-gnc-guid.cpp b/src/libqof/qof/test/test-gnc-guid.cpp index 82c1d711bf..bebd5c96d3 100644 --- a/src/libqof/qof/test/test-gnc-guid.cpp +++ b/src/libqof/qof/test/test-gnc-guid.cpp @@ -150,12 +150,10 @@ static void test_gnc_guid_roundtrip (void) { void test_suite_gnc_guid (void) { - guid_init (); GNC_TEST_ADD_FUNC (suitename, "gnc create guid", test_create_gnc_guid); GNC_TEST_ADD_FUNC (suitename, "gnc copy guid", test_gnc_guid_copy); GNC_TEST_ADD_FUNC (suitename, "gnc guid to string", test_gnc_guid_to_string); GNC_TEST_ADD_FUNC (suitename, "gnc guid equal", test_gnc_guid_equals); GNC_TEST_ADD_FUNC (suitename, "gnc guid string roundtrip", test_gnc_guid_roundtrip); - guid_shutdown (); } From cbc292cc91718ce5fb45b7b2e4ce70c74ef1c556 Mon Sep 17 00:00:00 2001 From: lmat Date: Mon, 28 Jul 2014 11:15:28 -0400 Subject: [PATCH 6/9] Removed the md5 file and updated the build system. We no longer need md5.h or md5.c because all that work is done in the boost uuid implementation. --- src/libqof/qof/Makefile.am | 9 - src/libqof/qof/guid.cpp | 1 - src/libqof/qof/md5.c | 445 ------------------------------------- src/libqof/qof/md5.h | 163 -------------- 4 files changed, 618 deletions(-) delete mode 100644 src/libqof/qof/md5.c delete mode 100644 src/libqof/qof/md5.h diff --git a/src/libqof/qof/Makefile.am b/src/libqof/qof/Makefile.am index 8bc270d08d..a1e3552090 100644 --- a/src/libqof/qof/Makefile.am +++ b/src/libqof/qof/Makefile.am @@ -75,7 +75,6 @@ qofinclude_HEADERS = \ qof-gobject.h noinst_HEADERS = \ - md5.h \ qofbook-p.h \ qofclass-p.h \ qofevent-p.h \ @@ -84,14 +83,6 @@ noinst_HEADERS = \ qofquery-p.h \ qofquerycore-p.h \ qofsession-p.h - -# Must compile md5.c without strict aliasing, otherwise function md5_finish_ctx -# gets "dereferencing type-punned pointer will break strict-aliasing rules" -noinst_LTLIBRARIES = libmd5.la -libmd5_la_SOURCES = md5.c -libmd5_la_CFLAGS = ${AM_CFLAGS} -fno-strict-aliasing - -libgnc_qof_la_LIBADD += libmd5.la EXTRA_DIST += \ qofmath128.cpp diff --git a/src/libqof/qof/guid.cpp b/src/libqof/qof/guid.cpp index edd1fa2f97..2f5f2b433b 100644 --- a/src/libqof/qof/guid.cpp +++ b/src/libqof/qof/guid.cpp @@ -50,7 +50,6 @@ extern "C" # include #endif #include "qof.h" -#include "md5.h" } #include diff --git a/src/libqof/qof/md5.c b/src/libqof/qof/md5.c deleted file mode 100644 index 8912106663..0000000000 --- a/src/libqof/qof/md5.c +++ /dev/null @@ -1,445 +0,0 @@ -/* md5.c - Functions to compute MD5 message digest of files or memory blocks - according to the definition of MD5 in RFC 1321 from April 1992. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - NOTE: The canonical source of this file is maintained with the GNU C - Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Ulrich Drepper , 1995. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#if STDC_HEADERS || defined _LIBC -# include -# include -#else -# ifndef HAVE_MEMCPY -#include -/* # define memcpy(d, s, n) bcopy ((s), (d), (n)) */ -# endif -#endif - -#include "md5.h" - -#ifdef _LIBC -# include -# if __BYTE_ORDER == __BIG_ENDIAN -# define WORDS_BIGENDIAN 1 -# endif -#endif - -#ifdef WORDS_BIGENDIAN -# define SWAP(n) \ - (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) -#else -# define SWAP(n) (n) -#endif - - -/* This array contains the bytes used to pad the buffer to the next - 64-byte boundary. (RFC 1321, 3.1: Step 1) */ -static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; - - -/* Initialize structure containing state of computation. - (RFC 1321, 3.3: Step 3) */ -void -md5_init_ctx (ctx) -struct md5_ctx *ctx; -{ - ctx->A = 0x67452301; - ctx->B = 0xefcdab89; - ctx->C = 0x98badcfe; - ctx->D = 0x10325476; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -/* Put result from CTX in first 16 bytes following RESBUF. The result - must be in little endian byte order. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -void * -md5_read_ctx (ctx, resbuf) -const struct md5_ctx *ctx; -void *resbuf; -{ - ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); - ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); - ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); - ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -void * -md5_finish_ctx (ctx, resbuf) -struct md5_ctx *ctx; -void *resbuf; -{ - /* Take yet unprocessed bytes into account. */ - md5_uint32 bytes = ctx->buflen; - size_t pad; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if (ctx->total[0] < bytes) - ++ctx->total[1]; - - pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; - memcpy (&ctx->buffer[bytes], fillbuf, pad); - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); - *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | - (ctx->total[0] >> 29)); - - /* Process last bytes. */ - md5_process_block (ctx->buffer, bytes + pad + 8, ctx); - - return md5_read_ctx (ctx, resbuf); -} - -/* Compute MD5 message digest for bytes read from STREAM. The - resulting message digest number will be written into the 16 bytes - beginning at RESBLOCK. */ -int -md5_stream (stream, resblock) -FILE *stream; -void *resblock; -{ - /* Important: BLOCKSIZE must be a multiple of 64. */ -#define BLOCKSIZE 4096 - struct md5_ctx ctx; - char buffer[BLOCKSIZE + 72]; - size_t sum; - - /* Initialize the computation context. */ - md5_init_ctx (&ctx); - - /* Iterate over full file contents. */ - while (1) - { - /* We read the file in blocks of BLOCKSIZE bytes. One call of the - computation function processes the whole buffer so that with the - next round of the loop another block can be read. */ - size_t n; - sum = 0; - - /* Read block. Take care for partial reads. */ - do - { - n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); - - sum += n; - } - while (sum < BLOCKSIZE && n != 0); - if (n == 0 && ferror (stream)) - return 1; - - /* If end of file is reached, end the loop. */ - if (n == 0) - break; - - /* Process buffer with BLOCKSIZE bytes. Note that - BLOCKSIZE % 64 == 0 - */ - md5_process_block (buffer, BLOCKSIZE, &ctx); - } - - /* Add the last bytes if necessary. */ - if (sum > 0) - md5_process_bytes (buffer, sum, &ctx); - - /* Construct result in desired memory. */ - md5_finish_ctx (&ctx, resblock); - return 0; -} - -/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void * -md5_buffer (buffer, len, resblock) -const char *buffer; -size_t len; -void *resblock; -{ - struct md5_ctx ctx; - - /* Initialize the computation context. */ - md5_init_ctx (&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - md5_process_bytes (buffer, len, &ctx); - - /* Put result in desired memory area. */ - return md5_finish_ctx (&ctx, resblock); -} - - -void -md5_process_bytes (buffer, len, ctx) -const void *buffer; -size_t len; -struct md5_ctx *ctx; -{ -#define NUM_MD5_WORDS 1024 - size_t add = 0; - - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if (ctx->buflen != 0) - { - size_t left_over = ctx->buflen; - - add = 128 - left_over > len ? len : 128 - left_over; - - memcpy (&ctx->buffer[left_over], buffer, add); - ctx->buflen += add; - - if (left_over + add > 64) - { - md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx); - /* The regions in the following copy operation cannot overlap. */ - memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], - (left_over + add) & 63); - ctx->buflen = (left_over + add) & 63; - } - - buffer = (const char *) buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if (len > 64) - { - if ((add & 3) == 0) /* buffer is still 32-bit aligned */ - { - md5_process_block (buffer, len & ~63, ctx); - buffer = (const char *) buffer + (len & ~63); - } - else /* buffer is not 32-bit aligned */ - { - md5_uint32 md5_buffer[NUM_MD5_WORDS]; - size_t num_bytes; - size_t buf_bytes; - - num_bytes = len & ~63; - while (num_bytes > 0) - { - buf_bytes = (num_bytes < sizeof(md5_buffer)) ? - num_bytes : sizeof(md5_buffer); - memcpy (md5_buffer, buffer, buf_bytes); - md5_process_block (md5_buffer, buf_bytes, ctx); - num_bytes -= buf_bytes; - buffer = (const char *) buffer + buf_bytes; - } - } - - len &= 63; - } - - /* Move remaining bytes in internal buffer. */ - if (len > 0) - { - memcpy (ctx->buffer, buffer, len); - ctx->buflen = len; - } -} - - -/* These are the four functions used in the four steps of the MD5 algorithm - and defined in the RFC 1321. The first function is a little bit optimized - (as found in Colin Plumbs public domain implementation). */ -/* #define FF(b, c, d) ((b & c) | (~b & d)) */ -#define FF(b, c, d) (d ^ (b & (c ^ d))) -#define FG(b, c, d) FF (d, b, c) -#define FH(b, c, d) (b ^ c ^ d) -#define FI(b, c, d) (c ^ (b | ~d)) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. */ - -void -md5_process_block (buffer, len, ctx) -const void *buffer; -size_t len; -struct md5_ctx *ctx; -{ - md5_uint32 correct_words[16]; - const md5_uint32 *words = buffer; - size_t nwords = len / sizeof (md5_uint32); - const md5_uint32 *endp = words + nwords; - md5_uint32 A = ctx->A; - md5_uint32 B = ctx->B; - md5_uint32 C = ctx->C; - md5_uint32 D = ctx->D; - - /* First increment the byte count. RFC 1321 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += len; - if (ctx->total[0] < len) - ++ctx->total[1]; - - /* Process all bytes in the buffer with 64 bytes in each round of - the loop. */ - while (words < endp) - { - md5_uint32 *cwp = correct_words; - md5_uint32 A_save = A; - md5_uint32 B_save = B; - md5_uint32 C_save = C; - md5_uint32 D_save = D; - - /* First round: using the given function, the context and a constant - the next context is computed. Because the algorithms processing - unit is a 32-bit word and it is determined to work on words in - little endian byte order we perhaps have to change the byte order - before the computation. To reduce the work for the next steps - we store the swapped words in the array CORRECT_WORDS. */ - -#define OP(a, b, c, d, s, T) \ - do \ - { \ - a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ - ++words; \ - CYCLIC (a, s); \ - a += b; \ - } \ - while (0) - - /* It is unfortunate that C does not provide an operator for - cyclic rotation. Hope the C compiler is smart enough. */ -#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) - - /* Before we start, one word to the strange constants. - They are defined in RFC 1321 as - - T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 - */ - - /* Round 1. */ - OP (A, B, C, D, 7, 0xd76aa478); - OP (D, A, B, C, 12, 0xe8c7b756); - OP (C, D, A, B, 17, 0x242070db); - OP (B, C, D, A, 22, 0xc1bdceee); - OP (A, B, C, D, 7, 0xf57c0faf); - OP (D, A, B, C, 12, 0x4787c62a); - OP (C, D, A, B, 17, 0xa8304613); - OP (B, C, D, A, 22, 0xfd469501); - OP (A, B, C, D, 7, 0x698098d8); - OP (D, A, B, C, 12, 0x8b44f7af); - OP (C, D, A, B, 17, 0xffff5bb1); - OP (B, C, D, A, 22, 0x895cd7be); - OP (A, B, C, D, 7, 0x6b901122); - OP (D, A, B, C, 12, 0xfd987193); - OP (C, D, A, B, 17, 0xa679438e); - OP (B, C, D, A, 22, 0x49b40821); - - /* For the second to fourth round we have the possibly swapped words - in CORRECT_WORDS. Redefine the macro to take an additional first - argument specifying the function to use. */ -#undef OP -#define OP(f, a, b, c, d, k, s, T) \ - do \ - { \ - a += f (b, c, d) + correct_words[k] + T; \ - CYCLIC (a, s); \ - a += b; \ - } \ - while (0) - - /* Round 2. */ - OP (FG, A, B, C, D, 1, 5, 0xf61e2562); - OP (FG, D, A, B, C, 6, 9, 0xc040b340); - OP (FG, C, D, A, B, 11, 14, 0x265e5a51); - OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); - OP (FG, A, B, C, D, 5, 5, 0xd62f105d); - OP (FG, D, A, B, C, 10, 9, 0x02441453); - OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); - OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); - OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); - OP (FG, D, A, B, C, 14, 9, 0xc33707d6); - OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); - OP (FG, B, C, D, A, 8, 20, 0x455a14ed); - OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); - OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); - OP (FG, C, D, A, B, 7, 14, 0x676f02d9); - OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); - - /* Round 3. */ - OP (FH, A, B, C, D, 5, 4, 0xfffa3942); - OP (FH, D, A, B, C, 8, 11, 0x8771f681); - OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); - OP (FH, B, C, D, A, 14, 23, 0xfde5380c); - OP (FH, A, B, C, D, 1, 4, 0xa4beea44); - OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); - OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); - OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); - OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); - OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); - OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); - OP (FH, B, C, D, A, 6, 23, 0x04881d05); - OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); - OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); - OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); - OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); - - /* Round 4. */ - OP (FI, A, B, C, D, 0, 6, 0xf4292244); - OP (FI, D, A, B, C, 7, 10, 0x432aff97); - OP (FI, C, D, A, B, 14, 15, 0xab9423a7); - OP (FI, B, C, D, A, 5, 21, 0xfc93a039); - OP (FI, A, B, C, D, 12, 6, 0x655b59c3); - OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); - OP (FI, C, D, A, B, 10, 15, 0xffeff47d); - OP (FI, B, C, D, A, 1, 21, 0x85845dd1); - OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); - OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); - OP (FI, C, D, A, B, 6, 15, 0xa3014314); - OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); - OP (FI, A, B, C, D, 4, 6, 0xf7537e82); - OP (FI, D, A, B, C, 11, 10, 0xbd3af235); - OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); - OP (FI, B, C, D, A, 9, 21, 0xeb86d391); - - /* Add the starting values of the context. */ - A += A_save; - B += B_save; - C += C_save; - D += D_save; - } - - /* Put checksum in context given as argument. */ - ctx->A = A; - ctx->B = B; - ctx->C = C; - ctx->D = D; -} diff --git a/src/libqof/qof/md5.h b/src/libqof/qof/md5.h deleted file mode 100644 index e501b4363b..0000000000 --- a/src/libqof/qof/md5.h +++ /dev/null @@ -1,163 +0,0 @@ -/* md5.h - Declaration of functions and data types used for MD5 sum - computing library functions. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - NOTE: The canonical source of this file is maintained with the GNU C - Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _MD5_H -#define _MD5_H 1 - -#include -#include - -#if defined HAVE_LIMITS_H || _LIBC -# include -#endif - -/* The following contortions are an attempt to use the C preprocessor - to determine an unsigned integral type that is 32 bits wide. An - alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but - doing that would require that the configure script compile and *run* - the resulting executable. Locally running cross-compiled executables - is usually not possible. */ - -#ifdef _LIBC -# include -typedef u_int32_t md5_uint32; -#else -# if defined __STDC__ && __STDC__ -# define UINT_MAX_32_BITS 4294967295U -# else -# define UINT_MAX_32_BITS 0xFFFFFFFF -# endif - -/* If UINT_MAX isn't defined, assume it's a 32-bit type. - This should be valid for all systems GNU cares about because - that doesn't include 16-bit systems, and only modern systems - (that certainly have ) have 64+-bit integral types. */ - -# ifndef UINT_MAX -# define UINT_MAX UINT_MAX_32_BITS -# endif - -# if UINT_MAX == UINT_MAX_32_BITS -typedef unsigned int md5_uint32; -# else -# if USHRT_MAX == UINT_MAX_32_BITS -typedef unsigned short md5_uint32; -# else -# if ULONG_MAX == UINT_MAX_32_BITS -typedef unsigned long md5_uint32; -# else -/* The following line is intended to evoke an error. - Using #error is not portable enough. */ -"Cannot determine unsigned 32-bit data type." -# endif -# endif -# endif -#endif - -#undef __P -#if defined (__STDC__) && __STDC__ -#define __P(x) x -#else -#define __P(x) () -#endif - -/* Structure to save state of computation between the single steps. */ -struct md5_ctx -{ - md5_uint32 A; - md5_uint32 B; - md5_uint32 C; - md5_uint32 D; - - md5_uint32 total[2]; - md5_uint32 buflen; - char buffer[128]; -}; - -/* - * The following three functions are build up the low level used in - * the functions `md5_stream' and `md5_buffer'. - */ - -/* Initialize structure containing state of computation. - (RFC 1321, 3.3: Step 3) */ -extern void md5_init_ctx __P ((struct md5_ctx *ctx)); - - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - - It is necessary that LEN is a multiple of 64!!! - - IMPORTANT: On some systems it is required that buffer be 32-bit - aligned. */ -extern void md5_process_block __P ((const void *buffer, size_t len, - struct md5_ctx *ctx)); - -/* Starting with the result of former calls of this function (or the - initialization function) update the context for the next LEN bytes - starting at BUFFER. - - It is NOT required that LEN is a multiple of 64. - - IMPORTANT: On some systems it is required that buffer be 32-bit - aligned. */ -extern void md5_process_bytes __P ((const void *buffer, size_t len, - struct md5_ctx *ctx)); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 16 bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF be correctly - aligned for a 32 bits value. */ -extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf)); - - -/* Put result from CTX in first 16 bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF be correctly - aligned for a 32 bits value. */ -extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf)); - - -/* Compute MD5 message digest for bytes read from STREAM. The - resulting message digest number will be written into the 16 bytes - beginning at RESBLOCK. - - IMPORTANT: On some systems it is required that resblock be 32-bit - aligned. */ -extern int md5_stream __P ((FILE *stream, void *resblock)); - - -/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. - - IMPORTANT: On some systems it is required that buffer and resblock - be correctly 32-bit aligned. */ -extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock)); - -#endif From ce94872ec86c37fb49660004f97d0ce65905c475 Mon Sep 17 00:00:00 2001 From: lmat Date: Mon, 28 Jul 2014 16:52:22 -0400 Subject: [PATCH 7/9] Cleaned up some code and comments. There should be no impacting changes in this commit. --- src/libqof/qof/guid.cpp | 33 +++++++++++++--------------- src/libqof/qof/guid.h | 48 ++++++++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/libqof/qof/guid.cpp b/src/libqof/qof/guid.cpp index 2f5f2b433b..4fda852a5b 100644 --- a/src/libqof/qof/guid.cpp +++ b/src/libqof/qof/guid.cpp @@ -108,24 +108,21 @@ guid_copy (const GncGUID *guid) { const boost::uuids::uuid * old {reinterpret_cast (guid)}; boost::uuids::uuid * ret {new boost::uuids::uuid (*old)}; - return reinterpret_cast(ret); + return reinterpret_cast (ret); } -static GncGUID * nullguid {reinterpret_cast(new boost::uuids::uuid{0})}; +static GncGUID * nullguid {reinterpret_cast (new boost::uuids::uuid{0})}; /*It looks like we are expected to provide the same pointer every time from this function*/ const GncGUID * -guid_null(void) +guid_null (void) { - //static boost::uuids::nil_generator nil; - //boost::uuids::uuid * ret {new boost::uuids::uuid {0}}; - //return reinterpret_cast (ret); return nullguid; } /*Takes an allocated guid pointer and constructs it in place*/ void -guid_replace(GncGUID *guid) +guid_replace (GncGUID *guid) { static boost::uuids::random_generator gen; boost::uuids::uuid * val {reinterpret_cast (guid)}; @@ -142,7 +139,7 @@ guid_new (void) } GncGUID -guid_new_return(void) +guid_new_return (void) { /*we need to construct our value as a boost guid so that it can be deconstructed (in place) in guid_replace*/ @@ -196,16 +193,16 @@ guid_to_string_buff (const GncGUID * guid, gchar *str) } gboolean -string_to_guid(const char * str, GncGUID * guid) +string_to_guid (const char * str, GncGUID * guid) { static boost::uuids::string_generator strgen; boost::uuids::uuid * converted {reinterpret_cast (guid)}; - new (converted) boost::uuids::uuid (strgen(str)); + new (converted) boost::uuids::uuid (strgen (str)); return true; } gboolean -guid_equal(const GncGUID *guid_1, const GncGUID *guid_2) +guid_equal (const GncGUID *guid_1, const GncGUID *guid_2) { if (!guid_1 || !guid_2) return false; @@ -215,7 +212,7 @@ guid_equal(const GncGUID *guid_1, const GncGUID *guid_2) } gint -guid_compare(const GncGUID *guid_1, const GncGUID *guid_2) +guid_compare (const GncGUID *guid_1, const GncGUID *guid_2) { boost::uuids::uuid const * g1 {reinterpret_cast (guid_1)}; boost::uuids::uuid const * g2 {reinterpret_cast (guid_2)}; @@ -229,7 +226,7 @@ guid_compare(const GncGUID *guid_1, const GncGUID *guid_2) guint guid_hash_to_guint (gconstpointer ptr) { - const boost::uuids::uuid * guid = reinterpret_cast(ptr); + const boost::uuids::uuid * guid = reinterpret_cast (ptr); if (!guid) { @@ -239,8 +236,8 @@ guid_hash_to_guint (gconstpointer ptr) guint hash {0}; unsigned retspot {0}; - boost::uuids::uuid::const_iterator guidspot {guid->begin()}; - while (guidspot != guid->end()){ + boost::uuids::uuid::const_iterator guidspot {guid->begin ()}; + while (guidspot != guid->end ()){ hash <<= 4; hash |= *guidspot; ++guidspot; @@ -251,8 +248,8 @@ guid_hash_to_guint (gconstpointer ptr) gint guid_g_hash_table_equal (gconstpointer guid_a, gconstpointer guid_b) { - return guid_equal (reinterpret_cast(guid_a), - reinterpret_cast(guid_b)); + return guid_equal (reinterpret_cast (guid_a), + reinterpret_cast (guid_b)); } GHashTable * @@ -275,7 +272,7 @@ gnc_string_to_guid (const GValue *src, GValue *dest) as_string = g_value_get_string (src); guid = g_new0 (GncGUID, 1); - string_to_guid(as_string, guid); + string_to_guid (as_string, guid); g_value_take_boxed (dest, guid); } diff --git a/src/libqof/qof/guid.h b/src/libqof/qof/guid.h index 78040d28cf..6cdbc50ddc 100644 --- a/src/libqof/qof/guid.h +++ b/src/libqof/qof/guid.h @@ -1,6 +1,7 @@ /********************************************************************\ * guid.h -- globally unique ID User API * * Copyright (C) 2000 Dave Peticolas * + * 2014 Aaron Laws * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -29,45 +30,46 @@ extern "C" { #endif -typedef struct _gncGuid { - unsigned char reserved[16]; -} GncGUID; - #include #include /** @addtogroup Entity @{ */ /** @addtogroup GncGUID - Globally Unique ID's provide a way to uniquely identify - some thing. A GncGUID is a unique, cryptographically + Globally Unique IDs provide a way to uniquely identify + something. A GncGUID is a unique, cryptographically random 128-bit value. The identifier is so random that it is safe to assume that there is no other such item on the planet Earth, and indeed, not even in the Galaxy or beyond. - QOF GncGUID's can be used independently of any other subsystem + QOF GncGUIDs can be used independently of any other subsystem in QOF. In particular, they do not require the use of - other parts of the object subsystem. New GncGUID's are usually - created by initialising a new entity using qof_instance_init, + other parts of the object subsystem. New GncGUIDs are usually + created by initializing a new entity using qof_instance_init, rather than calling GncGUID functions directly. @{ */ /** @file guid.h @brief globally unique ID User API @author Copyright (C) 2000 Dave Peticolas + Copyright 2014 Aaron Laws */ -/** The type used to store guids */ #define GUID_DATA_SIZE 16 #define GNC_TYPE_GUID (gnc_guid_get_type()) #define GNC_VALUE_HOLDS_GUID(value) G_VALUE_HOLDS(value, GNC_TYPE_GUID) +/** The type used to store guids */ +typedef struct _gncGuid { + unsigned char reserved[GUID_DATA_SIZE]; +} GncGUID; + GType gnc_guid_get_type (void); const GncGUID* gnc_value_get_guid (const GValue *value); -/** number of characters needed to encode a guid as a string +/** Number of characters needed to encode a guid as a string * not including the null terminator. */ #define GUID_ENCODING_LENGTH 32 @@ -84,13 +86,15 @@ void guid_replace (GncGUID *guid); */ GncGUID guid_new_return (void); -/** Returns a GncGUID which is guaranteed -to never reference any entity. */ +/** Returns a GncGUID which is guaranteed to never reference any entity. + * + * Do not free this value! The same pointer is returned on each call.*/ const GncGUID * guid_null (void); /** - * Allocate memory for a GUID. The returned pointer must be freed with - * guid_free. + * Allocate memory for a GUID. This does not construct a GUID. In other words, + * the returned pointer has not necessarily been initialized. The returned + * pointer must be freed with * guid_free. */ GncGUID * guid_malloc (void); @@ -140,11 +144,15 @@ gchar * guid_to_string (const GncGUID * guid); gchar * guid_to_string_buff (const GncGUID * guid, /*@ out @*/ gchar *buff); -/** Given a string, decode the id into the guid if guid is non-NULL. - * The function returns TRUE if the string was a valid 32 character - * hexadecimal number. This function accepts both upper and lower case - * hex digits. If the return value is FALSE, the effect on guid is - * undefined. */ +/** Given a string, replace the given guid with the parsed one unless + * the given value is null. + * If null is passed as guid or string, false is returned and nothing + * is done, otherwise, the function returns true. + * This function accepts both uppor and lower case hex digits. If + * letters outside the range of [a-fA-F] are passed, they are silently + * replaced. If non-alphanumeric digits are given, this function will + either return false or replace those values with others. +. */ gboolean string_to_guid(const gchar * string, /*@ out @*/ GncGUID * guid); From 726ab02d651e10c520dba895d368b0760f3396e2 Mon Sep 17 00:00:00 2001 From: lmat Date: Mon, 28 Jul 2014 17:03:07 -0400 Subject: [PATCH 8/9] Simplified some of the GUID code. This change applies some recommendations from jralls. It better utilizes for loops, and usage of swap. We also try to make sure the null guid is not freed since it's reused, and catch a c++ exception to make sure it doens't escape into C code when parsing a GUID. --- src/libqof/qof/guid.cpp | 76 +++++++++++++++++++++-------------------- src/libqof/qof/guid.h | 4 +-- 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/libqof/qof/guid.cpp b/src/libqof/qof/guid.cpp index 4fda852a5b..73b913a2c1 100644 --- a/src/libqof/qof/guid.cpp +++ b/src/libqof/qof/guid.cpp @@ -85,6 +85,15 @@ gnc_value_get_guid (const GValue *value) return val; } +static GncGUID * nullguid {reinterpret_cast (new boost::uuids::uuid{0})}; + +/*It looks like we are expected to provide the same pointer every time from this function*/ +const GncGUID * +guid_null (void) +{ + return nullguid; +} + /* Memory management routines ***************************************/ GncGUID * @@ -99,7 +108,11 @@ guid_free (GncGUID *guid) { if (!guid) return; + if (guid == nullguid) + /*!!Don't delete that!!*/ + return; delete reinterpret_cast (guid); + guid = nullptr; } @@ -111,23 +124,15 @@ guid_copy (const GncGUID *guid) return reinterpret_cast (ret); } -static GncGUID * nullguid {reinterpret_cast (new boost::uuids::uuid{0})}; - -/*It looks like we are expected to provide the same pointer every time from this function*/ -const GncGUID * -guid_null (void) -{ - return nullguid; -} - /*Takes an allocated guid pointer and constructs it in place*/ void guid_replace (GncGUID *guid) { static boost::uuids::random_generator gen; boost::uuids::uuid * val {reinterpret_cast (guid)}; - val->boost::uuids::uuid::~uuid(); - new (val) boost::uuids::uuid (gen ()); + val->boost::uuids::uuid::~uuid (); + boost::uuids::uuid temp (gen ()); + val->swap (temp); } GncGUID * @@ -169,25 +174,13 @@ guid_to_string_buff (const GncGUID * guid, gchar *str) { if (!str || !guid) return NULL; - static boost::uuids::string_generator str_gen; - stringstream ostr; - boost::uuids::uuid const & tempg = *reinterpret_cast(guid); - ostr << tempg; - string const & val (ostr.str()); - /*unsigned size {val.size()}; - size must equal GUID_ENCODING_LENGTH*/ - unsigned stringspot{0}; - for (unsigned destspot{0}; destspot < GUID_ENCODING_LENGTH; ++destspot, ++stringspot){ - switch (stringspot){ - /*there are hyphens in boost's output, and we need to skip them in our output*/ - case 8: - case 13: - case 18: - case 23: - ++stringspot; - } - str[destspot] = val[stringspot]; - } + boost::uuids::uuid const & tempg = *reinterpret_cast (guid); + unsigned destspot {0}; + string const & val {to_string (tempg)}; + for (auto val_char : val) + if (val_char != '-') + str [destspot++] = val_char; + str[GUID_ENCODING_LENGTH] = '\0'; return &str[GUID_ENCODING_LENGTH]; } @@ -195,9 +188,19 @@ guid_to_string_buff (const GncGUID * guid, gchar *str) gboolean string_to_guid (const char * str, GncGUID * guid) { - static boost::uuids::string_generator strgen; - boost::uuids::uuid * converted {reinterpret_cast (guid)}; - new (converted) boost::uuids::uuid (strgen (str)); + if (!guid || !str) + return false; + + try + { + static boost::uuids::string_generator strgen; + boost::uuids::uuid * converted {reinterpret_cast (guid)}; + new (converted) boost::uuids::uuid (strgen (str)); + } + catch (...) + { + return false; + } return true; } @@ -236,11 +239,10 @@ guid_hash_to_guint (gconstpointer ptr) guint hash {0}; unsigned retspot {0}; - boost::uuids::uuid::const_iterator guidspot {guid->begin ()}; - while (guidspot != guid->end ()){ + for (auto guidspot : *guid) + { hash <<= 4; - hash |= *guidspot; - ++guidspot; + hash |= guidspot; } return hash; } diff --git a/src/libqof/qof/guid.h b/src/libqof/qof/guid.h index 6cdbc50ddc..7015e23503 100644 --- a/src/libqof/qof/guid.h +++ b/src/libqof/qof/guid.h @@ -151,8 +151,8 @@ gchar * guid_to_string_buff (const GncGUID * guid, /*@ out @*/ gchar *buff); * This function accepts both uppor and lower case hex digits. If * letters outside the range of [a-fA-F] are passed, they are silently * replaced. If non-alphanumeric digits are given, this function will - either return false or replace those values with others. -. */ + * either return false or replace those values with others. + */ gboolean string_to_guid(const gchar * string, /*@ out @*/ GncGUID * guid); From 9711ae244664bb5b6fb2f85bcafcfb526ca2c7a0 Mon Sep 17 00:00:00 2001 From: lmat Date: Wed, 30 Jul 2014 11:57:36 -0400 Subject: [PATCH 9/9] Added new tests. Added tests for string_to_guid and guid_replace. --- src/libqof/qof/test/test-gnc-guid.cpp | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/libqof/qof/test/test-gnc-guid.cpp b/src/libqof/qof/test/test-gnc-guid.cpp index bebd5c96d3..2fdda52964 100644 --- a/src/libqof/qof/test/test-gnc-guid.cpp +++ b/src/libqof/qof/test/test-gnc-guid.cpp @@ -148,6 +148,44 @@ static void test_gnc_guid_roundtrip (void) { guid_free (guid1); } +/** + * guid_replace should put a newly generated guid into the parameter. In + * this test, we ensure that the first "new" guid doesn't match a subsequent + * "new" guid in the same memory location. + */ +static void test_gnc_guid_replace (void) +{ + GncGUID * guid1 {guid_malloc ()}; + + guid_replace (guid1); + GncGUID * guid2 {guid_copy (guid1)}; + guid_replace (guid1); + g_assert (! guid_equal (guid1, guid2)); + + guid_free (guid2); + guid_free (guid1); +} + +/** + * We create a bogus guid and ensure that it doesn't get parsed successfully, + * then we pass in a good GUID from string and ensure that the function returns true. + */ +static void test_gnc_guid_from_string (void) { + GncGUID * guid {guid_malloc ()}; + const char * bogus {"01-23-45-6789a.cDeF0123z56789abcdef"}; + + /* string_to_guid should return false if either parameter is null*/ + g_assert (!string_to_guid (nullptr, guid)); + g_assert (!string_to_guid (bogus, nullptr)); + + g_assert (!string_to_guid (bogus, guid)); + + const char * good {"0123456789abcdef1234567890abcdef"}; + g_assert (string_to_guid (good, guid)); + + guid_free (guid); +} + void test_suite_gnc_guid (void) { GNC_TEST_ADD_FUNC (suitename, "gnc create guid", test_create_gnc_guid); @@ -155,5 +193,7 @@ void test_suite_gnc_guid (void) GNC_TEST_ADD_FUNC (suitename, "gnc guid to string", test_gnc_guid_to_string); GNC_TEST_ADD_FUNC (suitename, "gnc guid equal", test_gnc_guid_equals); GNC_TEST_ADD_FUNC (suitename, "gnc guid string roundtrip", test_gnc_guid_roundtrip); + GNC_TEST_ADD_FUNC (suitename, "gnc guid from string", test_gnc_guid_from_string); + GNC_TEST_ADD_FUNC (suitename, "gnc guid replace", test_gnc_guid_replace); }