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

fix: memory leak when decoding Lists of Bytes #68

Merged
merged 2 commits into from
Sep 15, 2024

Conversation

kantai-chris
Copy link
Contributor

Messages that include a repeated field of type bytes are not properly freed due to a missing condition in deinit_field() which only cares for list of other message types or strings, but not bytes.

This commit introduces a new unit test that fails if decoding a message with a list of bytes leaks and fix, that makes the unit test pass.

Messages that include a `repeated` field of type `bytes` are not
properly freed due to a missing condition `deinit_field()` which only
cares for list of other message types or strings, but not bytes.

This commit introduces a new unit test that fails if decoding a message
with a list of bytes leaks and fix, that makes the unit test pass.
@Arwalk
Copy link
Owner

Arwalk commented Sep 14, 2024

Thanks! I'll look into the details ASAP. It seems I introduced this bug myself recently with bytes. Seems OK at first glance, but I will look at it properly soon.

Copy link
Owner

@Arwalk Arwalk left a comment

Choose a reason for hiding this comment

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

Just a slight little change to enforce switch (which would have prevented the mistake in the first place).

But apart from that this is great, thanks for the catch!

src/protobuf.zig Outdated
@@ -586,7 +586,7 @@ fn deinit_field(result: anytype, comptime field_name: []const u8, comptime ftype
}
},
.List => |list_type| {
if (list_type == .SubMessage or list_type == .String) {
if (list_type == .SubMessage or list_type == .String or list_type == .Bytes) {
Copy link
Owner

Choose a reason for hiding this comment

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

Let's use switch here so we have the exhaustive check at compile time and avoid this kind of error in the future.

diff --git a/src/protobuf.zig b/src/protobuf.zig
index dbe0c48..ac7e811 100644
--- a/src/protobuf.zig
+++ b/src/protobuf.zig
@@ -586,10 +586,13 @@ fn deinit_field(result: anytype, comptime field_name: []const u8, comptime ftype
             }
         },
         .List => |list_type| {
-            if (list_type == .SubMessage or list_type == .String or list_type == .Bytes) {
-                for (@field(result, field_name).items) |item| {
-                    item.deinit();
-                }
+            switch (list_type) {
+                .SubMessage, .String, .Bytes => {
+                    for (@field(result, field_name).items) |item| {
+                        item.deinit();
+                    }
+                },
+                .Varint, .FixedInt => {},
             }
             @field(result, field_name).deinit();
         },

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I'll change it. Thanks for the improvement. I'm currently taking my first baby steps with zig, so I'm grateful for each learning along the way :)

In `deinit_field()` we previously used an if condition that checked for
different types within a list, but unfortunately this check was not
exhaustive. By replacing this check with an switch statement, we now
make sure that we have to handle all possible cases, otherwise we'll get
a compiler error.
@kantai-chris kantai-chris requested a review from Arwalk September 15, 2024 10:06
@kantai-chris
Copy link
Contributor Author

I changed the check to use switch instead of if, please review.

@Arwalk Arwalk merged commit f03003e into Arwalk:master Sep 15, 2024
5 checks passed
@Arwalk
Copy link
Owner

Arwalk commented Sep 15, 2024

Thanks a lot for your contribution !

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.

2 participants