To clarify, the exemption macro is STACK_ALLOCATED_IGNORE?
Does this line of code have any significance?`using IsStackAllocatedTypeMarker [[maybe_unused]] = int;`
Drive-by comment... Apparently you can have a STACK_ALLOCATED class in std::vector, which I presume allocates those on the heap. Dunno if it's an issue.
--
--
Chromium Developers mailing list: [email protected]
View archives, change email options, or unsubscribe:
https://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAC3g16icBJ86S%3DKifT66n%3DipPgdp2JzVhKRQ2SeprQ8DUVps1w%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAHOQ7J-nByVY3TYQXhHN_8aENrLb-9opvO_EyDAPouu-JoO4jg%40mail.gmail.com.
Should we annotate base::FunctionRef with this?
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAH%3DT95T%3DD-0z2LNdkSzmqgx5FFcGL8RaRCrRuenUeHvmb1mZBQ%40mail.gmail.com.
1. Pointers *inside* STACK_ALLOCATED classes/structs shouldn't be rewritten as they're short-lived (which follows our "don't rewrite local variable and parameter pointers" rule).
2. Pointers *to* STACK_ALLOCATED classes/structs shouldn't be rewritten as the pointee isn't backed by PartitionAlloc, making raw_ptr/ref a dead balast (overhead with no protection).
When we made an (unsuccessful) attempt to correlate raw_ptr/raw_ref related tools with STACK_ALLOCATED, we had two rules in mind:
1. Pointers *inside* STACK_ALLOCATED classes/structs shouldn't be rewritten as they're short-lived (which follows our "don't rewrite local variable and parameter pointers" rule).2. Pointers *to* STACK_ALLOCATED classes/structs shouldn't be rewritten as the pointee isn't backed by PartitionAlloc, making raw_ptr/ref a dead balast (overhead with no protection).This confirms that the current version of STACK_ALLOCATED has an overloaded meaning, which I'm in favor of untangling. But I think this wasn't the core of your proposal.I am not sure about renaming STACK_ALLOCATED to STACK_SCOPED. It just feels weird to delete `new` and `deleted` for something labeled STACK_SCOPED.
Disallowing `new` may look over-restricted for STACK_SCOPED
Disallowing `new` may look over-restricted for STACK_SCOPEDThat is precisely my worry that after renaming disallowing `new` will no longer fit the name and people will be tempted to remove it. How about renaming it to STACK_SCOPED_AND_DISALLOW_NEW (used by default) and having STACK_SCOPED for the exceptional cases.
On Sun, Mar 24, 2024 at 6:39 PM Bartek Nowierski <[email protected]> wrote:Disallowing `new` may look over-restricted for STACK_SCOPEDThat is precisely my worry that after renaming disallowing `new` will no longer fit the name and people will be tempted to remove it. How about renaming it to STACK_SCOPED_AND_DISALLOW_NEW (used by default) and having STACK_SCOPED for the exceptional cases.I think a comment will prevent people from removing the constraint. The theoretically perfect STACK_SCOPED() seems hard to enforce (thus error-prone) and not very useful. The shorter name might attract people to use it instead of the better STACK_SCOPED_AND_DISALLOW_NEW().
Allowing std::vector<StackAllocated> is a loophole and might be fixed in the future.
- all STACK_ALLOCATED in non-blink code will become STACK_SCOPED, and std::vector<StackScoped> will be legal instead of exploiting a loophole.
- all STACK_ALLOCATED in non-blink code will become STACK_SCOPED, and std::vector<StackScoped> will be legal instead of exploiting a loophole.My point is that std::vector<StackScoped> can be a global or heap-allocated (due to the same loophole), so STACK_SCOPED will be equally inaccurate of a name as STACK_ALLOCATED.
The new name makes the desired case of stack-scoped std::vector<StackScoped> no longer a false positive
On Wed, Apr 3, 2024 at 6:54 AM Xianzhu Wang <[email protected]> wrote:On Tue, Apr 2, 2024 at 6:37 PM Bartek Nowierski <[email protected]> wrote:- all STACK_ALLOCATED in non-blink code will become STACK_SCOPED, and std::vector<StackScoped> will be legal instead of exploiting a loophole.My point is that std::vector<StackScoped> can be a global or heap-allocated (due to the same loophole), so STACK_SCOPED will be equally inaccurate of a name as STACK_ALLOCATED.Sorry I misunderstood your point. Filed crbug.com/332583996.The two names having a common subset of false positives doesn't necessarily make them equally inaccurate. The new name makes the desired case of stack-scoped std::vector<StackScoped> no longer a false positive, and disambiguates from the blink version of STACK_ALLOCATED.For further discussions, I created a globally editable empty doc here. I haven't got time to fill it with content yet. Feel free to add anything related into the doc.On Wed, Apr 3, 2024 at 2:41 AM Xianzhu Wang <[email protected]> wrote:(-memory-safe-dev@ because it's a closed group)Actually std::optional<StackAllocated> is a good thing and Oilpan works well with it. I'm not sure about other union types. +Omer Katz
For Oilpan, it's mostly the memory allocation that matters. Life scope is less of a concern.As long as StackAllocated types are allocated on the native stack, Oilpan can find them using conservative stack scanning and handle them conservatively.std::vector<StackAllocated>, even if the vector is stack allocated, is a problem for Oilpan because the vector's backing is allocated off the stack and Oilpan will have no way of observing it and finding the objects in the vector.On-stack std::optional on the other hand is fine because the underlying object in this case will be allocated on the native stack. The same would generally apply to on-stack std::variant and unions (even though neither are gc-safe off-stack).
--Omer Katz
V8, Software Engineer
Google Germany GmbH
Erika-Mann-Straße 33
80636 München
Geschäftsführer: Paul Manicle, Liana Sebastian
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Diese E-Mail ist vertraulich. Falls Sie diese fälschlicherweise erhalten haben sollten, leiten Sie diese bitte nicht an jemand anderes weiter, löschen Sie alle Kopien und Anhänge davon und lassen Sie mich bitte wissen, dass die E-Mail an die falsche Person gesendet wurde.
This e-mail is confidential. If you received this communication by mistake, please don't forward it to anyone else, please erase all copies and attachments, and please let me know that it has gone to the wrong person.
Why can't the plugin look at all fields of type std::vector<T>, std::optional<T>, etc. and check that T is not STACK_SCOPES_*?
It should be possible as an ASTMatcher query imo. We do something similar in the blink gc plugin to detect std::vector<T>, std::optional<T> and such where T is GCed (here).Our checks for whether T is GCed or Traceable rely on it having a specific base class or a trace method. Assuming STACK_SCOPED_* contains some marker, the query for whether T is stack scopes should be as simple as this example.
I was surprised that `auto local = std::make_unique<T>();` is marked as expected to compile for STACK_SCOPED. While the unique_ptr is a local variable, it owns a heap allocation, and it can be moved in ways that cause it to outlive the current stack frame. So I would not expect us to want STACK_SCOPED in a unique_ptr, unless we have some dataflow analysis proving it does not escape the stack frame as well.
I have two ideas and one question.Idea 1: We may just ban instantiation of `std::allocator<StackAllocated>` in the clang plugin to achieve a more strict `STACK_ALLOCATED` (i.e. no `std::vector<StackAllocated>`).Idea 2: If we want to move forward with the `STACK_SCOPED` option, how about naming it like `STACK_OWNED`? I feel it's weird that we can return `std::unique_ptr<StackScoped>` from a function, as the object outlives the "scope".Question: WDYT about pointers pointing to `STACK_*` object?Currently, the plugin bans even `T*` and `T&` in member fields if `T` is `STACK_ALLOCATED`. However, in theory, it should be possible to use stack-allocated objects in the non-`STACK_ALLOCATED` class as a pointer/reference.The same for `STACK_SCOPED`. Should we ban pointers to `STACK_SCOPED` in class member fields?Honestly, I'm not particularly concerned about this point, but if we think that the name should match the reality, we need to consider this point as well.
such as forbidding `std::make_unique<StackScoped>()` altogether
such as forbidding `std::make_unique<StackScoped>()` altogetherI actually have a specific use case where I want to apply STACK_SCOPED, but std::make_unique<StackScoped>() (assigned to a local variable) is preventing me. But from the looks of it, preventing it from escaping the scope of the current call stack/task should be easy.
100%
In both examples, the pointer is returned from a function. So in that sense it's lifetime is extnede... though it still remains stack-scoped.
It can't be returned by value, because of polymorphism. It's stack scoped nonetheless.