Add safe cstring rules#250
Conversation
|
@nunoplopes do you think it's better to implement most of the cstring functions as part of |
|
|
||
| fn f4(a0: AnyPtr, a1: AnyPtr, a2: usize) -> AnyPtr { | ||
| a0.memcpy(&a1, a2 as usize); | ||
| let __tmp: Vec<u8> = (0..a2) |
There was a problem hiding this comment.
why can't we use memcpy here?
There was a problem hiding this comment.
f4 is memmove. memmove allows overlap between src and dst, memcpy does not (it's UB). Maybe it would be a good idea to add an assert inside Ptr::memcpy to panic on overlapping regions.
There was a problem hiding this comment.
But our implementation of memcpy is ok with overlaps. There's no point in reinventing the wheel.
There was a problem hiding this comment.
It's not ok if dst > src. For the following code:
#include <string.h>
int main(void) {
char buf[6] = {1, 2, 3, 4, 5, 6};
memmove(buf + 2, buf, 4);
for (int i = 0; i < 6; i++) {
printf("%d ", buf[i]);
}
printf("\n");
return 0;
}The output is:
C: 1 2 1 2 3 4 (correct, it's a shift right)
memmove translated as Ptr::memcpy: 1 2 1 2 1 2 (wrong)
There was a problem hiding this comment.
I think an assert on overlapping Ptr::memcpy would be useful. Memcpy with overlapping memory is UB in C
There was a problem hiding this comment.
I know it's UB in C. But our safe Rust implementation can handle overlapping memory. So let's use it.
There was a problem hiding this comment.
In this case I will change the implementation of Ptr::memcpy to fully behave as memmove
| } | ||
| } | ||
|
|
||
| unsafe fn f7(a0: Ptr<u8>) -> usize { |
| let mut __p2 = a1.clone(); | ||
| let mut __i: usize = 0; | ||
| loop { | ||
| if __i == a2 { |
There was a problem hiding this comment.
you can decrement a2; there's no need for __i
There was a problem hiding this comment.
It makes no difference, a2 is textually replaced inside the rule. We cannot decrement a2 until it reaches 0, we need to save it in a variable eitherway
| let mut __p = a0.reinterpret_cast::<u8>(); | ||
| let mut __i: usize = 0; | ||
| loop { | ||
| if __i == a2 { |
There was a problem hiding this comment.
same here; can be decremented
There was a problem hiding this comment.
It makes no difference, a2 is textually replaced inside the rule. We cannot decrement a2 until it reaches 0, we need to save it in a variable eitherway
| break __i; | ||
| } | ||
| let mut __q = a1.clone(); | ||
| let __hit = loop { |
There was a problem hiding this comment.
I would rather read a1 into a local vector. seems easier to optimize.
There was a problem hiding this comment.
No longer relevant. I replaced the __hit = loop idiom with CStringIterator
|
|
||
| fn f18(a0: Ptr<u8>, a1: Ptr<u8>) -> Ptr<u8> { | ||
| let mut __p = a0.clone(); | ||
| loop { |
There was a problem hiding this comment.
this code should be using CStringIterator instead. becomes a lot smaller.
There was a problem hiding this comment.
Done. Also used CStringIterator in other rules
No description provided.