From 9233c03ca8bc8ea14fe6f9906549a7e894db492e Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Fri, 14 Jan 2022 22:25:45 +0100 Subject: [PATCH] [daap] Unescaping of \' in the value part of a daap clause --- src/daap_query.c | 4 ++ src/parsers/daap_parser.y | 88 +++++++-------------------------------- 2 files changed, 19 insertions(+), 73 deletions(-) diff --git a/src/daap_query.c b/src/daap_query.c index 24bfed99..25ada9c2 100644 --- a/src/daap_query.c +++ b/src/daap_query.c @@ -36,11 +36,15 @@ daap_query_parse_sql(const char *daap_query) { struct daap_result result; + DPRINTF(E_SPAM, L_DAAP, "Parse DAAP query input '%s'\n", daap_query); + if (daap_lex_parse(&result, daap_query) != 0) { DPRINTF(E_LOG, L_DAAP, "Could not parse '%s': %s\n", daap_query, result.errmsg); return NULL; } + DPRINTF(E_SPAM, L_DAAP, "Parse DAAP query output '%s'\n", result.str); + return safe_strdup(result.str); } diff --git a/src/parsers/daap_parser.y b/src/parsers/daap_parser.y index e9a5c5b7..63bd0b0f 100644 --- a/src/parsers/daap_parser.y +++ b/src/parsers/daap_parser.y @@ -182,32 +182,9 @@ int daap_lex_parse(struct daap_result *result, const char *input); #ifndef DEBUG_PARSER_MOCK #include "daap_query_hash.h" #include "db.h" +#include "misc.h" #else -struct dmap_query_field_map { - char *dmap_field; - char *db_col; - int as_int; -}; - -static struct dmap_query_field_map testdqfm_int = { "daap.testint", "f.testint", 1 }; -static struct dmap_query_field_map testdqfm_str = { "daap.teststr", "f.teststr", 0 }; - -static struct dmap_query_field_map * daap_query_field_lookup(char *tag, int len) -{ - if (strcmp(tag, testdqfm_str.dmap_field) == 0) - return &testdqfm_str; - else - return &testdqfm_int; -} - -static char * db_escape_string(const char *str) -{ - char *new = strdup(str); - char *ptr; - while ((ptr = strpbrk(new, "\\'"))) - *ptr = 'X'; - return new; -} +#include "owntonefunctions.h" #endif } @@ -222,48 +199,6 @@ struct daap_result { } %code { -static int str_replace(char *s, size_t sz, const char *pattern, const char *replacement) -{ - char *ptr; - char *src; - char *dst; - size_t num; - - if (!s) - return -1; - - if (!pattern || !replacement) - return 0; - - size_t p_len = strlen(pattern); - size_t r_len = strlen(replacement); - size_t s_len = strlen(s) + 1; // Incl terminator - - ptr = s; - while ((ptr = strstr(ptr, pattern))) - { - // We will move the part of the string after the pattern from src to dst - src = ptr + p_len; - dst = ptr + r_len; - - num = s_len - (src - s); // Number of bytes w/terminator we need to move - if (dst + num > s + sz) - return -1; // Not enough room - - // Shift everything after the pattern to the right, use memmove since - // there might be an overlap - memmove(dst, src, num); - - // Write replacement, no null terminater - memcpy(ptr, replacement, r_len); - - // Advance ptr to avoid infinite looping - ptr = dst; - } - - return 0; -} - static void sql_append(struct daap_result *result, const char *fmt, ...) { va_list ap; @@ -317,6 +252,8 @@ static void sql_like_escape(char **value, char *escape_char) size_t len = strlen(s); char *new; + *escape_char = 0; + if (len < 2) return; // Shouldn't ever happen since lexer should give strings w/wildcards @@ -329,8 +266,8 @@ static void sql_like_escape(char **value, char *escape_char) len = 2 * len; // Enough for every char to be escaped new = realloc(s, len); - str_replace(new, len, "%", "\\%"); - str_replace(new, len, "_", "\\_"); + safe_snreplace(new, len, "%", "\\%"); + safe_snreplace(new, len, "_", "\\_"); new[0] = new[strlen(new) - 1] = '%'; *escape_char = '\\'; *value = new; @@ -338,9 +275,13 @@ static void sql_like_escape(char **value, char *escape_char) static void sql_str_escape(char **value) { - char *old = *value; - *value = db_escape_string(old); - free(old); + char *s = *value; + + if (strchr(s, '\'')) + safe_snreplace(s, strlen(s) + 1, "\\'", "'"); // See Kid's audiobooks test case + + *value = db_escape_string(s); + free(s); } static void sql_append_dmap_clause(struct daap_result *result, struct ast *a) @@ -423,7 +364,8 @@ static void sql_append_dmap_clause(struct daap_result *result, struct ast *a) } /* Creates the parsing result from the AST */ -static void sql_from_ast(struct daap_result *result, struct ast *a) { +static void sql_from_ast(struct daap_result *result, struct ast *a) +{ if (!a || result->err < 0) return;