tag/IcyMetadataParser: do not null-terminate strings in icy_parse_tag()

Just pass std::string_views into the unmodified buffer to
icy_parse_tag_item().
This commit is contained in:
Max Kellermann 2023-12-20 19:54:20 +01:00
parent 2618294eb7
commit e443ee357a
2 changed files with 12 additions and 17 deletions

View File

@ -99,10 +99,10 @@ icy_parse_tag_item(TagBuilder &tag,
* of the string). If that fails, return the first single quote. If * of the string). If that fails, return the first single quote. If
* that also fails, return #end. * that also fails, return #end.
*/ */
static char * static const char *
find_end_quote(char *p, char *const end) noexcept find_end_quote(const char *p, const char *const end) noexcept
{ {
char *fallback = std::find(p, end, '\''); const char *fallback = std::find(p, end, '\'');
if (fallback >= end - 1 || fallback[1] == ';') if (fallback >= end - 1 || fallback[1] == ';')
return fallback; return fallback;
@ -124,7 +124,7 @@ icy_parse_tag(
#ifdef HAVE_ICU_CONVERTER #ifdef HAVE_ICU_CONVERTER
const IcuConverter *icu_converter, const IcuConverter *icu_converter,
#endif #endif
char *p, char *const end) noexcept const char *p, const char *const end) noexcept
{ {
assert(p != nullptr); assert(p != nullptr);
assert(end != nullptr); assert(end != nullptr);
@ -133,18 +133,18 @@ icy_parse_tag(
TagBuilder tag; TagBuilder tag;
while (p != end) { while (p != end) {
const char *const name = p; const char *eq = std::find(p, end, '=');
char *eq = std::find(p, end, '=');
if (eq == end) if (eq == end)
break; break;
*eq = 0; const std::string_view name{p, eq};
p = eq + 1; p = eq + 1;
if (*p != '\'') { if (*p != '\'') {
/* syntax error; skip to the next semicolon, /* syntax error; skip to the next semicolon,
try to recover */ try to recover */
char *semicolon = std::find(p, end, ';'); const char *semicolon = std::find(p, end, ';');
if (semicolon == end) if (semicolon == end)
break; break;
p = semicolon + 1; p = semicolon + 1;
@ -153,12 +153,11 @@ icy_parse_tag(
++p; ++p;
const char *const value = p; const char *quote = find_end_quote(p, end);
char *quote = find_end_quote(p, end);
if (quote == end) if (quote == end)
break; break;
*quote = 0; const std::string_view value{p, quote};
p = quote + 1; p = quote + 1;
icy_parse_tag_item(tag, icy_parse_tag_item(tag,
@ -167,7 +166,7 @@ icy_parse_tag(
#endif #endif
name, value); name, value);
char *semicolon = std::find(p, end, ';'); const char *semicolon = std::find(p, end, ';');
if (semicolon == end) if (semicolon == end)
break; break;
p = semicolon + 1; p = semicolon + 1;

View File

@ -2,8 +2,6 @@
* Unit tests for class IcyMetaDataParser. * Unit tests for class IcyMetaDataParser.
*/ */
#include "util/ScopeExit.hxx"
/* include the .cxx file to get access to internal functions */ /* include the .cxx file to get access to internal functions */
#include "tag/IcyMetaDataParser.cxx" #include "tag/IcyMetaDataParser.cxx"
@ -16,13 +14,11 @@
static std::unique_ptr<Tag> static std::unique_ptr<Tag>
icy_parse_tag(const char *p) icy_parse_tag(const char *p)
{ {
char *q = strdup(p);
AtScopeExit(q) { free(q); };
return icy_parse_tag( return icy_parse_tag(
#ifdef HAVE_ICU_CONVERTER #ifdef HAVE_ICU_CONVERTER
nullptr, nullptr,
#endif #endif
q, q + strlen(q)); p, p + strlen(p));
} }
static void static void