-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Add a _malloca-like API Span<T>.Alloc(int length) #25423
Comments
Have heard from people that know the pattern; "what's the right number to use"; so a built-in would be better (while still allowing those that know their levels to fallback to the pattern) |
An intrinsic method that conditionally turns into a The upshot is that any method that calls |
What is the right number.....that is the real question.... I am not being smart here... But for instance the stack size on a default Ubuntu dotnet core is a lot bigger than a default windows dotnet core (approx 4* the size) and it would be nice to use some of that huge stack... ;) |
@AndyAyersMS This could also be done as a compiler only change with no JIT support. There are a few ways to pull this off depending on available resources and requirements. @Drawaes TBD implementation detail that shouldn't really affect the proposal. The nice thing is that as an implementation detail the developer never has to be bothered with it. :) |
But you know us developers, if that stack size is too conservative/low, we won't use the API and go the manual route again. But you're obviously correct that it is an Implementation detail. |
@Tornhoof Yup, but to be honest I'm not too worried about that. The folks commenting in this thread are self-selecting from the highest group of enthusiast / advanced developers. You're always going to have scenarios that will be better served by something custom that can take advantage of domain-specific knowledge. In those cases you're not the target audience of these APIs. And that's perfectly ok! Use the APIs under consideration at https://github.com/dotnet/corefx/issues/26954 if that's more applicable to your scenario. This specific issue is for the 99% use case. If needed we can always tweak to try to make it encompass the 99.9% use case. But KISS is the driving motivation here, and that can't be compromised. |
The warning in the compiler needs to go in quick... as this API might have a process to go through, how about split the warning out and get it pushed through I think the warning is super important! Aka a rosyln analyser |
@Drawaes In that case, I think an issue in dotnet/roslyn should be opened for that. |
One case I didn't see called out in the proposal is how to deal with older compilers. Take C# 7.2 which shipped with full Best way to prevent this is to add a modreq to
The compiler team does not differentiate between adding new warnings and adding new errors to the compiler. We treat all new diagnostics as errors (too many customers correctly use |
@krwq recently wrote a tool that pings the security team whenever |
Just as a note, the threshold for _malloca on Windows is For reference: |
I experimented with this a little bit recently, and from the runtime perspective it turns out we can make it work without too much pain. The biggest problem is what Jared pointed out earlier: the C# compiler won't restrict these spans from escaping out of the local method. So if you use it you have to be disciplined about it without relying on compiler support. At the moment that seems strictly worse. |
Agreed. |
Also stackalloc ref types to |
I'm closing this in favor of #52065, which proposes more concrete APIs. @tannergooding - check out the original post at the top of this issue for more context. I assume your proposal argues for similar behavior. |
That's this issue? Stack recursion..? |
Bah, you're no fun. :) |
(This is distinct from the proposal at https://github.com/dotnet/corefx/issues/26954, which considers a more powerful API that can give the caller specific information about the current stack. The proposal under consideration here is only for a "KISS" API. Both proposals could exist side-by-side depending on the scenario, and in fact this proposal could depend on the more powerful API if we decide that's the right behavior.)
As the pattern
Span<T> span = stackalloc T[len];
becomes more commonplace, we're seeing a rise in incorrect usage where developers are piping through untrusted len values, potentially making their applications susceptible to reliability issues or DoS attacks. The safe language construct isSpan<T> span = ((uint)len <= 128 /* or other const */) ? stackalloc T[len] : new T[len];
. We can't rely on our larger developer audience remembering the safe pattern, and even our more knowledgeable advanced developers can forget the check from time to time.Following are concrete proposals from the security team as to how this can be addressed.
First, create a utility method
public static Span<T> Span<T>.Alloc(int length)
. This API willstackalloc
in the current frame if appropriate; otherwise the method will heap-alloc, similar to the CRT's _malloca API. Adding this method and getting the desired runtime behavior would not require compiler changes, but it would require JIT changes. The implementation of the method would default simply tonew T[length]
if length is negative or is too large. Advanced developers who want to pull from an existing array pool as fallback wouldn't use this API; they'd perform the check manually.Second, once the utility method is in place, the compiler should be smart enough to treat
return Span<T>.Alloc(...);
as a compile-time error, just as it does today forSpan<T> span = stackalloc T[...]; return span;
. This would require a compiler change.Third, the developer should be warned when passing a non-constant and non-bounds-checked value into
stackalloc
, and the warning should direct the developer to useSpan<T>.Alloc
instead. The developer should also be warned when usingstackalloc
orSpan<T>.Alloc
in a loop. (We considered warning on recursive method calls, but that really belongs in a different analyzer.) Making this a proper compiler warning is probably a bit too noisy, so it could be a Roslyn code analyzer instead. This wouldn't require a compiler or JIT change; it'd just be a new version of the analyzers package for developers who run it as part of build.Finally, remember that this is a KISS proposal. It's intended for the majority use case for developers who may want to consume
Span
-based APIs but need a bit of a safety net. Advanced developers could still use the other APIs under consideration or perform their own custom checks as appropriate for their applications.The text was updated successfully, but these errors were encountered: