mirror of
https://github.com/netdata/netdata.git
synced 2025-04-23 13:00:23 +00:00
fix crashes identified by sentry (#19856)
* check for the existance of rc->rrdset * avoid division by zero * format rfc3339 days avoiding sprintf
This commit is contained in:
parent
766e65288c
commit
a20869aa37
3 changed files with 153 additions and 25 deletions
src
|
@ -449,7 +449,7 @@ void update_mem_pgfaults_chart(struct cgroup *cg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_mem_usage_limit_chart(struct cgroup *cg, unsigned long long memory_limit) {
|
void update_mem_usage_limit_chart(struct cgroup *cg, unsigned long long memory_limit) {
|
||||||
if (is_cgroup_systemd_service(cg))
|
if (is_cgroup_systemd_service(cg) || !memory_limit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RRDSET *chart = cg->st_mem_usage_limit;
|
RRDSET *chart = cg->st_mem_usage_limit;
|
||||||
|
@ -488,7 +488,7 @@ void update_mem_usage_limit_chart(struct cgroup *cg, unsigned long long memory_l
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_mem_utilization_chart(struct cgroup *cg, unsigned long long memory_limit) {
|
void update_mem_utilization_chart(struct cgroup *cg, unsigned long long memory_limit) {
|
||||||
if (is_cgroup_systemd_service(cg))
|
if (is_cgroup_systemd_service(cg) || !memory_limit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RRDSET *chart = cg->st_mem_utilization;
|
RRDSET *chart = cg->st_mem_utilization;
|
||||||
|
|
|
@ -36,7 +36,7 @@ struct variable_lookup_job {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void variable_lookup_add_result_with_score(struct variable_lookup_job *vbd, NETDATA_DOUBLE n, RRDSET *st, const char *source __maybe_unused) {
|
static void variable_lookup_add_result_with_score(struct variable_lookup_job *vbd, NETDATA_DOUBLE n, RRDSET *st, const char *source __maybe_unused) {
|
||||||
if(vbd->score.last_rrdset != st) {
|
if(vbd->score.last_rrdset != st && vbd->rc->rrdset) {
|
||||||
vbd->score.last_rrdset = st;
|
vbd->score.last_rrdset = st;
|
||||||
vbd->score.last_score = rrdlabels_common_count(vbd->rc->rrdset->rrdlabels, st->rrdlabels);
|
vbd->score.last_score = rrdlabels_common_count(vbd->rc->rrdset->rrdlabels, st->rrdlabels);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,71 @@
|
||||||
|
|
||||||
#include "rfc3339.h"
|
#include "rfc3339.h"
|
||||||
|
|
||||||
|
// Helper functions for safe printing of date/time components
|
||||||
|
// These functions don't add a null terminator and return only the exact count of bytes written
|
||||||
|
|
||||||
|
static inline size_t print_4digit_year(char *buffer, size_t size, int year) {
|
||||||
|
if (!buffer || size < 4) return 0; // Need at least 4 digits
|
||||||
|
|
||||||
|
// Ensure year is in valid range (0-9999)
|
||||||
|
year = year < 0 ? 0 : (year > 9999 ? 9999 : year);
|
||||||
|
|
||||||
|
buffer[0] = '0' + (year / 1000) % 10;
|
||||||
|
buffer[1] = '0' + (year / 100) % 10;
|
||||||
|
buffer[2] = '0' + (year / 10) % 10;
|
||||||
|
buffer[3] = '0' + year % 10;
|
||||||
|
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t print_2digit(char *buffer, size_t size, int value) {
|
||||||
|
if (!buffer || size < 2) return 0; // Need at least 2 digits
|
||||||
|
|
||||||
|
// Ensure value is in valid range (0-99)
|
||||||
|
value = value < 0 ? 0 : (value > 99 ? 99 : value);
|
||||||
|
|
||||||
|
buffer[0] = '0' + (value / 10) % 10;
|
||||||
|
buffer[1] = '0' + value % 10;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t print_fraction(char *buffer, size_t size, usec_t fraction, size_t digits) {
|
||||||
|
if (!buffer || size < digits) return 0;
|
||||||
|
|
||||||
|
// Validate and cap the number of digits
|
||||||
|
digits = digits < 1 ? 1 : (digits > 9 ? 9 : digits);
|
||||||
|
|
||||||
|
// Calculate divisor to get correct precision
|
||||||
|
usec_t divisor = 1;
|
||||||
|
for (size_t i = 0; i < 6 - digits; i++)
|
||||||
|
divisor *= 10;
|
||||||
|
|
||||||
|
// Calculate the fraction to print
|
||||||
|
fraction = fraction / divisor;
|
||||||
|
|
||||||
|
// Ensure fraction won't exceed the requested number of digits
|
||||||
|
usec_t max_value = 1;
|
||||||
|
for (size_t i = 0; i < digits; i++)
|
||||||
|
max_value *= 10;
|
||||||
|
max_value--;
|
||||||
|
|
||||||
|
fraction = fraction > max_value ? max_value : fraction;
|
||||||
|
|
||||||
|
// Print the fraction with leading zeros
|
||||||
|
usec_t remaining = fraction;
|
||||||
|
|
||||||
|
// Setup working backwards from least significant digit
|
||||||
|
for (int i = digits - 1; i >= 0; i--) {
|
||||||
|
buffer[i] = '0' + (remaining % 10);
|
||||||
|
remaining /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return digits;
|
||||||
|
}
|
||||||
|
|
||||||
size_t rfc3339_datetime_ut(char *buffer, size_t len, usec_t now_ut, size_t fractional_digits, bool utc) {
|
size_t rfc3339_datetime_ut(char *buffer, size_t len, usec_t now_ut, size_t fractional_digits, bool utc) {
|
||||||
if (!buffer || len == 0)
|
if (!buffer || len < 20) // Minimum size for YYYY-MM-DDThh:mm:ssZ
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
time_t t = (time_t)(now_ut / USEC_PER_SEC);
|
time_t t = (time_t)(now_ut / USEC_PER_SEC);
|
||||||
|
@ -21,43 +84,108 @@ size_t rfc3339_datetime_ut(char *buffer, size_t len, usec_t now_ut, size_t fract
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t used_length = strftime(buffer, len, "%Y-%m-%dT%H:%M:%S", tmp);
|
size_t pos = 0;
|
||||||
if (used_length == 0) {
|
|
||||||
buffer[0] = '\0';
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fractional_digits >= 1 && fractional_digits <= 9) {
|
// Year (4 digits)
|
||||||
int fractional_part = (int)(now_ut % USEC_PER_SEC);
|
if (len - pos < 4) goto finish;
|
||||||
if (fractional_part && len - used_length > fractional_digits + 1) {
|
pos += print_4digit_year(&buffer[pos], len - pos, tmp->tm_year + 1900);
|
||||||
char format[] = ".%01d";
|
|
||||||
format[3] = (char)('0' + fractional_digits);
|
|
||||||
|
|
||||||
// Adjust fractional part
|
// Month separator
|
||||||
fractional_part /= (int)pow(10, 6 - fractional_digits);
|
if (len - pos < 1) goto finish;
|
||||||
|
buffer[pos++] = '-';
|
||||||
|
|
||||||
used_length += snprintf(buffer + used_length, len - used_length,
|
// Month (2 digits)
|
||||||
format, fractional_part);
|
if (len - pos < 2) goto finish;
|
||||||
|
pos += print_2digit(&buffer[pos], len - pos, tmp->tm_mon + 1);
|
||||||
|
|
||||||
|
// Day separator
|
||||||
|
if (len - pos < 1) goto finish;
|
||||||
|
buffer[pos++] = '-';
|
||||||
|
|
||||||
|
// Day (2 digits)
|
||||||
|
if (len - pos < 2) goto finish;
|
||||||
|
pos += print_2digit(&buffer[pos], len - pos, tmp->tm_mday);
|
||||||
|
|
||||||
|
// T separator
|
||||||
|
if (len - pos < 1) goto finish;
|
||||||
|
buffer[pos++] = 'T';
|
||||||
|
|
||||||
|
// Hour (2 digits)
|
||||||
|
if (len - pos < 2) goto finish;
|
||||||
|
pos += print_2digit(&buffer[pos], len - pos, tmp->tm_hour);
|
||||||
|
|
||||||
|
// Minute separator
|
||||||
|
if (len - pos < 1) goto finish;
|
||||||
|
buffer[pos++] = ':';
|
||||||
|
|
||||||
|
// Minute (2 digits)
|
||||||
|
if (len - pos < 2) goto finish;
|
||||||
|
pos += print_2digit(&buffer[pos], len - pos, tmp->tm_min);
|
||||||
|
|
||||||
|
// Second separator
|
||||||
|
if (len - pos < 1) goto finish;
|
||||||
|
buffer[pos++] = ':';
|
||||||
|
|
||||||
|
// Second (2 digits)
|
||||||
|
if (len - pos < 2) goto finish;
|
||||||
|
pos += print_2digit(&buffer[pos], len - pos, tmp->tm_sec);
|
||||||
|
|
||||||
|
// Add fractional part if requested
|
||||||
|
if (fractional_digits > 9) fractional_digits = 9;
|
||||||
|
if (fractional_digits) {
|
||||||
|
usec_t fractional_part = now_ut % USEC_PER_SEC;
|
||||||
|
|
||||||
|
if (fractional_part > 0) {
|
||||||
|
// Need space for decimal point and digits
|
||||||
|
if (len - pos < fractional_digits + 1) goto finish;
|
||||||
|
|
||||||
|
buffer[pos++] = '.';
|
||||||
|
pos += print_fraction(&buffer[pos], len - pos, fractional_part, fractional_digits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add timezone information
|
||||||
if (utc) {
|
if (utc) {
|
||||||
if (used_length + 1 < len) {
|
if (len - pos < 1) goto finish;
|
||||||
buffer[used_length++] = 'Z';
|
buffer[pos++] = 'Z';
|
||||||
buffer[used_length] = '\0';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
long offset = tmbuf.tm_gmtoff;
|
long offset = tmbuf.tm_gmtoff;
|
||||||
int hours = (int)(offset / 3600);
|
int hours = (int)(offset / 3600);
|
||||||
int minutes = abs((int)((offset % 3600) / 60));
|
int minutes = abs((int)((offset % 3600) / 60));
|
||||||
|
|
||||||
if (used_length + 7 < len) { // Space for "+HH:MM\0"
|
// Check if timezone is UTC
|
||||||
used_length += snprintf(buffer + used_length, len - used_length, "%+03d:%02d", hours, minutes);
|
if (hours == 0 && minutes == 0) {
|
||||||
|
if (len - pos < 1) goto finish;
|
||||||
|
buffer[pos++] = 'Z';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Need space for sign, hours, colon, minutes (6 chars total)
|
||||||
|
if (len - pos < 6) goto finish;
|
||||||
|
|
||||||
|
// Add timezone offset
|
||||||
|
buffer[pos++] = (hours >= 0) ? '+' : '-';
|
||||||
|
hours = abs(hours);
|
||||||
|
|
||||||
|
// Hours with leading zero
|
||||||
|
pos += print_2digit(&buffer[pos], len - pos, hours);
|
||||||
|
|
||||||
|
// Colon
|
||||||
|
buffer[pos++] = ':';
|
||||||
|
|
||||||
|
// Minutes with leading zero
|
||||||
|
pos += print_2digit(&buffer[pos], len - pos, minutes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return used_length;
|
finish:
|
||||||
|
// Ensure null termination
|
||||||
|
if (pos < len)
|
||||||
|
buffer[pos] = '\0';
|
||||||
|
else
|
||||||
|
buffer[len - 1] = '\0';
|
||||||
|
|
||||||
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
usec_t rfc3339_parse_ut(const char *rfc3339, char **endptr) {
|
usec_t rfc3339_parse_ut(const char *rfc3339, char **endptr) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue