From d715b7dd090b033aa15e46688fc8345899d8150a Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Wed, 8 Apr 2026 17:45:21 +0900 Subject: [PATCH 1/2] parser: Handle long time on parsing until the limit of INT Signed-off-by: Hiroshi Hatake --- src/flb_parser.c | 53 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/src/flb_parser.c b/src/flb_parser.c index c1ec6b3e6a0..15a77442937 100644 --- a/src/flb_parser.c +++ b/src/flb_parser.c @@ -1905,18 +1905,38 @@ int flb_parser_time_lookup(const char *time_str, size_t tsize, time_t time_now; char *p = NULL; char *fmt; - int time_len = tsize; + char *buf; + char *time_buf = NULL; + int time_len; const char *time_ptr = time_str; char tmp[64]; + size_t buf_size = sizeof(tmp); struct tm tmy; *ns = 0; - if (tsize > sizeof(tmp) - 1) { - flb_error("[parser] time string length is too long"); + if (tsize > INT_MAX) { + flb_error("[parser] time string length exceeds supported range"); return -1; } + time_len = (int) tsize; + buf = tmp; + + if (tsize > sizeof(tmp) - 1) { + if (tsize > (SIZE_MAX - 8)) { + flb_error("[parser] time string length is too long"); + return -1; + } + buf_size = tsize + 8; + time_buf = flb_malloc(buf_size); + if (time_buf == NULL) { + flb_errno(); + return -1; + } + buf = time_buf; + } + /* * Some records coming from old Syslog messages do not contain the * year, so it's required to ingest this information in the value @@ -1924,7 +1944,8 @@ int flb_parser_time_lookup(const char *time_str, size_t tsize, */ if (parser->time_with_year == FLB_FALSE) { /* Given time string is too long */ - if (time_len + 6 >= sizeof(tmp)) { + if (time_len + 6 >= buf_size) { + flb_free(time_buf); return -1; } @@ -1965,7 +1986,7 @@ int flb_parser_time_lookup(const char *time_str, size_t tsize, uint64_t t = tmy.tm_year + 1900; - fmt = tmp; + fmt = buf; u64_to_str(t, fmt); fmt += 4; *fmt++ = ' '; @@ -1974,8 +1995,8 @@ int flb_parser_time_lookup(const char *time_str, size_t tsize, fmt += time_len; *fmt++ = '\0'; - time_ptr = tmp; - time_len = strlen(tmp); + time_ptr = buf; + time_len = strlen(buf); p = flb_strptime(time_ptr, parser->time_fmt_year, tm); } else { @@ -1984,13 +2005,14 @@ int flb_parser_time_lookup(const char *time_str, size_t tsize, * null-terminated, which time_ptr is not guaranteed * to be. So we use tmp to hold our string. */ - if (time_len >= sizeof(tmp)) { + if (time_len >= buf_size) { + flb_free(time_buf); return -1; } - memcpy(tmp, time_ptr, time_len); - tmp[time_len] = '\0'; - time_ptr = tmp; - time_len = strlen(tmp); + memcpy(buf, time_ptr, time_len); + buf[time_len] = '\0'; + time_ptr = buf; + time_len = strlen(buf); p = flb_strptime(time_ptr, parser->time_fmt, tm); } @@ -1998,9 +2020,11 @@ int flb_parser_time_lookup(const char *time_str, size_t tsize, if (p == NULL) { if (parser->time_strict) { flb_error("[parser] cannot parse '%.*s'", (int)tsize, time_str); + flb_free(time_buf); return -1; } flb_debug("[parser] non-exact match '%.*s'", (int)tsize, time_str); + flb_free(time_buf); return 0; } @@ -2009,9 +2033,11 @@ int flb_parser_time_lookup(const char *time_str, size_t tsize, if (ret < 0) { if (parser->time_strict) { flb_error("[parser] cannot parse %%L for '%.*s'", (int)tsize, time_str); + flb_free(time_buf); return -1; } flb_debug("[parser] non-exact match on %%L '%.*s'", (int)tsize, time_str); + flb_free(time_buf); return 0; } p += ret; @@ -2021,9 +2047,11 @@ int flb_parser_time_lookup(const char *time_str, size_t tsize, if (p == NULL) { if (parser->time_strict) { flb_error("[parser] cannot parse '%.*s' after %%L", (int)tsize, time_str); + flb_free(time_buf); return -1; } flb_debug("[parser] non-exact match after %%L '%.*s'", (int)tsize, time_str); + flb_free(time_buf); return 0; } } @@ -2032,6 +2060,7 @@ int flb_parser_time_lookup(const char *time_str, size_t tsize, flb_tm_gmtoff(tm) = parser->time_offset; } + flb_free(time_buf); return 0; } From 156d405346ff46664539d27bddb2649c708542ca Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Wed, 8 Apr 2026 18:20:26 +0900 Subject: [PATCH 2/2] tests: parser: Add test cases for too long cases Signed-off-by: Hiroshi Hatake --- tests/internal/parser.c | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/internal/parser.c b/tests/internal/parser.c index 4ba61d48b1e..cd857c06aab 100644 --- a/tests/internal/parser.c +++ b/tests/internal/parser.c @@ -15,6 +15,9 @@ #include #include #endif +#include +#include +#include #include "flb_tests_internal.h" /* Parsers configuration */ @@ -891,6 +894,63 @@ void test_parser_time_zone_conflicts(void) flb_config_exit(config); } +void test_parser_time_lookup_long_fraction() +{ + int ret; + double ns; + time_t epoch; + struct flb_tm tm; + struct flb_parser *parser; + struct flb_config *config; + const char *time_string = "10/03/2016 12:21:08.123456789123456789123456789123456789123456789123456789"; + + config = flb_config_init(); + load_json_parsers(config); + + parser = flb_parser_get("generic_N", config); + TEST_CHECK(parser != NULL); + if (parser == NULL) { + flb_parser_exit(config); + flb_config_exit(config); + return; + } + + ret = flb_parser_time_lookup(time_string, strlen(time_string), 0, parser, &tm, &ns); + TEST_CHECK(ret == 0); + + epoch = flb_parser_tm2time(&tm, FLB_FALSE); + TEST_CHECK(epoch == 1475497268); + TEST_CHECK(fabs(ns - 0.123456789) <= DBL_EPSILON); + + flb_parser_exit(config); + flb_config_exit(config); +} + +void test_parser_time_lookup_reject_oversized_length() +{ + int ret; + double ns; + struct flb_tm tm; + struct flb_parser *parser; + struct flb_config *config; + + config = flb_config_init(); + load_json_parsers(config); + + parser = flb_parser_get("generic_N", config); + TEST_CHECK(parser != NULL); + if (parser == NULL) { + flb_parser_exit(config); + flb_config_exit(config); + return; + } + + ret = flb_parser_time_lookup("x", (size_t) INT_MAX + 1, 0, parser, &tm, &ns); + TEST_CHECK(ret == -1); + + flb_parser_exit(config); + flb_config_exit(config); +} TEST_LIST = { { "tzone_offset", test_parser_tzone_offset}, @@ -902,6 +962,8 @@ TEST_LIST = { { "time_zone_iana_australia", test_parser_time_zone_iana_australia }, { "time_zone_missing_year", test_parser_time_zone_missing_year }, { "time_zone_conflicts", test_parser_time_zone_conflicts }, + { "time_lookup_long_fraction", test_parser_time_lookup_long_fraction}, + { "time_lookup_reject_oversized_length", test_parser_time_lookup_reject_oversized_length}, { "mysql_unquoted" , test_mysql_unquoted }, { 0 } };