-
Notifications
You must be signed in to change notification settings - Fork 161
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
Fix copy_file_range to use ABI specified len types #499
Fix copy_file_range to use ABI specified len types #499
Conversation
Signed-off-by: Alex Saveau <[email protected]>
Great find!
Can you be more specific about what would break? You might not be able to copy as much as the syscall theoretically could in a single call, but I don't see how it breaks.
I don't think
I haven't tried it (and it might take a few years to overflow a
That's a great point. I think we have two options here:
I can see the argument to make The argument for |
shit, bumped the button |
Bad wording, I meant that all the APIs will be broken: rustix will have to force everyone over to u128s whether they want to or not.
I generally agree, but I don't see any overflow checks of the
That's actually the problem. If you write this: loop {
if copy_file_range(&from, None, &to, None, u64::MAX)? == 0 {
return Ok(());
}
} It will fail on the second iteration of the loop with
That's true, and I think I would agree if it wasn't for the |
Do you mean that rustix would need to make the
That may be a bug. It'd be a bug that few people would ever be able to get anywhere near, but a bug nonetheless.
Ironically, that program fails for me on 64-bit x86_64, and passes on 32-bit i686. On x86_64, it appears Linux doesn't like that the second iteration requests Hmm, and that's actually an ugly difference. Ideally, i686 should fail in the same way as x86_64 does, but rustix has to saturate before Linux does the overflow check, and there's no way for rustix to do the overflow check itself (without doing an I'll need to think it through a little more, but that may be the thing that convinces me that |
Huh, you're right. Why did they go with a usize then? Weird.
Since your experiments suggest that 32-bit is still using 64-bit offsets (which duh now that I noticed 64 bit offsets in the function signature), I'm a little less worried about using u64s as I thought 32-bit architectures were totally broken right now. But I do agree that the inconsistency is troubling. I'm especially worried about the 32-bit to 64-bit transition. We're obviously developing on 64-bit machines, but if someone was still using a 32-bit machine for some reason, they would think their code is working fine with u64::MAX and then be confused when nothing works on other people's 64-bit machines. |
Ok, let's do this. I don't think of the kinds of things rustix does as lying per se; the idea is that there's often a conceptual API that the actual kernel API is an approximation of, within the constraints of the C language, backwards compatibility, and the syscall calling convention, and rustix seeks to expose the conceptual API, in Rust terms. But with this overflow behavior, it feels like rustix crossed the line. It's not just that we just copy fewer bytes than requested sometimes, which is already part of the API, it's that overflow behavior is different. |
That's a really elegant way of framing rustix' approach to syscall adaptation, hadn't thought of it that way. Thanks for sharing! |
This is an 0.37 breaking change. The lengths are specified as
size_t
s which means everything will break if we ever get 128 bit machines. I think this is trying to emulate the stdlib copy APIs, but they have different requirements: their APIs always copy the full buffer and just return the number of bytes copied as a convenience. I'm pretty sure you can easily overflow the returned length by doing anio::copy
between pipes for example. In rustix land, people need to do the looping themselves. On that note, I believe using a u64 also breaks 32 bit implementations:Using usize also makes this API consistent with splice.