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

Panic in Connection::read_chunk() buf.set_len(new_len); #167

Open
calltherain opened this issue Mar 27, 2024 · 0 comments
Open

Panic in Connection::read_chunk() buf.set_len(new_len); #167

calltherain opened this issue Mar 27, 2024 · 0 comments

Comments

@calltherain
Copy link

Hi team,

I encountered a strange error at line 165 in Connection::read_chunk()

async fn read_chunk(&mut self, chunk_size: usize, buf: &mut BytesMut) -> Result<()> {
// This is an unsafe variant of doing the following
// but skips the zero-initialization of the buffer
//
// let pos = bytes.len();
// bytes.resize(pos + chunk_size, 0);
// self.stream.read_exact(&mut bytes[pos..]).await?;
let pos = buf.len();
let new_len = pos + chunk_size;
// Ensure the buffer has enough capacity
if buf.capacity() < new_len {
buf.reserve(new_len - buf.capacity());
}
// Unsafe to set the length of the buffer, but we will fill it with read_exact
unsafe {
buf.set_len(new_len);
}
self.stream.read_exact(&mut buf[pos..]).await?;
Ok(())
}
}

The context is like this:

pos = 114662

chunk_size = 16381

new_len = 131043

*buf = (bytes::bytes_mut::BytesMut) {
  ptr = (pointer = "removed for brevity")
  len = 114662
  cap = 131040
  data = 0x0000000000000001
}

capacity  < new_len so execution goes to buf.reserve()
new_len - buf.capacity() = 131043 - 131040 = 3

Here is the implemtation of buf.reserve():

    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        let len = self.len();            //114662
        let rem = self.capacity() - len;    // rem = 131040-114662 = 16378

        // additional = 3,  rem = 16378, so this function returns without allocate additional buffer.
        if additional <= rem {             
            // The handle can already store at least `additional` more bytes, so
            // there is no further work needed to be done.
            return;
        }

        self.reserve_inner(additional);
    }

Because capacity is still 131040, so application panics at line 165, here is the implementation of set_len()

 #[inline]
    pub unsafe fn set_len(&mut self, len: usize) {          
         // len = 131043, cap = 131040, assertion failed
        debug_assert!(len <= self.cap, "set_len out of bounds");
        self.len = len;
    }

Side note: It only panics when the application read a specific row (row 247), the first 246 rows doesn't result panic.

MATCH (n:Label1)
RETURN n {.*, 
    sub: [ (n)-[:R]->(av) | av{.*}] 
}
SKIP 246
LIMIT 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant