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

Leverage new MemorySizeAttribute in metadata #271

Closed
AArnott opened this issue May 20, 2021 · 6 comments · Fixed by #923
Closed

Leverage new MemorySizeAttribute in metadata #271

AArnott opened this issue May 20, 2021 · 6 comments · Fixed by #923
Labels
enhancement New feature or request metadata gem A feature of the metadata that cswin32 does not yet utilitze

Comments

@AArnott
Copy link
Member

AArnott commented May 20, 2021

I'm not sure what it does yet, but we should see what it can offer the C# projection.

@AArnott AArnott added the enhancement New feature or request label May 20, 2021
@KevinCathcart
Copy link

KevinCathcart commented May 26, 2021

I'm not sure what it does yet

It appears you used to know what it did. perhaps reviewing #225 could help you remember.

The attribute points to the parameter that specifies the memory size in byte that the called function may access starting from pointer parameter it is attached to. It seems to have at least three use cases.

The simplest use case is pointers representing arrays. This is basically the same as [NativeArrayInfo]'s CountParamIndex, except it is always measured in units of bytes. For byte* arrays both cases are synonyms. It also gets used with void* for buffers. If it were to be used with other array element sizes, it would be count*sizeof(ElementType), but I don't think that actually happens anywhere.

The second use case is for a version of the extensible struct pattern (like where the struct has a field that indicates its own size), without having the size field in the struct itself but instead as a separate parameter.

The third use case use case is rather esoteric. It applies when an output parameter of a function is a struct containing a flexible array member (or the pre-standard equivalent, known as the "struct hack", where the last field of the struct is an array of unspecified size, determined by how much you malloc/alloca). In that case, you need to specify the total size of the buffer available to write the struct to (since the struct size can vary), and it needs to fail if the buffer you provided is too small. For an example, this scenario happens with the AccessCheck family of APIs in conjunction with the struct Windows.Win32.Security.PRIVILEGE_SET.

Flexible array member structs are obviously a bit obnoxious to project into other languages since they violate the concept of structs being fixed sized. CsWin32 does not appear to handle these well right now. It sees the flexible array member as a fixed sized inline array of size 1, because that is how they are being represented in the metadata. That would probably need to be improved before this third use case could be handled.

Hope this helps.

@jnm2
Copy link
Contributor

jnm2 commented May 27, 2021

You used to know what it did: see #225

Could come across as a bit rough.

@KevinCathcart
Copy link

KevinCathcart commented May 27, 2021

Could come across as a bit rough.

Fair point. It was intended as a pointer to help Andrew remember what must have slipped his mind in the subsequent time, given everything else done since. Adjusted the wording to be harder to misinterpret the intention.

The first two cases I outlined should hopefully be at least a little familiar, since both got mentioned in the issue that originally led to the new attribute. The third case however might be new. I couldn't find much in the code or issues about the flexible array members or the struct hack, and there definitely seems to be nothing in any of the repositories about how this attribute can relate to those.

@jnm2
Copy link
Contributor

jnm2 commented May 27, 2021

We discussed the third case in #117 and microsoft/win32metadata#266 with the BITMAPINFO struct as an example.

@KevinCathcart
Copy link

Yes and no. When i was saying it was new, I meant very specifically with respect to this attribute.

Those issues you referenced discussed the struct hack, but did not really seem to discuss the case where they are being used as an output parameter of an api. They most certainly did not point out that those apis will almost always have a buffer size argument often with this newish attribute on it.

What was being discussed there was mostly some basic details of the shape for the representation (with plenty of emphasis on the fixed sized array cases too), and any Metadata improvements for flagging these structs. Hence why I said "not much".

Despite its size Issue 117 was still a relatively cursory look at variable size structs, mostly because a key concern there was getting something workable for downlevel frameworks that don't have span, or only have slow span, which is less safe in some scenarios.

Another consideration not brought up there is if there was anything that could or should be done to help the user allocate memory for those variable sized structs. The answer of course is that there is plenty that could be done to help there, if deemed desireable.

Example of what could be done For example, the code could provide a factory method that takes total byte size (or even element count, and calculate the size), allocates a byte array of that size, gets a ref to element 0, uses Unsafe.As to turn it into a ref of the struct type, and returns it as a ref return. Unlike the span stuff, nothing in such an allocation helper should cause GC problems, even on old platforms. Interior pointers located as local variables have been supported by the framework basically forever, due to refs to array elements. The GC won't care about changing a managed pointer of one value type into another, especially if both are blitable, so contain no object references.

Similarly, relatively little was said about if any changes to the friendly overloads would help improve things for the (not much that is both feasible and sensible springs to mind for the output case).

@AArnott
Copy link
Member Author

AArnott commented Apr 28, 2023

Thank you @KevinCathcart for enumerating the 3 scenarios we have. That was enlightening. The first case (representing arrays) in irritating because it overlaps with NativeArrayInfoAttribute yet does it ambiguously so I don't know whether the pointer is to an array or just one struct. I filed microsoft/win32metadata#1555 to track that. I think all such uses should switch to NativeArrayInfoAttribute to resolve the ambiguity.

Cases 2 and 3 seem to be the in and out variants of variable size structs. In that case, it's not clear to me that CsWin32 should do anything to assist in this case, since we can't emit sizeof code or similar to find the size of a struct whose size can actually vary. Even in the versioned structs, if the user passes in a pointer to a FOO2 as an argument to a FOO* parameter, CsWin32 had better not inject sizeof(FOO) as the automated value for the size parameter.

In summary, I think I should close this issue as fixed with #923, which seems like the only safe use of this attribute (and hopefully going away soon anyway).

AArnott added a commit that referenced this issue Jun 12, 2024
* Bump xunit from 2.8.0 to 2.8.1

Bumps [xunit](https://github.com/xunit/xunit) from 2.8.0 to 2.8.1.
- [Commits](xunit/xunit@2.8.0...2.8.1)

---
updated-dependencies:
- dependency-name: xunit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump Microsoft.NET.Test.Sdk from 17.9.0 to 17.10.0

Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.9.0 to 17.10.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](microsoft/vstest@v17.9.0...v17.10.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump xunit.runner.visualstudio from 2.8.0 to 2.8.1

Bumps [xunit.runner.visualstudio](https://github.com/xunit/visualstudio.xunit) from 2.8.0 to 2.8.1.
- [Release notes](https://github.com/xunit/visualstudio.xunit/releases)
- [Commits](xunit/visualstudio.xunit@2.8.0...2.8.1)

---
updated-dependencies:
- dependency-name: xunit.runner.visualstudio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request metadata gem A feature of the metadata that cswin32 does not yet utilitze
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants