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

Record fields with &default constructors and expiration attributes may not trigger their timers, causing state leaks #3513

Open
ckreibich opened this issue Dec 16, 2023 · 1 comment
Labels
Area: Scripting Complexity: Modest A cup of tea and an evening (or two) with Zeek. Implementation: Core Implementation requires modification of the Zeek core Type: Bug 🐛 Unexpected behavior or output.

Comments

@ckreibich
Copy link
Member

ckreibich commented Dec 16, 2023

As discussed on Slack, in the following snippet from SMB::State$recent_files the &read_expire timer never applies, causing the set to grow indefinitely:

                ## A set of recent files to avoid logging the same
                ## files over and over in the smb files log.
                ## This only applies to files seen in a single connection.
                recent_files : set[string] &default=string_set() &read_expire=3min;

It works when using:

                recent_files : set[string] &default=set() &read_expire=3min;

The cause is differing associativity —

(&default=string_set()) (&read_expire=3min)

vs

&default=(set() &read_expire=3min)

as evidenced by the fact that the following does not parse, since the parser has no alternative to fall back to:

print string_set() &read_expire=3sec;

A few ideas for fixes:

  • Of course it'd be ideal if the parser just did the right thing — not sure how feasible that is in the general case because given sufficiently complex attributes this basically becomes arithmetic ... whether you mean 2 + (3 * 2) or (2 + 3) * 2 is up to you.
  • Require attributes bound to constructors to be expressed inside parentheses, so &default=(string_set() &read_expire=3min).
  • For record fields it doesn’t make sense to have any container attributes associated with them if they’re optional (which &default implies), because those attributes will be lost if the field is initially missing but later populated. So we could check for that case and generate a warning (or error outright).

It might be good to review our attribute code to see whether we have any others that allow expressions that introduce their own attributes.

Scanning the scripts tree finds no other instance where we use &default with an expiration timer and a derived type.

I'm adding this to 6.2 and the backport list for 6.0. Let's see how we resolve this and determine backporting then.

@awelzel, @vpax, fyi.


Related: zeek/zeek-docs#179

type R: record {
        s: set[string] &ordered &default=set("1", "2", "3", "4", "5");
};
@ckreibich ckreibich added Complexity: Modest A cup of tea and an evening (or two) with Zeek. Type: Bug 🐛 Unexpected behavior or output. Area: Scripting Implementation: Core Implementation requires modification of the Zeek core labels Dec 16, 2023
@ckreibich
Copy link
Member Author

#3511 fixes the specific instance of the problem in the SMB code; this ticket is about resolving the broader parsing problem.

awelzel added a commit that referenced this issue Dec 17, 2023
The SMB::State$recent_files field is meant to have expiring entries.
However, due to usage of &default=string_set(), the &read_expire
attribute is not respected causing unbounded state growth. Replace
&default=string_set() with &default=set().

Thanks to ya-sato on Slack for reporting!

Related: zeek/zeek-docs#179, #3513.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Scripting Complexity: Modest A cup of tea and an evening (or two) with Zeek. Implementation: Core Implementation requires modification of the Zeek core Type: Bug 🐛 Unexpected behavior or output.
Projects
Status: No status
Status: No status
Development

No branches or pull requests

1 participant