Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws_util: fix leading zeros in time_key #8116

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 34 additions & 13 deletions src/aws/flb_aws_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
#define FLB_AWS_BASE_USER_AGENT_LEN 21
#endif

#define FLB_AWS_MILLISECOND_FORMATTER_LENGTH 3
#define FLB_AWS_NANOSECOND_FORMATTER_LENGTH 9
#define FLB_AWS_MILLISECOND_LENGTH 3
#define FLB_AWS_NANOSECOND_LENGTH 9
#define FLB_AWS_MILLISECOND_FORMATTER "%3N"
#define FLB_AWS_NANOSECOND_FORMATTER_N "%9N"
#define FLB_AWS_NANOSECOND_FORMATTER_L "%L"
Expand Down Expand Up @@ -957,6 +957,20 @@ flb_sds_t flb_get_s3_key(const char *format, time_t time, const char *tag,
return NULL;
}


static void decimal_with_leading_zeros(char *dst, char *src, int expected_len)
{
int src_len = strlen(src);
int zero_len = expected_len - src_len;
int i;

for (i = 0; i < zero_len; i++) {
dst[i] = '0';
}

strncat(dst + zero_len, src, src_len);
}

/*
* This function is an extension to strftime which can support milliseconds with %3N,
* support nanoseconds with %9N or %L. The return value is the length of formatted
Expand All @@ -965,8 +979,8 @@ flb_sds_t flb_get_s3_key(const char *format, time_t time, const char *tag,
size_t flb_aws_strftime_precision(char **out_buf, const char *time_format,
struct flb_time *tms)
{
char millisecond_str[FLB_AWS_MILLISECOND_FORMATTER_LENGTH+1];
char nanosecond_str[FLB_AWS_NANOSECOND_FORMATTER_LENGTH+1];
char millisecond_str[FLB_AWS_MILLISECOND_LENGTH+1];
char nanosecond_str[FLB_AWS_NANOSECOND_LENGTH+1];
char *tmp_parsed_time_str;
char *buf;
size_t out_size;
Expand All @@ -975,6 +989,7 @@ size_t flb_aws_strftime_precision(char **out_buf, const char *time_format,
struct tm timestamp;
struct tm *tmp;
int i;
int j;

/*
* Guess the max length needed for tmp_parsed_time_str and tmp_out_buf. The
Expand Down Expand Up @@ -1002,28 +1017,34 @@ size_t flb_aws_strftime_precision(char **out_buf, const char *time_format,
}

/* Replace %3N to millisecond, %9N and %L to nanosecond in time_format. */
snprintf(millisecond_str, FLB_AWS_MILLISECOND_FORMATTER_LENGTH+1,
snprintf(millisecond_str, FLB_AWS_MILLISECOND_LENGTH+1,
Copy link
Collaborator

@nokute78 nokute78 Nov 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about ensuring like following code ?

snprintf(nanosecond_str, FLB_AWS_MILLISECOND_LENGTH+1, "%03" PRIu64, (uint64_t) tms->tm.tv_nsec / 1000000);

"%" PRIu64, (uint64_t) tms->tm.tv_nsec / 1000000);
snprintf(nanosecond_str, FLB_AWS_NANOSECOND_FORMATTER_LENGTH+1,
snprintf(nanosecond_str, FLB_AWS_NANOSECOND_LENGTH+1,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about ensuring like following code ?

snprintf(nanosecond_str, FLB_AWS_NANOSECOND_LENGTH+1, "%09" PRIu64, (uint64_t) tms->tm.tv_nsec);

Example code:

#include <stdio.h>
#include <inttypes.h>

int main()
{
  uint64_t val = 1;
  int i;

  for (i=0; i<9; i++)  {
    printf("i=%d " "%09" PRIu64 "\n", i, val);
    val *= 10;
  }
}

Output is

i=0 000000001
i=1 000000010
i=2 000000100
i=3 000001000
i=4 000010000
i=5 000100000
i=6 001000000
i=7 010000000
i=8 100000000

"%" PRIu64, (uint64_t) tms->tm.tv_nsec);

j = 0;
for (i = 0; i < time_format_len; i++) {
if (strncmp(time_format+i, FLB_AWS_MILLISECOND_FORMATTER, 3) == 0) {
strncat(tmp_parsed_time_str, millisecond_str,
FLB_AWS_MILLISECOND_FORMATTER_LENGTH+1);
decimal_with_leading_zeros(tmp_parsed_time_str + j, millisecond_str,
FLB_AWS_MILLISECOND_LENGTH);
i += 2;
j += FLB_AWS_MILLISECOND_LENGTH;
}
else if (strncmp(time_format+i, FLB_AWS_NANOSECOND_FORMATTER_N, 3) == 0) {
strncat(tmp_parsed_time_str, nanosecond_str,
FLB_AWS_NANOSECOND_FORMATTER_LENGTH+1);
decimal_with_leading_zeros(tmp_parsed_time_str + j, nanosecond_str,
FLB_AWS_NANOSECOND_LENGTH);
i += 2;
j += FLB_AWS_NANOSECOND_LENGTH;
}
else if (strncmp(time_format+i, FLB_AWS_NANOSECOND_FORMATTER_L, 2) == 0) {
strncat(tmp_parsed_time_str, nanosecond_str,
FLB_AWS_NANOSECOND_FORMATTER_LENGTH+1);
decimal_with_leading_zeros(tmp_parsed_time_str + j, nanosecond_str,
FLB_AWS_NANOSECOND_LENGTH);
i += 1;
j += FLB_AWS_NANOSECOND_LENGTH;
}
else {
strncat(tmp_parsed_time_str,time_format+i,1);
strncat(tmp_parsed_time_str + j, time_format+i, 1);
j += 1;
}
}

Expand Down
19 changes: 19 additions & 0 deletions tests/internal/aws_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,24 @@ static void test_flb_get_s3_key_mixed_timestamp()
flb_sds_destroy(s3_key_format);
}

/*
* https://github.com/fluent/fluent-bit/issues/7538
*/
static void test_flb_aws_strftime_precision_leading_zeros()
{
char *out_buf;
struct flb_time tms;
char *time_format = "ms=%3N, ns=%9N, ns=%L";
tms.tm.tv_sec = 1698784683;
tms.tm.tv_nsec = 1000009;

out_buf = flb_malloc(1024);
TEST_CHECK(out_buf != NULL);
flb_aws_strftime_precision(&out_buf, time_format, &tms);

TEST_CHECK(strcmp(out_buf, "ms=001, ns=001000009, ns=001000009") == 0);
}

TEST_LIST = {
{ "parse_api_error" , test_flb_aws_error},
{ "flb_aws_endpoint" , test_flb_aws_endpoint},
Expand All @@ -391,5 +409,6 @@ TEST_LIST = {
{"flb_get_s3_key_increment_index", test_flb_get_s3_key_increment_index},
{"flb_get_s3_key_index_overflow", test_flb_get_s3_key_index_overflow},
{"flb_get_s3_key_mixed_timestamp", test_flb_get_s3_key_mixed_timestamp},
{"test_flb_aws_strftime_precision_leading_zeros", test_flb_aws_strftime_precision_leading_zeros},
{ 0 }
};
Loading