diff --git a/include/cmetrics/cmt_decode_prometheus.h b/include/cmetrics/cmt_decode_prometheus.h index 7500469..5087981 100644 --- a/include/cmetrics/cmt_decode_prometheus.h +++ b/include/cmetrics/cmt_decode_prometheus.h @@ -33,6 +33,7 @@ #define CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR 50 #define CMT_DECODE_PROMETHEUS_PARSE_VALUE_FAILED 60 #define CMT_DECODE_PROMETHEUS_PARSE_TIMESTAMP_FAILED 70 +#define CMT_DECODE_PROMETHEUS_SAMPLE_VALUE_TOO_LONG 80 #define CMT_DECODE_PROMETHEUS_MAX_LABEL_COUNT 128 diff --git a/src/cmt_cat.c b/src/cmt_cat.c index 5ef28d4..dcd941b 100644 --- a/src/cmt_cat.c +++ b/src/cmt_cat.c @@ -36,7 +36,7 @@ int cmt_cat_copy_label_keys(struct cmt_map *map, char **out) /* labels array */ s = map->label_count; - if (s == 0) { + if (s <= 0) { *out = NULL; return 0; } @@ -242,7 +242,7 @@ static inline int cmt_opts_compare(struct cmt_opts *a, struct cmt_opts *b) { int ret; - ret = strcmp(a->ns, a->ns); + ret = strcmp(a->ns, b->ns); if (ret != 0) { return ret; } diff --git a/src/cmt_decode_msgpack.c b/src/cmt_decode_msgpack.c index 25942b3..3730af8 100644 --- a/src/cmt_decode_msgpack.c +++ b/src/cmt_decode_msgpack.c @@ -227,15 +227,15 @@ static int unpack_opts(mpack_reader_t *reader, struct cmt_opts *opts) } if (cfl_sds_len(opts->ns) > 0) { - cfl_sds_cat(opts->fqname, opts->ns, cfl_sds_len(opts->ns)); - cfl_sds_cat(opts->fqname, "_", 1); + cfl_sds_cat_safe(&opts->fqname, opts->ns, cfl_sds_len(opts->ns)); + cfl_sds_cat_safe(&opts->fqname, "_", 1); } if (cfl_sds_len(opts->subsystem) > 0) { - cfl_sds_cat(opts->fqname, opts->subsystem, cfl_sds_len(opts->subsystem)); - cfl_sds_cat(opts->fqname, "_", 1); + cfl_sds_cat_safe(&opts->fqname, opts->subsystem, cfl_sds_len(opts->subsystem)); + cfl_sds_cat_safe(&opts->fqname, "_", 1); } - cfl_sds_cat(opts->fqname, opts->name, cfl_sds_len(opts->name)); + cfl_sds_cat_safe(&opts->fqname, opts->name, cfl_sds_len(opts->name)); } return result; diff --git a/src/cmt_decode_prometheus.c b/src/cmt_decode_prometheus.c index 134cb92..ba7ec47 100644 --- a/src/cmt_decode_prometheus.c +++ b/src/cmt_decode_prometheus.c @@ -456,14 +456,22 @@ static int add_metric_histogram(struct cmt_decode_prometheus_context *context) cfl_sds_t *labels_without_le = NULL; cfl_sds_t *values_without_le = NULL; int label_i; - uint64_t timestamp; + uint64_t timestamp = 0; + + if (cfl_list_size(&context->metric.samples) < 3) { + return report_error(context, + CMT_DECODE_PROMETHEUS_SYNTAX_ERROR, + "not enough samples for histogram"); + } /* bucket_count = sample count - 3: * - "Inf" bucket * - sum * - count */ bucket_count = cfl_list_size(&context->metric.samples) - 3; - timestamp = context->opts.override_timestamp; + if (context->opts.override_timestamp) { + timestamp = context->opts.override_timestamp; + } bucket_defaults = calloc(bucket_count + 1, sizeof(*bucket_defaults)); if (!bucket_defaults) { @@ -627,6 +635,7 @@ static int add_metric_histogram(struct cmt_decode_prometheus_context *context) context->current.histogram = h; } + if (cmt_histogram_set_default(h, timestamp, bucket_defaults, sum, count, label_i, label_i ? values_without_le : NULL)) { @@ -661,7 +670,7 @@ static int add_metric_summary(struct cmt_decode_prometheus_context *context) size_t quantile_index; double *quantiles = NULL; double *quantile_defaults = NULL; - double sum; + double sum = 0.0; double count_dbl; size_t label_count; uint64_t count = 0; @@ -673,13 +682,21 @@ static int add_metric_summary(struct cmt_decode_prometheus_context *context) cfl_sds_t *labels_without_quantile = NULL; cfl_sds_t *values_without_quantile = NULL; int label_i; - uint64_t timestamp; + uint64_t timestamp = 0; + + if (cfl_list_size(&context->metric.samples) < 2) { + return report_error(context, + CMT_DECODE_PROMETHEUS_SYNTAX_ERROR, + "not enough samples for summary"); + } /* quantile_count = sample count - 2: * - sum * - count */ quantile_count = cfl_list_size(&context->metric.samples) - 2; - timestamp = context->opts.override_timestamp; + if (context->opts.override_timestamp) { + timestamp = context->opts.override_timestamp; + } quantile_defaults = calloc(quantile_count, sizeof(*quantile_defaults)); if (!quantile_defaults) { @@ -1143,17 +1160,36 @@ static int sample_start(struct cmt_decode_prometheus_context *context) return 0; } -static int parse_sample( - struct cmt_decode_prometheus_context *context, - const char *value1, - const char *value2) +static int parse_sample(struct cmt_decode_prometheus_context *context, + const char *value1, + const char *value2) { + int len; struct cmt_decode_prometheus_context_sample *sample; sample = cfl_list_entry_last(&context->metric.samples, struct cmt_decode_prometheus_context_sample, _head); - strcpy(sample->value1, value1); - strcpy(sample->value2, value2); + /* value1 */ + len = strlen(value1); + if (len >= sizeof(sample->value1) - 1) { + return report_error(context, + CMT_DECODE_PROMETHEUS_SAMPLE_VALUE_TOO_LONG, + "sample value is too long (max %zu characters)", sizeof(sample->value1) - 1); + } + + strncpy(sample->value1, value1, len); + sample->value1[len] = 0; + + /* value2 */ + len = strlen(value2); + if (len >= sizeof(sample->value2) - 1) { + return report_error(context, + CMT_DECODE_PROMETHEUS_SAMPLE_VALUE_TOO_LONG, + "sample value is too long (max %zu characters)", sizeof(sample->value2) - 1); + } + strncpy(sample->value2, value2, len); + sample->value2[len] = 0; + return 0; } diff --git a/src/cmt_encode_prometheus.c b/src/cmt_encode_prometheus.c index 287d701..f020288 100644 --- a/src/cmt_encode_prometheus.c +++ b/src/cmt_encode_prometheus.c @@ -139,7 +139,7 @@ static void append_metric_value(cfl_sds_t *buf, struct prom_fmt *fmt, int add_timestamp) { int len; - double val; + double val = 0.0; uint64_t ts; char tmp[128]; diff --git a/src/cmt_encode_splunk_hec.c b/src/cmt_encode_splunk_hec.c index 3cbc966..49def33 100644 --- a/src/cmt_encode_splunk_hec.c +++ b/src/cmt_encode_splunk_hec.c @@ -121,12 +121,15 @@ static void append_metric_value(cfl_sds_t *buf, struct cmt_map *map, static void format_context_common(struct cmt_splunk_hec_context *context, cfl_sds_t *buf, struct cmt_map *map, struct cmt_metric *metric) { - int len, tlen; + int len; + int tlen; + int result = CMT_ENCODE_SPLUNK_HEC_ALLOCATION_ERROR; + uint64_t ts; char hostname[256], timestamp[128]; - char *index = NULL, *source = NULL, *source_type = NULL; + char *index = NULL; + char *source = NULL; + char *source_type = NULL; struct timespec tms; - uint64_t ts; - int result = CMT_ENCODE_SPLUNK_HEC_ALLOCATION_ERROR; /* Open parenthesis */ cfl_sds_cat_safe(buf, "{", 1); @@ -159,6 +162,7 @@ static void format_context_common(struct cmt_splunk_hec_context *context, cfl_sd len = snprintf(index, tlen, "\"index\":\"%s\",", context->index); cfl_sds_cat_safe(buf, index, len); free(index); + index = NULL; } /* source */ @@ -174,13 +178,14 @@ static void format_context_common(struct cmt_splunk_hec_context *context, cfl_sd len = snprintf(source, tlen, "\"source\":\"%s\",", context->source); cfl_sds_cat_safe(buf, source, len); free(source); + source = NULL; } /* sourcetype */ if (context->source_type != NULL) { tlen = strlen(context->source_type) + 18; /* adding snprintf template character length */ source_type = malloc(tlen); - if (source == NULL) { + if (source_type == NULL) { cmt_errno(); result = CMT_ENCODE_SPLUNK_HEC_ALLOCATION_ERROR; @@ -189,6 +194,7 @@ static void format_context_common(struct cmt_splunk_hec_context *context, cfl_sd len = snprintf(source_type, tlen, "\"sourcetype\":\"%s\",", context->source_type); cfl_sds_cat_safe(buf, source_type, len); free(source_type); + source_type = NULL; } return;