From fc5a66f86db215a1ad16418c527bd6d79fd915a3 Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Sat, 6 Oct 2018 23:27:54 +0200 Subject: [PATCH] [misc] New utility functions: trim, atrim and safe_snprintf_cat --- src/db.c | 34 +++++++------------- src/lastfm.c | 4 +-- src/misc.c | 89 +++++++++++++++++++++++++++++++++++++++------------- src/misc.h | 14 +++++++-- 4 files changed, 91 insertions(+), 50 deletions(-) diff --git a/src/db.c b/src/db.c index 824e75c4..6b1e6d82 100644 --- a/src/db.c +++ b/src/db.c @@ -6767,31 +6767,24 @@ db_statements_prepare(void) char *query; char keystr[2048]; char valstr[1024]; - int keyremain; - int valremain; int ret; int i; // Prepare "INSERT INTO files" statement - keyremain = sizeof(keystr); - valremain = sizeof(valstr); + memset(keystr, 0, sizeof(keystr)); + memset(valstr, 0, sizeof(valstr)); for (i = 0; i < ARRAY_SIZE(mfi_cols_map); i++) { if (mfi_cols_map[i].flag == DB_FLAG_AUTO) continue; - keyremain -= snprintf(keystr + sizeof(keystr) - keyremain, keyremain, "%s, ", mfi_cols_map[i].name); - valremain -= snprintf(valstr + sizeof(valstr) - valremain, valremain, "?, "); - if (keyremain <= 0 || valremain <= 0) - { - DPRINTF(E_FATAL, L_DB, "Bug! Size of keystr or valstr is insufficient (%d, %d)\n", keyremain, valremain); - return -1; - } + CHECK_ERR(L_DB, safe_snprintf_cat(keystr, sizeof(keystr), "%s, ", mfi_cols_map[i].name)); + CHECK_ERR(L_DB, safe_snprintf_cat(valstr, sizeof(valstr), "?, ")); } - // Terminates at the ending ", " - keystr[sizeof(keystr) - keyremain - 2] = '\0'; - valstr[sizeof(valstr) - valremain - 2] = '\0'; + // Terminate at the ending ", " + *(strrchr(keystr, ',')) = '\0'; + *(strrchr(valstr, ',')) = '\0'; CHECK_NULL(L_DB, query = db_mprintf("INSERT INTO files (%s) VALUES (%s);", keystr, valstr)); @@ -6806,22 +6799,17 @@ db_statements_prepare(void) free(query); // Prepare "UPDATE files" statement - keyremain = sizeof(keystr); + memset(keystr, 0, sizeof(keystr)); for (i = 0; i < ARRAY_SIZE(mfi_cols_map); i++) { if (mfi_cols_map[i].flag == DB_FLAG_AUTO) continue; - keyremain -= snprintf(keystr + sizeof(keystr) - keyremain, keyremain, "%s = ?, ", mfi_cols_map[i].name); - if (keyremain <= 0) - { - DPRINTF(E_FATAL, L_DB, "Bug! Size of keystr is insufficient (%d)\n", keyremain); - return -1; - } + CHECK_ERR(L_DB, safe_snprintf_cat(keystr, sizeof(keystr), "%s = ?, ", mfi_cols_map[i].name)); } - // Terminates at the ending ", " - keystr[sizeof(keystr) - keyremain - 2] = '\0'; + // Terminate at the ending ", " + *(strrchr(keystr, ',')) = '\0'; CHECK_NULL(L_DB, query = db_mprintf("UPDATE files SET %s WHERE %s = ?;", keystr, mfi_cols_map[0].name)); diff --git a/src/lastfm.c b/src/lastfm.c index d72538c3..6e18620b 100644 --- a/src/lastfm.c +++ b/src/lastfm.c @@ -154,7 +154,7 @@ response_process(struct http_client_ctx *ctx, char **errmsg) DPRINTF(E_DBG, L_LASTFM, "LastFM response:\n%s\n", body); if (errmsg) - *errmsg = trimwhitespace(mxmlGetOpaque(e_node)); + *errmsg = atrim(mxmlGetOpaque(e_node)); mxmlDelete(tree); return -1; @@ -180,7 +180,7 @@ response_process(struct http_client_ctx *ctx, char **errmsg) return -1; } - sk = trimwhitespace(mxmlGetOpaque(s_node)); + sk = atrim(mxmlGetOpaque(s_node)); if (sk) { DPRINTF(E_LOG, L_LASTFM, "Got session key from LastFM: %s\n", sk); diff --git a/src/misc.c b/src/misc.c index f74fe924..2262c7f2 100644 --- a/src/misc.c +++ b/src/misc.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #ifndef CLOCK_REALTIME @@ -341,6 +342,7 @@ safe_asprintf(const char *fmt, ...) { char *ret = NULL; va_list va; + va_start(va, fmt); if (vasprintf(&ret, fmt, va) < 0) { @@ -348,9 +350,34 @@ safe_asprintf(const char *fmt, ...) abort(); } va_end(va); + return ret; } +int +safe_snprintf_cat(char *dst, size_t n, const char *fmt, ...) +{ + size_t dstlen; + va_list va; + int ret; + + if (!dst || !fmt) + return -1; + + dstlen = strlen(dst); + if (n < dstlen) + return -1; + + va_start(va, fmt); + ret = vsnprintf(dst + dstlen, n - dstlen, fmt, va); + va_end(va); + + if (ret >= 0 && ret < n - dstlen) + return 0; + else + return -1; +} + /* Key/value functions */ struct keyval * @@ -586,7 +613,7 @@ m_readfile(const char *path, int num_lines) goto error; } - lines[i] = trimwhitespace(line); + lines[i] = atrim(line); if (!lines[i] || (strlen(lines[i]) == 0)) { DPRINTF(E_LOG, L_MISC, "Line %d in '%s' is invalid\n", i+1, path); @@ -643,40 +670,58 @@ unicode_fixup_string(char *str, const char *fromcode) } char * -trimwhitespace(const char *str) +trim(char *str) { - char *ptr; - char *start; - char *out; + size_t start; // Position of first non-space char + size_t term; // Position of 0-terminator if (!str) return NULL; - // Find the beginning - while (isspace(*str)) - str++; + start = 0; + term = strlen(str); - if (*str == 0) // All spaces? - return strdup(""); + while ((start < term) && isspace(str[start])) + start++; + while ((term > start) && isspace(str[term - 1])) + term--; - // Make copy, because we will need to insert a null terminator - start = strdup(str); - if (!start) + str[term] = '\0'; + + // Shift chars incl. terminator + if (start) + memmove(str, str + start, term - start + 1); + + return str; +} + +char * +atrim(const char *str) +{ + size_t start; // Position of first non-space char + size_t term; // Position of 0-terminator + size_t size; + char *result; + + if (!str) return NULL; - // Find the end - ptr = start + strlen(start) - 1; - while (ptr > start && isspace(*ptr)) - ptr--; + start = 0; + term = strlen(str); - // Insert null terminator - *(ptr+1) = 0; + while ((start < term) && isspace(str[start])) + start++; + while ((term > start) && isspace(str[term - 1])) + term--; - out = strdup(start); + size = term - start + 1; - free(start); + result = malloc(size); - return out; + memcpy(result, str + start, size); + result[size - 1] = '\0'; + + return result; } void diff --git a/src/misc.h b/src/misc.h index 65915540..edc63c19 100644 --- a/src/misc.h +++ b/src/misc.h @@ -58,6 +58,10 @@ safe_strdup(const char *str); char * safe_asprintf(const char *fmt, ...); +int +safe_snprintf_cat(char *dst, size_t n, const char *fmt, ...); + + /* Key/value functions */ struct keyval * keyval_alloc(void); @@ -87,8 +91,13 @@ m_readfile(const char *path, int num_lines); char * unicode_fixup_string(char *str, const char *fromcode); +// Modifies str so it is trimmed. Returns pointer to str. char * -trimwhitespace(const char *str); +trim(char *str); + +// Copies the trimmed part of str to a newly allocated string (caller must free) +char * +atrim(const char *str); void swap_pointers(char **a, char **b); @@ -105,8 +114,7 @@ b64_encode(const uint8_t *in, size_t len); uint64_t murmur_hash64(const void *key, int len, uint32_t seed); - -/* Checks if the address is in a network that is configured as trusted */ +// Checks if the address is in a network that is configured as trusted bool peer_address_is_trusted(const char *addr);