Skip to content

fix: add missing zend_string_release calls to prevent memory leaks#77

Merged
kjdev merged 1 commit into
masterfrom
fix/memory-leak
Aug 12, 2025
Merged

fix: add missing zend_string_release calls to prevent memory leaks#77
kjdev merged 1 commit into
masterfrom
fix/memory-leak

Conversation

@kjdev

@kjdev kjdev commented Aug 12, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • Bug Fixes
    • Resolved a memory leak that occurred when handling Brotli dictionaries during certain error scenarios, improving overall stability.
    • Improved memory cleanup in edge cases related to Brotli dictionary availability checks, reducing potential memory footprint and avoiding rare crashes.

@coderabbitai

coderabbitai Bot commented Aug 12, 2025

Copy link
Copy Markdown

Walkthrough

Adds zend_string_release(dict) on two error paths in php_brotli_output_handler_load_dict within brotli.c to free the allocated dictionary string before setting it to NULL. Other control flow and existing frees remain unchanged.

Changes

Cohort / File(s) Summary
Brotli output handler memory cleanup
brotli.c
Inserted zend_string_release(dict) on dictionary error branches in php_brotli_output_handler_load_dict; dict still set to NULL afterward. No other logic changes; existing b64 buffer handling unchanged.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Possibly related PRs

Poem

I nibble code like clover sprigs,
Snipping leaks with tidy gigs;
A dict set free on error’s sigh,
I twitch my nose and hop on by.
Buffers snug, no bytes adrift—
Thump-thump: a clean-up gift. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/memory-leak

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@kjdev

kjdev commented Aug 12, 2025

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 12, 2025

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🔭 Outside diff range comments (1)
brotli.c (1)

473-485: Memory leak: dict not released in early-return and success paths

php_brotli_output_handler_load_dict() returns a freshly allocated zend_string that must be released by the caller. In php_brotli_output_handler_context_start():

  • If BROTLI_G(compression_coding) is false (Lines 475-477), we return without releasing dict → leak.
  • On the success (or failure) path of php_brotli_context_create_encoder_ex(...) (Lines 479-485), dict is not released. Per team learning, ownership is not transferred to the encoder create function; cleanup is handled by callers (see retrieved learnings).

Proposed fix releases dict in all return paths:

 static int php_brotli_output_handler_context_start(php_brotli_context *ctx)
 {
     long level = BROTLI_G(output_compression_level);
     zend_string *dict = php_brotli_output_handler_load_dict(ctx);
     if (!BROTLI_G(compression_coding)) {
-        return FAILURE;
+        if (dict) {
+            zend_string_release(dict);
+        }
+        return FAILURE;
     }
 
-    return php_brotli_context_create_encoder_ex(ctx,
-                                                level,
-                                                BROTLI_DEFAULT_WINDOW,
-                                                BROTLI_MODE_GENERIC,
-                                                dict,
-                                                0);
+    int rc = php_brotli_context_create_encoder_ex(ctx,
+                                                  level,
+                                                  BROTLI_DEFAULT_WINDOW,
+                                                  BROTLI_MODE_GENERIC,
+                                                  dict,
+                                                  0);
+    if (dict) {
+        zend_string_release(dict);
+    }
+    return rc;
 }
🧹 Nitpick comments (1)
brotli.c (1)

452-452: Consistency nit: prefer zend_string_release over zend_string_free

Elsewhere we use zend_string_release(dict). For consistency and to avoid confusion about refcount semantics, consider using zend_string_release(b64) here as well.

-                zend_string_free(b64);
+                zend_string_release(b64);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 00d09d7 and a710f26.

📒 Files selected for processing (1)
  • brotli.c (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-02T04:03:47.808Z
Learnt from: kjdev
PR: kjdev/php-ext-brotli#64
File: brotli.c:122-134
Timestamp: 2025-05-02T04:03:47.808Z
Learning: In the php-ext-brotli extension, encoder/decoder resource cleanup is deliberately handled by the caller functions rather than within resource creation functions like `php_brotli_context_create_encoder_ex`. The cleanup is done via `php_brotli_context_close()` which properly destroys any encoder/decoder instances.

Applied to files:

  • brotli.c
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: ci (8.1, x86, nts, vs16, false)
  • GitHub Check: ci (8.1, x86, nts, vs16, true)
  • GitHub Check: ci (8.1, x86, ts, vs16, true)
  • GitHub Check: ci (8.1, x64, nts, vs16, true)
  • GitHub Check: ci (8.1, x86, ts, vs16, false)
  • GitHub Check: ci (8.1-zts-alpine, system, apcu, php, linux/amd64)
  • GitHub Check: ci (8.2, x86, ts, vs16, false)
  • GitHub Check: ci (8.2, x86, nts, vs16, true)
  • GitHub Check: ci (8.3, x86, ts, vs16, true)
  • GitHub Check: ci (8.3, x64, ts, vs16, true)
  • GitHub Check: ci (8.2, x64, nts, vs16, false)
  • GitHub Check: ci (8.3, x86, nts, vs16, true)
  • GitHub Check: ci (8.3, x86, nts, vs16, false)
  • GitHub Check: ci (8.3, x64, ts, vs16, false)
🔇 Additional comments (2)
brotli.c (2)

449-451: Good catch: release dict on invalid available-dictionary path

Releasing the zend_string before nulling it fixes a real leak on this error path. Looks correct and safe.


458-460: Good catch: release dict when Available-Dictionary header is missing

Same here—this closes the leak when the header isn’t present. Change looks good.

@kjdev kjdev merged commit a710f26 into master Aug 12, 2025
132 of 156 checks passed
@kjdev kjdev deleted the fix/memory-leak branch August 12, 2025 01:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant