Skip to content

Conversation

@ShelbyZ
Copy link

@ShelbyZ ShelbyZ commented Nov 13, 2025

Summary

CloudWatch logs PutLogEvents API change in 2025 to support events up to 1MB (ref) while our defaults reflect the older value 256KB.

Add runtime tests to validate the new limit:

  • event_size_near_limit: Validates events just under 1MB are accepted
  • event_size_at_aws_max: Validates events near AWS max are truncated
  • event_truncation_with_backslash: Validates backslash handling at truncation boundary

Enter [N/A] in the box, if an item is not applicable to your change.

Testing
Before we can approve your change; please submit the following in a comment:

  • [N/A] Example configuration file for the change
  • Debug log output from testing the change

Gist: https://gist.github.com/ShelbyZ/76bfac405e03723efeb532a48d5b6a87

Over-limit on current logs

2025-11-13T04:37:45.155000+00:00 fluent-bit/log-router/b5075d48a899473fb8e8acc51e786ac2 [2025/11/13 04:37:45.155344086] [ warn] [output:cloudwatch_logs:app-logs-output] [size=1047894] Truncating event which is larger than max size allowed by CloudWatch
2025-11-13T04:37:45.155000+00:00 fluent-bit/log-router/b5075d48a899473fb8e8acc51e786ac2 [2025/11/13 04:37:45.155470414] [debug] [output:cloudwatch_logs:app-logs-output] Using stream=b5075d48a899473fb8e8acc51e786ac2, group=/ecs/fluentbit-workshop-lab3/app-logs
2025-11-13T04:37:45.159000+00:00 fluent-bit/log-router/b5075d48a899473fb8e8acc51e786ac2 [2025/11/13 04:37:45.155790284] [debug] [output:cloudwatch_logs:app-logs-output] cloudwatch:PutLogEvents: events=1, payload=262280 bytes

New limit

2025-11-13T04:32:20.986000+00:00 fluent-bit/log-router/21e880b6b1774c8e8ec2a6fb6b4679ea [2025/11/13 04:32:20.986187322] [debug] [output:cloudwatch_logs:app-logs-output] Using stream=21e880b6b1774c8e8ec2a6fb6b4679ea, group=/ecs/fluentbit-workshop-lab3/app-logs
2025-11-13T04:32:20.986000+00:00 fluent-bit/log-router/21e880b6b1774c8e8ec2a6fb6b4679ea [2025/11/13 04:32:20.986606024] [debug] [output:cloudwatch_logs:app-logs-output] cloudwatch:PutLogEvents: events=1, payload=1048057 bytes
2025-11-13T04:32:20.986000+00:00 fluent-bit/log-router/21e880b6b1774c8e8ec2a6fb6b4679ea [2025/11/13 04:32:20.986614394] [debug] [output:cloudwatch_logs:app-logs-output] Sending log events to log stream 21e880b6b1774c8e8ec2a6fb6b4679ea

Tested directly against CloudWatch Logs via PutLogEvents to discover that a maximum value of 1,048,546 bytes could be sent without issue. Using 1,000,000 bytes (1MB) gives a safe margin to avoid calculations for the PUT_LOG_EVENTS_PAYLOAD_SIZE which would need reevaluation to support observed max. The encoded max size was also 1,048,586 bytes which is 10 bytes about 1MiB (1,048,576) which makes me worry that depending on an exact max may break over time.

  • [WIP] Attached Valgrind output that shows no leaks or memory corruption was found

If this is a change to packaging of containers or native binaries then please confirm it works for all targets.

  • [N/A] Run local packaging test showing all targets (including any new ones) build.
  • [N/A] Set ok-package-test label to test for all targets (requires maintainer to do).

Documentation

  • [N/A] Documentation required for this feature

Backporting

  • [N/A] Backport to latest stable release.

Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.

Summary by CodeRabbit

  • Improvements

    • Increased maximum CloudWatch log event payload size from ~256 KB to 1 MB to allow larger single-request events.
    • Added a new public constant to control entity prefix length.
  • Tests

    • Added end-to-end tests for events at the size limit, over the new limit, and truncation edge cases (including backslash handling).

✏️ Tip: You can customize this high-level summary in your review settings.

@ShelbyZ ShelbyZ requested a review from a team as a code owner November 13, 2025 04:58
@coderabbitai
Copy link

coderabbitai bot commented Nov 13, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Updated CloudWatch Logs public header: MAX_EVENT_LEN increased from 262118 to 1000000 with an expanded explanatory comment; added new public macro AWS_ENTITY_PREFIX_LEN = 10. Added three runtime tests to validate large-event handling and truncation behavior.

Changes

Cohort / File(s) Summary
CloudWatch API header
plugins/out_cloudwatch_logs/cloudwatch_api.h
Updated macro MAX_EVENT_LEN from 262118 to 1000000 and replaced the short comment with a multi-line explanatory documentation block; added new public macro AWS_ENTITY_PREFIX_LEN with value 10.
CloudWatch runtime tests
tests/runtime/out_cloudwatch.c
Added inclusion of the CloudWatch API header, new JSON test constants, helper create_large_json_message(size_t), helper run_cloudwatch_test_with_data(char*, size_t), and three tests: flb_test_cloudwatch_event_size_at_limit, flb_test_cloudwatch_event_size_over_limit, flb_test_cloudwatch_event_truncation_with_backslash. Registered these tests in the test list.

Sequence Diagram(s)

Not applicable — changes are macro/documentation updates and new test cases; no runtime control-flow or component interaction changes to diagram.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Focus review on:
    • plugins/out_cloudwatch_logs/cloudwatch_api.h — confirm documentation accuracy and potential ABI/consumer expectations for the larger MAX_EVENT_LEN.
    • tests/runtime/out_cloudwatch.c — verify large message allocation, memory usage, correct truncation behavior (especially handling of trailing backslash), and test isolation/cleanup.
    • Search for call sites or static buffers that assumed the previous MAX_EVENT_LEN.

Poem

🐰 I nibble bytes beneath the moon,

I stretch the logs to one million tune.
I craft a JSON, then trim with care,
Escape the slash that may snare.
Hooray — big messages land safe there.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: increasing MAX_EVENT_LEN to 1MB and adding corresponding tests.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ShelbyZ ShelbyZ force-pushed the cloudwatch_event_size branch from 7c85150 to ee95b3b Compare November 18, 2025 19:31
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c85150 and ee95b3b.

📒 Files selected for processing (1)
  • plugins/out_cloudwatch_logs/cloudwatch_api.h (1 hunks)
🔇 Additional comments (1)
plugins/out_cloudwatch_logs/cloudwatch_api.h (1)

56-56: I'll search the repository directly for the constants to verify the buffer calculations:Based on my verification, here's the rewritten review comment:

MAX_EVENT_LEN increase to 1,000,000 is correct and properly handled.

The increase to 1,000,000 bytes correctly reflects CloudWatch's 2025 update supporting log events up to 1 MB. Verification confirms the buffer logic is sound:

  • Individual events are truncated at MAX_EVENT_LEN (cloudwatch_api.c:558-561)
  • Payload size is calculated as the sum of all event messages in UTF-8, plus 26 bytes for each log event, and the code conservatively uses 42 bytes per event
  • Batch size check (cloudwatch_api.c:891) prevents payloads from exceeding PUT_LOG_EVENTS_PAYLOAD_SIZE
  • Maximum single event with overhead: 1,000,000 + 42 = 1,000,042 bytes fits within the 1,048,576-byte batch limit

No buffer sizing issues detected.

@ShelbyZ ShelbyZ force-pushed the cloudwatch_event_size branch 2 times, most recently from 3d7597b to ee654ea Compare November 19, 2025 19:22
@ShelbyZ ShelbyZ changed the title Increase MAX_EVENT_LEN to match current max out_cloudwatch_logs: increase MAX_EVENT_LEN to 1MB with tests Nov 19, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
tests/runtime/out_cloudwatch.c (5)

12-14: Avoid duplicating MAX_EVENT_LEN and keep tests tied to the real limit

Here you reintroduce MAX_EVENT_LEN locally but it’s not used anywhere in this file, and the actual definition already lives in cloudwatch_api.h. That creates a drift risk if the plugin constant changes again.

Consider either:

  • Including the CloudWatch API header and using its MAX_EVENT_LEN directly in the tests, or
  • Wiring these tests to use this macro (e.g., create_large_json_message(MAX_EVENT_LEN - 1000), constructing “over-limit” payloads as MAX_EVENT_LEN + delta) instead of hard‑coded sizes later in the file.

399-430: create_large_json_message is bounds-safe but relies on magic offsets

The allocation and index math look safe (no obvious buffer overruns), but the use of hard-coded values (12 for the prefix offset, 15 for the “overhead” size) makes this helper fragile if the JSON structure ever changes.

You could make this more robust and self-documenting by defining prefix/suffix strings and using strlen for lengths, e.g. const char *prefix = "{\"message\":\""; const char *suffix = "\"}"; and computing offsets from those instead of literal 12/15.


432-468: Nice reuse of CloudWatch setup; consider minimal defensive checks

This helper cleanly de-duplicates the common setup/teardown logic and pushes arbitrary JSON payloads via the existing lib input/output harness. Functionally it’s consistent with the rest of the file.

If you want to harden it slightly, you could add a TEST_CHECK(ctx != NULL); after flb_create() to fail fast on allocation/init errors, but that’s in line with (and optional relative to) existing tests.


470-498: Use MAX_EVENT_LEN (or AWS max) instead of hard-coded sizes in new large-event tests

Both flb_test_cloudwatch_event_size_near_limit and flb_test_cloudwatch_event_size_at_aws_max currently hard-code 999000 and 1048500 while the file defines MAX_EVENT_LEN and the PR is about aligning with CloudWatch’s updated maximum.

To keep these tests robust against future limit changes and better reflect their intent:

  • For the “near limit” test, derive the size from MAX_EVENT_LEN (e.g., MAX_EVENT_LEN - 1000 or similar), rather than 999000 directly.
  • For the “AWS max” test, consider either:
    • Using a named constant that documents how it relates to the AWS limit (e.g., AWS_MAX_EVENT_SIZE_APPROX), or
    • Deriving it from MAX_EVENT_LEN plus a clear delta that documents “this should be truncated down to MAX_EVENT_LEN”.

That would remove magic numbers and ensure these tests stay aligned with the semantics they’re meant to cover.


500-525: Backslash-boundary test indexing looks correct but could reuse the JSON helper

The manual construction of the backslash-heavy payload appears bounds-safe: the loop limit (i < 999980), the base offset (12), and the subsequent strcpy(large_json + 12 + 999980, "\"}") all fit well within the flb_malloc(1000100) buffer.

To reduce the amount of manual index arithmetic and keep the JSON shape consistent with other tests, you could consider building the bulk of the message via create_large_json_message() and then post-processing the payload (e.g., walking the message body and replacing selected characters with \\) instead of re-encoding `{"message":"..."} by hand here.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d7597b and ee654ea.

📒 Files selected for processing (2)
  • plugins/out_cloudwatch_logs/cloudwatch_api.h (1 hunks)
  • tests/runtime/out_cloudwatch.c (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/out_cloudwatch_logs/cloudwatch_api.h
🧰 Additional context used
🧬 Code graph analysis (1)
tests/runtime/out_cloudwatch.c (3)
plugins/out_s3/s3.c (1)
  • setenv (57-60)
src/flb_lib.c (9)
  • flb_create (143-225)
  • flb_input (266-276)
  • flb_input_set (305-335)
  • flb_output (279-289)
  • flb_output_set (520-551)
  • flb_start (983-994)
  • flb_lib_push (843-870)
  • flb_stop (1011-1055)
  • flb_destroy (228-263)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
🔇 Additional comments (1)
tests/runtime/out_cloudwatch.c (1)

539-541: Registering new tests in TEST_LIST looks correct

The new tests are properly added to TEST_LIST with descriptive names and the required {NULL, NULL} terminator remains intact. This should integrate cleanly with the existing runtime test harness.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
tests/runtime/out_cloudwatch.c (1)

403-437: Consider safer string operations and add documentation.

The function is correct but could be improved:

  1. strcpy usage (lines 424, 433): Consider using memcpy or strncpy for explicit length control, even though the current usage is safe.

  2. Silent size adjustment (lines 414-416): The function silently adjusts target_size if it's too small. Consider returning NULL or documenting this behavior.

  3. Missing documentation: Add a comment noting that the caller must free the returned pointer.

Example improvement for the strcpy calls:

-    strcpy(json, TEST_JSON_PREFIX);
+    memcpy(json, TEST_JSON_PREFIX, prefix_len);
-    strcpy(json + prefix_len + data_size, TEST_JSON_SUFFIX);
+    memcpy(json + prefix_len + data_size, TEST_JSON_SUFFIX, suffix_len);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3bf4539 and bb01b00.

📒 Files selected for processing (2)
  • plugins/out_cloudwatch_logs/cloudwatch_api.h (1 hunks)
  • tests/runtime/out_cloudwatch.c (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/runtime/out_cloudwatch.c (3)
plugins/out_s3/s3.c (1)
  • setenv (57-60)
src/flb_lib.c (9)
  • flb_create (143-225)
  • flb_input (266-276)
  • flb_input_set (305-335)
  • flb_output (279-289)
  • flb_output_set (520-551)
  • flb_start (983-994)
  • flb_lib_push (843-870)
  • flb_stop (1011-1055)
  • flb_destroy (228-263)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
🔇 Additional comments (7)
plugins/out_cloudwatch_logs/cloudwatch_api.h (2)

46-56: LGTM! Conservative limit with clear documentation.

The 1MB limit with ~4.6% safety margin is a sound approach for production reliability. The comment clearly documents the rationale and empirical testing results.


60-60: Good addition for maintainability.

Defining the prefix length as a constant improves code clarity and reduces magic numbers.

tests/runtime/out_cloudwatch.c (5)

8-9: LGTM! Correct header inclusion.

Including the CloudWatch API header provides access to MAX_EVENT_LEN and other constants needed for the new tests.


15-17: LGTM! Clear test structure constants.

These constants appropriately define the JSON envelope for constructing test messages.


439-476: LGTM! Standard test helper implementation.

The function properly sets up the test environment, handles optional data injection, and ensures cleanup.


478-534: LGTM! Comprehensive edge-case coverage.

The three test functions properly exercise large-event handling:

  • At-limit events
  • Over-limit events requiring truncation
  • Backslash handling at truncation boundaries (important for JSON escaping)

Memory management is correct in all tests. The tests follow the existing pattern of integration-style validation without explicit truncation assertions.

Note: The test names in code (event_size_at_limit, event_size_over_limit) differ from those mentioned in the PR objectives (event_size_near_limit, event_size_at_aws_max). The current names are more descriptive and accurate.


548-550: LGTM! Proper test registration.

The three new tests are correctly registered in the test suite with names matching their function declarations.

Increase MAX_EVENT_LEN from 262,118 bytes (256 KiB) to 1,000,000 bytes
(1 MB) to better align with AWS CloudWatch's documented maximum event
size of 1,048,576 bytes (1 MiB). The 1 MB limit provides a ~4.6% safety
margin to account for JSON encoding overhead.

Testing confirmed messages up to 1,048,546 bytes (encoding to 1,048,586
bytes) succeed, though we use a conservative limit for production safety.

Add runtime tests to validate the new limit:
- event_size_at_limit: Validates events at exactly MAX_EVENT_LEN (1MB) are accepted
- event_size_over_limit: Validates events exceeding MAX_EVENT_LEN are truncated
- event_truncation_with_backslash: Validates backslash handling at truncation boundary

Signed-off-by: Shelby Hagman <[email protected]>
@ShelbyZ ShelbyZ force-pushed the cloudwatch_event_size branch from bb01b00 to f844d36 Compare November 20, 2025 23:11
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
tests/runtime/out_cloudwatch.c (4)

403-438: Large JSON generator is correct; minor optional simplification

The helper correctly:

  • enforces a minimum target_size to hold prefix + at least one data byte + suffix,
  • allocates target_size + 1 and null‑terminates at json[target_size],
  • fills the payload so that strlen(json) == target_size.

If you ever want to shave a few lines, the data fill loop could be replaced with a memset starting at json + prefix_len for data_size bytes, but that’s purely cosmetic in a test helper.


440-477: Shared CloudWatch test harness looks consistent with existing patterns

run_cloudwatch_test_with_data mirrors the setup/teardown logic of the earlier tests (env flag, lib input, cloudwatch_logs output, start/push/stop/destroy) and correctly frees resources on the happy path.

Optionally, you could assert on the return value of flb_lib_push to catch immediate push failures, but given the existing tests do not, this is non‑blocking.


479-492: Limit-size test correctly drives a MAX_EVENT_LEN‑sized payload through the pipeline

create_large_json_message(MAX_EVENT_LEN) followed by strlen(large_json) ensures the pushed payload is exactly MAX_EVENT_LEN bytes long, which is what the truncation logic should treat as in‑bounds.

The test currently asserts only that setup succeeds and the pipeline runs without crashing, which matches the style of existing runtime tests here. If you later add hooks to inspect the mock AWS backend, this would be a good place to assert that the event was not truncated.


494-507: Over-limit test exercises truncation path, though assertions are coarse

Using create_large_json_message(MAX_EVENT_LEN + 1) ensures the input exceeds the per‑event cap and should force the CloudWatch code down the truncation path.

As with the previous test, this currently validates “no crash / no fatal error” rather than inspecting the truncated size. That’s acceptable for a runtime smoke test, but if you later expose the observed payload length from the mock backend, asserting that it equals MAX_EVENT_LEN would make this test much stronger.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb01b00 and f844d36.

📒 Files selected for processing (2)
  • plugins/out_cloudwatch_logs/cloudwatch_api.h (1 hunks)
  • tests/runtime/out_cloudwatch.c (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/runtime/out_cloudwatch.c (3)
plugins/out_s3/s3.c (1)
  • setenv (57-60)
src/flb_lib.c (9)
  • flb_create (143-225)
  • flb_input (266-276)
  • flb_input_set (305-335)
  • flb_output (279-289)
  • flb_output_set (520-551)
  • flb_start (983-994)
  • flb_lib_push (843-870)
  • flb_stop (1011-1055)
  • flb_destroy (228-263)
include/fluent-bit/flb_mem.h (1)
  • flb_free (126-128)
🔇 Additional comments (2)
tests/runtime/out_cloudwatch.c (2)

8-17: Using shared constants for JSON shape and MAX_EVENT_LEN is a good choice

Including cloudwatch_api.h and defining TEST_JSON_PREFIX/TEST_JSON_SUFFIX keeps the tests aligned with the real CloudWatch event constraints and avoids duplicated magic numbers. No issues here.


549-551: New tests are correctly registered in TEST_LIST

The three new test cases are wired into TEST_LIST with clear names matching their purposes, so they will run under the existing runtime test harness without further changes.

Comment on lines +46 to +56
/*
* https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html
* AWS CloudWatch's documented maximum event size is 1,048,576 bytes (1 MiB),
* including JSON encoding overhead (structure, escaping, etc.).
*
* Setting MAX_EVENT_LEN to 1,000,000 bytes (1 MB) provides a ~4.6% safety margin
* to account for JSON encoding overhead and ensure reliable operation.
* Testing confirmed messages up to 1,048,546 bytes (encoding to 1,048,586 bytes)
* succeed, though we use a conservative limit for production safety.
*/
#define MAX_EVENT_LEN 1000000
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Event size cap looks sound; align earlier payload comment with new semantics

The new MAX_EVENT_LEN = 1000000 choice, with the detailed comment and empirical numbers, is reasonable and keeps event->len + PUT_LOG_EVENTS_PER_EVENT_LEN comfortably under PUT_LOG_EVENTS_PAYLOAD_SIZE for a single event.

One thing to tidy up: the earlier comment at lines 23–27 still states that using the documented payload size (1,048,576) “leads to API errors” and that “no issues have been seen setting it to 1,000,000 bytes,” but PUT_LOG_EVENTS_PAYLOAD_SIZE here remains 1,048,576 while 1,000,000 is now used for MAX_EVENT_LEN. That’s confusing for future readers.

Consider updating that earlier comment to explicitly distinguish:

  • payload buffer size (still 1,048,576, per AWS docs), and
  • per‑event cap (MAX_EVENT_LEN = 1,000,000) used as a conservative safety margin.

This keeps the rationale clear and avoids implying the payload macro itself should be 1,000,000.

🤖 Prompt for AI Agents
In plugins/out_cloudwatch_logs/cloudwatch_api.h around lines 23–27 and 46–56,
the earlier comment implies the payload macro should be reduced to 1,000,000
which conflicts with the new MAX_EVENT_LEN; update the earlier comment to
explicitly state that PUT_LOG_EVENTS_PAYLOAD_SIZE remains the AWS-documented
1,048,576 byte payload buffer, while MAX_EVENT_LEN is a separate conservative
per-event cap set to 1,000,000 bytes to allow JSON-encoding overhead, and remove
any wording that suggests changing the payload macro itself to 1,000,000.

Comment on lines +509 to +535
/* Test event with trailing backslash at truncation boundary */
void flb_test_cloudwatch_event_truncation_with_backslash(void)
{
char *large_json;
size_t prefix_len = strlen(TEST_JSON_PREFIX);
size_t suffix_len = strlen(TEST_JSON_SUFFIX);
size_t total_len;
size_t data_len;
size_t i;

/* Create base message near MAX_EVENT_LEN */
large_json = create_large_json_message(MAX_EVENT_LEN + 100);
TEST_CHECK(large_json != NULL);

if (large_json) {
total_len = strlen(large_json);
data_len = total_len - prefix_len - suffix_len;

/* Post-process: replace every 100th character with backslash */
for (i = 99; i < data_len; i += 100) {
large_json[prefix_len + i] = '\\';
}

run_cloudwatch_test_with_data(large_json, strlen(large_json));
flb_free(large_json);
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Backslash truncation test likely builds invalid JSON and may not hit the boundary case

Two concerns with this helper:

  1. JSON correctness

    create_large_json_message() builds a valid JSON string. The loop:

    for (i = 99; i < data_len; i += 100) {
        large_json[prefix_len + i] = '\\';
    }

    replaces individual data characters with a single '\\' but does not adjust the following character, so many substrings inside the "message" value become \A, \B, etc. In standard JSON, a backslash must be followed by a valid escape (", \, /, b, f, n, r, t, or u); \A is invalid. If the lib input’s test formatter is parsing this as JSON (as it does for JSON_TD), this test may fail or behave differently than intended because the JSON is malformed rather than because of truncation behavior.

  2. Not guaranteed to place a backslash at the truncation boundary

    The current pattern (every 100th data character starting at offset 99) does not ensure that the character at the truncation boundary (index MAX_EVENT_LEN - 1 in the full JSON string) is a backslash. If the truncation logic only special‑cases “last byte before cut is '\'”, this test may never exercise that branch.

To both keep the JSON valid and guarantee a backslash at the boundary, you could:

  • Explicitly plant a \\ escape sequence straddling MAX_EVENT_LEN - 1 / MAX_EVENT_LEN, and
  • Optionally keep (or remove) the regular 100‑byte pattern if you still want many backslashes.

For example:

-    /* Post-process: replace every 100th character with backslash */
-    for (i = 99; i < data_len; i += 100) {
-        large_json[prefix_len + i] = '\\';
-    }
+    /* Post-process: add backslashes in the data portion */
+
+    /* 1) Ensure a backslash is exactly at the truncation boundary.
+     * MAX_EVENT_LEN is an index in the full JSON string; make sure we stay in the data range
+     * and create a valid JSON escape sequence (“\\”) there.
+     */
+    {
+        size_t boundary = MAX_EVENT_LEN - 1; /* index in full JSON string */
+
+        if (boundary + 1 < total_len - suffix_len) {
+            large_json[boundary]     = '\\';
+            large_json[boundary + 1] = '\\';
+        }
+    }
+
+    /* 2) Optionally, sprinkle additional backslashes while keeping JSON valid:
+     * turn pairs of 'A's into '\\\\' sequences.
+     */
+    for (i = 99; i + 1 < data_len; i += 100) {
+        large_json[prefix_len + i]     = '\\';
+        large_json[prefix_len + i + 1] = '\\';
+    }

This way:

  • The input JSON remains syntactically valid.
  • The character at MAX_EVENT_LEN - 1 is a backslash, so the truncation logic’s “trailing backslash” handling is actually exercised.
🤖 Prompt for AI Agents
In tests/runtime/out_cloudwatch.c around lines 509 to 535, the loop currently
injects single backslash characters into the JSON payload which produces invalid
JSON escapes and does not guarantee a backslash at the truncation boundary; fix
by (1) stop inserting lone '\' characters that create invalid escapes, (2)
instead insert valid JSON escape sequences (a pair of characters representing a
backslash in the JSON string) when mutating the payload, and (3) explicitly
place one such two‑char escape so that its first byte lands at index
MAX_EVENT_LEN - 1 of the final JSON buffer (i.e. straddle the truncation
boundary) to ensure the truncation branch is exercised, taking care to check
bounds against the buffer length and maintain existing prefix/suffix offsets;
you may keep or remove the periodic 100‑byte pattern but any injected backslash
must be written as a two‑character JSON escape.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants