Skip to content

Commit

Permalink
Merge pull request #224 from MrAnno/fix-stats-prometheus-label-escaping
Browse files Browse the repository at this point in the history
Fix stats prometheus label escaping
  • Loading branch information
OverOrion authored Jul 26, 2024
2 parents f554484 + 2465700 commit 52d08b7
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 4 deletions.
47 changes: 44 additions & 3 deletions lib/stats/stats-prometheus.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2023 László Várady
* Copyright (c) 2024 Axoflow
* Copyright (c) 2023-2024 László Várady
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand All @@ -25,16 +26,56 @@
#include "stats/stats-cluster.h"
#include "stats/stats-counter.h"
#include "timeutils/unixtime.h"
#include "utf8utils.h"
#include "str-utils.h"
#include "scratch-buffers.h"

#include <string.h>


/* Exposition format:
*
* A label value can be any sequence of UTF-8 characters, but the
* backslash (\), double-quote ("), and line feed (\n) characters have to be
* escaped as \\, \", and \n, respectively.
*/
static gchar *
stats_format_prometheus_sanitize_label_value(const gchar *value)
{
GString *sanitized_value = scratch_buffers_alloc();
append_unsafe_utf8_as_escaped_binary(sanitized_value, value, -1, "\"");

const gchar *value_end = value + strlen(value);

while (value < value_end)
{
gunichar uchar = g_utf8_get_char_validated(value, value_end - value);

if (G_UNLIKELY(uchar == (gunichar) -1 || uchar == (gunichar) -2))
{
/* double backslash to conform to the format */
g_string_append_printf(sanitized_value, "\\\\x%02x", *(guint8 *) value);
value++;
continue;
}

switch (uchar)
{
case '\\':
g_string_append(sanitized_value, "\\\\");
break;
case '"':
g_string_append(sanitized_value, "\\\"");
break;
case '\n':
g_string_append(sanitized_value, "\\n");
break;
default:
g_string_append_unichar_optimized(sanitized_value, uchar);
break;
}

value = g_utf8_next_char(value);
}

return sanitized_value->str;
}

Expand Down
30 changes: 29 additions & 1 deletion lib/stats/tests/test_stats_prometheus.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2023 László Várady
* Copyright (c) 2024 Axoflow
* Copyright (c) 2023-2024 László Várady
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -164,6 +165,33 @@ Test(stats_prometheus, test_prometheus_format_sanitize)
stats_cluster_free(cluster);
}

Test(stats_prometheus, test_prometheus_format_label_escaping)
{
/* Exposition format:
*
* A label value can be any sequence of UTF-8 characters, but the
* backslash (\), double-quote ("), and line feed (\n) characters have to be
* escaped as \\, \", and \n, respectively.
*/

StatsClusterLabel labels[] =
{
stats_cluster_label("control_chars", "a\a\tb\nc"),
stats_cluster_label("backslashes", "a\\a\\t\\nb"),
stats_cluster_label("quotes", "\"\"hello\""),
stats_cluster_label("invalid_utf8", "a\xfa"),
};
StatsCluster *cluster = test_single_cluster("test_name", labels, G_N_ELEMENTS(labels));

assert_prometheus_format(cluster, SC_TYPE_SINGLE_VALUE,
"syslogng_test_name{control_chars=\"a\a\tb\\nc\","
"backslashes=\"a\\\\a\\\\t\\\\nb\","
"quotes=\"\\\"\\\"hello\\\"\","
"invalid_utf8=\"a\\\\xfa\"} 0\n");

stats_cluster_free(cluster);
}

gchar *stats_format_prometheus_format_value(const StatsClusterKey *key, const StatsCounterItem *counter);

Test(stats_prometheus, test_prometheus_format_value)
Expand Down
4 changes: 4 additions & 0 deletions news/bugfix-224.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
`syslog-ng-ctl`: fix escaping of `stats prometheus`

Metric labels (for example, the ones produced by `metrics-probe()`) may contain control characters, invalid UTF-8 or `\`
characters. In those specific rare cases, the escaping of the `stats prometheus` output was incorrect.

0 comments on commit 52d08b7

Please sign in to comment.