-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
[vm/ffi] Variable length inline arrays no bounds checks #55964
Comments
Yes! First, I want to share some stats on how common variable-size arrays are in Windows APIs. In win32metadata (v58.0.18), there are a total of Currently, it's a bit painful to work with variable-sized arrays as we need to do a manual offset calculation to access the pointer to the first element of the array. While #41237 could be helpful here, I would like to see the addition of |
This particular issue arises due to win32 API oddities, which I'd prefer we not introduce special API constructs for if possible. So my preferred solution for this would be if we had a general mechanism for structs that have variable-data that follows (which I guess #52366 tracks). Then the (Orthogonal to that, we may consider having a way to omit bounds checks - as C code wouldn't perform them either. Possibly only do them in |
@halildurmus Are all of these single-dimension variable-length arrays? Or are there multi-dimension arrays as well? |
According to the metadata, these are all single-dimensional variable-length arrays and there are no multi-dimensional arrays in Win32 structs. |
From @lrhn in https://dart-review.googlesource.com/c/sdk/+/371960?tab=comments
#include <cstdlib>
struct HectoChunks {
int chunkCount;
int chunk[][10][10];
};
HectoChunks* allocChunks(int chunkCount);
int main(int argc, const char* args[]) {
HectoChunks *h = allocChunks(42);
// Use it:
for (int i = 0; i < h-> chunkCount; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
h->chunk[i][j][k] = i * 100 + j * 10 + k;
}
}
}
}
HectoChunks* allocChunks(int chunkCount) {
HectoChunks* chunks = reinterpret_cast<HectoChunks*>(
malloc(sizeof(int) + chunkCount * sizeof(int[10][10])));
chunks->chunkCount = 10;
return chunks;
} We could, this would require a different annotation design. It would require a final class HectoChunks extends Struct {
@Int()
external int chunkCount;
@Array(Array.variableLength, 10, 10)
external Array<Array<Array<Int>>> chunk;
} All consts are evaluated in the CFE already, so we would not be able to distinguish such annotation from: final class HectoChunks extends Struct {
@Int()
external int chunkCount;
@Array(0, 10, 10)
external Array<Array<Array<Int>>> chunk;
} (Unless we change the type of dimension from Losing the distinction between @mkustermann @mraleph Are you aware of any use of higher-dimension variable length arrays in C? |
The variable dimension is always the first, so could it be That is, just more arguments to the constructor for the later dimensions. |
That would work. 👍 Then we'd also need a |
IMHO we should have the same or at least similar expressibility in Dart FFI as we have in C. |
The current CL provides an API that we can extend without breaking the API in the current CL.
Not that much I believe, half a day maybe. Happy to change the current CL, do a follow up CL, or leave it to the future. |
In that case, let's just do it in this CL. |
Some Windows APIs seem to rely on allowing out of bounds access of inline arrays.
The last element is defined as length 1, but used as a larger length.
This is similar to the length 0 as variable length in GNU compilers, but there the length is 0.
With a length of 0, we could detect that it's intended as variable length and skip the bounds checks (#52366). Moreover, we should probably disallow doing
Allocator.call
on these, and it should be documented thatsizeOf<...>()
on those returns the size without the variable length last element (which corresponds to how it works in C withsizeof
of such structs).But a size 1 inline array is perfectly well-defined C, it does not communicate in any way a variable length array. (So far the only example that I've seen are these old Windows APIs.)
We should explore how we can facilitate such APIs.
If we only ever expect to have such structs backed by C memory, then:
If we want to support such structs backed by Dart memory, then Array should have some kind of escape hatch. Some options:
Array.unsafeResize
that allows one to ditch bounds.@Array.variable
annotation for fields for variable arrays in structs ([ffi] Support inline array of variable length #52366).Thanks for reporting @kirill-21!
cc @halildurmus I presume you've run into this already in
package:win32
? Any thoughts?For a
@Array.variable
we can't reasonably target it with FFIgen. But if it's all Windows APIs and everyone is using these throughpackage:win32
then it's fine, becausepackage:win32
has its own code generator.cc @mkustermann @HosseinYousefi
The text was updated successfully, but these errors were encountered: