-3

I have this function:

use std::io;

pub fn recv(mut buf: &mut [u8]) -> io::Result<usize> {
    let size_to_extend = 50; // I want to increase the size of "buf" by 50
    unsafe {
        /* ??? */
    }
}

How can I adjust the size of the array buf, even though it's a parameter? It is necessary that this method needs to happen.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Thomas Braun
  • 505
  • 3
  • 14
  • 1
    Looks like a xy-problem, especially [this comment](https://stackoverflow.com/questions/56051611/how-to-unsafely-increase-the-size-of-a-mutable-slice-of-bytes#comment98745257_56051879) – chpio May 09 '19 at 09:30

1 Answers1

2

What you are attempting to do is all-but-guaranteed to cause undefined behavior. Find a better API.


If you want the changes to be reflected outside of the function, you are out of luck. There's no way that this function signature will allow for that to happen, for the same reason that fn foo(x: i32) won't allow you to change the value passed in as observed by the caller.

If you just need this inside of the function, use slice::from_raw_parts. I've marked the entire function as unsafe because certain inputs will cause undefined behavior and this code cannot possibly guard against it:

use std::slice;

pub unsafe fn recv(buf: &mut [u8]) {
    let size_to_extend = 50;

    let ptr = buf.as_mut_ptr();
    let len = buf.len();
    let bad_idea = slice::from_raw_parts_mut(ptr, len + size_to_extend);

    for b in bad_idea.iter_mut() {
        *b = 10;
    }
}

If you can change the API, something like this works to expose the change outside the function:

pub unsafe fn recv(buf: &mut &mut [u8]) {
    let size_to_extend = 50;

    let ptr = buf.as_mut_ptr();
    let len = buf.len();
    let bad_idea = slice::from_raw_parts_mut(ptr, len + size_to_extend);

    for b in bad_idea.iter_mut() {
        *b = 10;
    }

    *buf = bad_idea;
}

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • I checked the size of "buf" before the slice transformation, and I got (say) "x". After the transformation, I still get the length of buf equal to "x"? – Thomas Braun May 09 '19 at 03:54
  • Your comments will certainly help some people, but for me the solution is not optimal for the scenario. I am having to debug somebody else's API... here's a function which is called periodically in order to re-align the network buffer: `code impl AsyncRead for KcpStream { unsafe fn prepare_uninitialized_buffer(&self, mut m: &mut [u8]) -> bool { println!("Prepping unit buffer!"); false } fn read_buf(&mut self, buf: &mut B) -> Poll { <&KcpStream>::read_buf(&mut &*self, buf) } }` – Thomas Braun May 09 '19 at 04:24
  • What's happening is that the buffer goes from ~8000 bytes capacity down to 80, then it wont accept any more data. As such, I need to resize the buffer somehow. I can't seem to find where the buffer is initialized anyways... – Thomas Braun May 09 '19 at 04:26
  • Have you tried to *allocate* a new buffer? Or use for example the [*bytes* crate](https://crates.io/crates/bytes)? – chpio May 09 '19 at 09:33
  • At this point, I think it's impossible to forcibly reset the buffer's length. I've spent the past 35 hours trying it. Oh well, at least I lose points for asking a goddamn question – Thomas Braun May 09 '19 at 19:53
  • @ThomasBraun yes, it's impossible — that's what I meant by *If you want the changes to be reflected outside of the function, you are out of luck*. I agree with this being an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) — you have a problem where some code is passing you a bad value and instead of fixing that code, you are trying to monkey with it it from the other side. It's conceptually the same as if you were getting flat tires from driving over a bed of nails and asking how to patch your tires. – Shepmaster May 09 '19 at 19:58
  • I understand that, and sometimes it works. But, I've spent a while looking for the original declaration of the &mut [u8], and can't find it anywhere. That is why I've been trying to forcibly resize it – Thomas Braun May 09 '19 at 20:27
  • I appreciate you trying to help, and I'm not mad at you. I've spent over 30 hours trying to track and fix the bug in someone else's low-level API, and at this point I'm ready to shoot myself, lol. – Thomas Braun May 09 '19 at 20:28