Skip to main content

virtio_queue/
descriptor_utils.rs

1// Portions Copyright 2019 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE-BSD-3-Clause file.
4//
5// Copyright (C) 2024 Red Hat, Inc. All rights reserved.
6//
7// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
8
9use std::collections::VecDeque;
10use std::io::{self, Read, Write};
11use std::mem::{size_of, MaybeUninit};
12use std::ops::Deref;
13use std::ptr::copy_nonoverlapping;
14use std::{cmp, result};
15
16use crate::{DescriptorChain, Error};
17use vm_memory::bitmap::{BitmapSlice, WithBitmapSlice};
18use vm_memory::{ByteValued, GuestMemory, Permissions, VolatileSlice};
19
20pub type Result<T> = result::Result<T, Error>;
21
22#[derive(Clone)]
23struct DescriptorChainConsumer<'a, B> {
24    buffers: VecDeque<VolatileSlice<'a, B>>,
25    bytes_consumed: usize,
26}
27
28impl<'a, B: BitmapSlice> DescriptorChainConsumer<'a, B> {
29    fn available_bytes(&self) -> usize {
30        // This is guaranteed not to overflow because the total length of the chain
31        // is checked during all creations of `DescriptorChainConsumer` (see
32        // `Reader::new()` and `Writer::new()`).
33        self.buffers
34            .iter()
35            .fold(0usize, |count, vs| count + vs.len())
36    }
37
38    fn bytes_consumed(&self) -> usize {
39        self.bytes_consumed
40    }
41
42    /// Consumes at most `count` bytes from the `DescriptorChain`. Callers must provide a function
43    /// that takes a `&[VolatileSlice]` and returns the total number of bytes consumed. This
44    /// function guarantees that the combined length of all the slices in the `&[VolatileSlice]` is
45    /// less than or equal to `count`.
46    ///
47    /// # Errors
48    ///
49    /// If the provided function returns any error then no bytes are consumed from the buffer and
50    /// the error is returned to the caller.
51    fn consume<F>(&mut self, count: usize, f: F) -> io::Result<usize>
52    where
53        F: FnOnce(&[&VolatileSlice<B>]) -> io::Result<usize>,
54    {
55        let mut buflen = 0;
56        let mut bufs = Vec::with_capacity(self.buffers.len());
57        for vs in &self.buffers {
58            if buflen >= count {
59                break;
60            }
61
62            bufs.push(vs);
63
64            let rem = count - buflen;
65            if rem < vs.len() {
66                buflen += rem;
67            } else {
68                buflen += vs.len();
69            }
70        }
71
72        if bufs.is_empty() {
73            return Ok(0);
74        }
75
76        let bytes_consumed = f(&bufs)?;
77
78        // This can happen if a driver tricks a device into reading/writing more data than
79        // fits in a `usize`.
80        let total_bytes_consumed =
81            self.bytes_consumed
82                .checked_add(bytes_consumed)
83                .ok_or_else(|| {
84                    io::Error::new(io::ErrorKind::InvalidData, Error::DescriptorChainOverflow)
85                })?;
86
87        let mut rem = bytes_consumed;
88        while let Some(vs) = self.buffers.pop_front() {
89            if rem < vs.len() {
90                // Split the slice and push the remainder back into the buffer list. Safe because we
91                // know that `rem` is not out of bounds due to the check and we checked the bounds
92                // on `vs` when we added it to the buffer list.
93                self.buffers.push_front(vs.offset(rem).unwrap());
94                break;
95            }
96
97            // No need for checked math because we know that `vs.size() <= rem`.
98            rem -= vs.len();
99        }
100
101        self.bytes_consumed = total_bytes_consumed;
102
103        Ok(bytes_consumed)
104    }
105
106    fn split_at(&mut self, offset: usize) -> Result<DescriptorChainConsumer<'a, B>> {
107        let mut rem = offset;
108        let pos = self.buffers.iter().position(|vs| {
109            if rem < vs.len() {
110                true
111            } else {
112                rem -= vs.len();
113                false
114            }
115        });
116
117        if let Some(at) = pos {
118            let mut other = self.buffers.split_off(at);
119
120            if rem > 0 {
121                // There must be at least one element in `other` because we checked
122                // its `size` value in the call to `position` above.
123                let front = other.pop_front().expect("empty VecDeque after split");
124                self.buffers
125                    .push_back(front.subslice(0, rem).map_err(Error::VolatileMemoryError)?);
126                other.push_front(front.offset(rem).map_err(Error::VolatileMemoryError)?);
127            }
128
129            Ok(DescriptorChainConsumer {
130                buffers: other,
131                bytes_consumed: 0,
132            })
133        } else if rem == 0 {
134            Ok(DescriptorChainConsumer {
135                buffers: VecDeque::new(),
136                bytes_consumed: 0,
137            })
138        } else {
139            Err(Error::SplitOutOfBounds(offset))
140        }
141    }
142}
143
144/// Provides high-level interface over the sequence of memory regions
145/// defined by readable descriptors in the descriptor chain.
146///
147/// Note that virtio spec requires driver to place any device-writable
148/// descriptors after any device-readable descriptors (2.6.4.2 in Virtio Spec v1.1).
149/// Reader will skip iterating over descriptor chain when first writable
150/// descriptor is encountered.
151#[derive(Clone)]
152pub struct Reader<'a, B = ()> {
153    buffer: DescriptorChainConsumer<'a, B>,
154}
155
156impl<'a, B: BitmapSlice> Reader<'a, B> {
157    /// Construct a new Reader wrapper over `desc_chain`.
158    pub fn new<M, T>(mem: &'a M, desc_chain: DescriptorChain<T>) -> Result<Reader<'a, B>>
159    where
160        M: GuestMemory,
161        <M as GuestMemory>::Bitmap: WithBitmapSlice<'a, S = B>,
162        T: Deref,
163        T::Target: GuestMemory + Sized,
164    {
165        let mut total_len: usize = 0;
166        let mut buffers = VecDeque::<VolatileSlice<'a, B>>::new();
167
168        for desc in desc_chain.readable() {
169            // Verify that summing the descriptor sizes does not overflow.
170            // This can happen if a driver tricks a device into reading more data than
171            // fits in a `usize`.
172            total_len = total_len
173                .checked_add(desc.len() as usize)
174                .ok_or(Error::DescriptorChainOverflow)?;
175
176            let slices = mem
177                .get_slices(desc.addr(), desc.len() as usize, Permissions::Read)
178                .map_err(Error::GuestMemoryError)?;
179            for slice in slices {
180                buffers.push_back(slice.map_err(Error::GuestMemoryError)?);
181            }
182        }
183
184        Ok(Reader {
185            buffer: DescriptorChainConsumer {
186                buffers,
187                bytes_consumed: 0,
188            },
189        })
190    }
191
192    /// Reads an object from the descriptor chain buffer.
193    pub fn read_obj<T: ByteValued>(&mut self) -> io::Result<T> {
194        let mut obj = MaybeUninit::<T>::uninit();
195
196        // SAFETY: `MaybeUninit` guarantees that the pointer is valid for
197        // `size_of::<T>()` bytes.
198        let buf = unsafe {
199            ::std::slice::from_raw_parts_mut(obj.as_mut_ptr() as *mut u8, size_of::<T>())
200        };
201
202        self.read_exact(buf)?;
203
204        // SAFETY: any type that implements `ByteValued` can be considered initialized
205        // even if it is filled with random data.
206        Ok(unsafe { obj.assume_init() })
207    }
208
209    /// Returns number of bytes available for reading.  May return an error if the combined
210    /// lengths of all the buffers in the DescriptorChain would cause an integer overflow.
211    pub fn available_bytes(&self) -> usize {
212        self.buffer.available_bytes()
213    }
214
215    /// Returns number of bytes already read from the descriptor chain buffer.
216    pub fn bytes_read(&self) -> usize {
217        self.buffer.bytes_consumed()
218    }
219
220    /// Splits this `Reader` into two at the given offset in the `DescriptorChain` buffer.
221    /// After the split, `self` will be able to read up to `offset` bytes while the returned
222    /// `Reader` can read up to `available_bytes() - offset` bytes.  Returns an error if
223    /// `offset > self.available_bytes()`.
224    pub fn split_at(&mut self, offset: usize) -> Result<Reader<'a, B>> {
225        self.buffer.split_at(offset).map(|buffer| Reader { buffer })
226    }
227}
228
229impl<B: BitmapSlice> io::Read for Reader<'_, B> {
230    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
231        self.buffer.consume(buf.len(), |bufs| {
232            let mut rem = buf;
233            let mut total = 0;
234            for vs in bufs {
235                let copy_len = cmp::min(rem.len(), vs.len());
236
237                // SAFETY: Safe because we verify that we do not read outside
238                // of the slice's bound. The slice guard will only get dropped
239                // after the function returns. This will keep the pointer valid
240                // while reads are happening.
241                unsafe {
242                    copy_nonoverlapping(vs.ptr_guard().as_ptr(), rem.as_mut_ptr(), copy_len);
243                }
244                rem = &mut rem[copy_len..];
245                total += copy_len;
246            }
247            Ok(total)
248        })
249    }
250}
251
252/// Provides high-level interface over the sequence of memory regions
253/// defined by writable descriptors in the descriptor chain.
254///
255/// Note that virtio spec requires driver to place any device-writable
256/// descriptors after any device-readable descriptors (2.6.4.2 in Virtio Spec v1.1).
257/// Writer will start iterating the descriptors from the first writable one and will
258/// assume that all following descriptors are writable.
259#[derive(Clone)]
260pub struct Writer<'a, B = ()> {
261    buffer: DescriptorChainConsumer<'a, B>,
262}
263
264impl<'a, B: BitmapSlice> Writer<'a, B> {
265    /// Construct a new Writer wrapper over `desc_chain`.
266    pub fn new<M, T>(mem: &'a M, desc_chain: DescriptorChain<T>) -> Result<Writer<'a, B>>
267    where
268        M: GuestMemory,
269        <M as GuestMemory>::Bitmap: WithBitmapSlice<'a, S = B>,
270        T: Deref,
271        T::Target: GuestMemory + Sized,
272    {
273        let mut total_len: usize = 0;
274        let mut buffers = VecDeque::<VolatileSlice<'a, B>>::new();
275
276        for desc in desc_chain.writable() {
277            // Verify that summing the descriptor sizes does not overflow.
278            // This can happen if a driver tricks a device into writing more data than
279            // fits in a `usize`.
280            total_len = total_len
281                .checked_add(desc.len() as usize)
282                .ok_or(Error::DescriptorChainOverflow)?;
283
284            let slices = mem
285                .get_slices(desc.addr(), desc.len() as usize, Permissions::Write)
286                .map_err(Error::GuestMemoryError)?;
287            for slice in slices {
288                buffers.push_back(slice.map_err(Error::GuestMemoryError)?);
289            }
290        }
291
292        Ok(Writer {
293            buffer: DescriptorChainConsumer {
294                buffers,
295                bytes_consumed: 0,
296            },
297        })
298    }
299
300    /// Writes an object to the descriptor chain buffer.
301    pub fn write_obj<T: ByteValued>(&mut self, val: T) -> io::Result<()> {
302        self.write_all(val.as_slice())
303    }
304
305    /// Returns number of bytes available for writing.  May return an error if the combined
306    /// lengths of all the buffers in the DescriptorChain would cause an overflow.
307    pub fn available_bytes(&self) -> usize {
308        self.buffer.available_bytes()
309    }
310
311    /// Returns number of bytes already written to the descriptor chain buffer.
312    pub fn bytes_written(&self) -> usize {
313        self.buffer.bytes_consumed()
314    }
315
316    /// Splits this `Writer` into two at the given offset in the `DescriptorChain` buffer.
317    /// After the split, `self` will be able to write up to `offset` bytes while the returned
318    /// `Writer` can write up to `available_bytes() - offset` bytes.  Returns an error if
319    /// `offset > self.available_bytes()`.
320    pub fn split_at(&mut self, offset: usize) -> Result<Writer<'a, B>> {
321        self.buffer.split_at(offset).map(|buffer| Writer { buffer })
322    }
323}
324
325impl<B: BitmapSlice> io::Write for Writer<'_, B> {
326    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
327        self.buffer.consume(buf.len(), |bufs| {
328            let mut rem = buf;
329            let mut total = 0;
330            for vs in bufs {
331                let copy_len = cmp::min(rem.len(), vs.len());
332
333                // SAFETY: Safe because we ensure that we do not write over the
334                // slice's bounds. The slice guard will only get dropped after
335                // the function returns. This will keep the pointer valid while
336                // writes are happening.
337                unsafe {
338                    copy_nonoverlapping(rem.as_ptr(), vs.ptr_guard_mut().as_ptr(), copy_len);
339                }
340                vs.bitmap().mark_dirty(0, copy_len);
341                rem = &rem[copy_len..];
342                total += copy_len;
343            }
344            Ok(total)
345        })
346    }
347
348    fn flush(&mut self) -> io::Result<()> {
349        // Nothing to flush since the writes go straight into the buffer.
350        Ok(())
351    }
352}
353
354#[cfg(test)]
355mod tests {
356    use super::*;
357    use crate::{
358        desc::{split::Descriptor as SplitDescriptor, RawDescriptor},
359        Queue, QueueOwnedT, QueueT,
360    };
361    use vm_memory::{Address, GuestAddress, GuestMemoryMmap, Le32};
362
363    use crate::mock::MockSplitQueue;
364    use virtio_bindings::bindings::virtio_ring::{VRING_DESC_F_NEXT, VRING_DESC_F_WRITE};
365
366    const MAX_QUEUE_SIZE: u16 = 16;
367
368    #[derive(Copy, Clone, PartialEq, Eq)]
369    pub enum DescriptorType {
370        Readable,
371        Writable,
372    }
373
374    /// Test utility function to create a descriptor chain in guest memory.
375    pub fn create_descriptor_chain(
376        memory: &GuestMemoryMmap,
377        descriptor_array_addr: GuestAddress,
378        descriptors: Vec<(DescriptorType, u32)>,
379        spaces_between_regions: u32,
380    ) -> Result<DescriptorChain<&GuestMemoryMmap>> {
381        let descriptors_len = descriptors.len();
382        let mut descs = vec![];
383
384        let queue = MockSplitQueue::create(memory, descriptor_array_addr, MAX_QUEUE_SIZE);
385
386        let mut buffers_start_addr = queue.end();
387
388        for (index, (type_, size)) in descriptors.into_iter().enumerate() {
389            let mut flags = 0;
390            if let DescriptorType::Writable = type_ {
391                flags |= VRING_DESC_F_WRITE;
392            }
393            if index + 1 < descriptors_len {
394                flags |= VRING_DESC_F_NEXT;
395            }
396
397            descs.push(RawDescriptor::from(SplitDescriptor::new(
398                buffers_start_addr.raw_value(),
399                size,
400                flags as u16,
401                (index + 1) as u16,
402            )));
403
404            let offset = size + spaces_between_regions;
405            buffers_start_addr = buffers_start_addr
406                .checked_add(u64::from(offset))
407                .ok_or(Error::InvalidChain)?;
408        }
409
410        queue.build_desc_chain(&descs).unwrap();
411
412        let avail_ring = queue.avail_addr();
413
414        let mut queue: Queue = Queue::new(MAX_QUEUE_SIZE).unwrap();
415        queue
416            .try_set_desc_table_address(descriptor_array_addr)
417            .unwrap();
418        queue.try_set_avail_ring_address(avail_ring).unwrap();
419        queue.set_ready(true);
420
421        let chain = queue.iter(memory).unwrap().next().unwrap();
422
423        Ok(chain.clone())
424    }
425
426    #[test]
427    fn reader_test_inv_desc_addr() {
428        let memory: GuestMemoryMmap =
429            GuestMemoryMmap::from_ranges(&[(GuestAddress(0x0), 0x1000)]).unwrap();
430
431        let queue = MockSplitQueue::create(&memory, GuestAddress(0x0), MAX_QUEUE_SIZE);
432
433        // set addr out of memory
434        let descriptor = RawDescriptor::from(SplitDescriptor::new(0x1001, 1, 0, 1_u16));
435        queue.build_desc_chain(&[descriptor]).unwrap();
436
437        let avail_ring = queue.avail_addr();
438
439        let mut queue: Queue = Queue::new(MAX_QUEUE_SIZE).unwrap();
440        queue.try_set_desc_table_address(GuestAddress(0x0)).unwrap();
441        queue.try_set_avail_ring_address(avail_ring).unwrap();
442        queue.set_ready(true);
443
444        let chain = queue.iter(&memory).unwrap().next().unwrap();
445
446        assert!(Reader::new(&memory, chain).is_err());
447    }
448
449    #[test]
450    fn reader_test_simple_chain() {
451        use DescriptorType::*;
452
453        let memory_start_addr = GuestAddress(0x0);
454        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
455
456        let chain = create_descriptor_chain(
457            &memory,
458            GuestAddress(0x0),
459            vec![
460                (Readable, 8),
461                (Readable, 16),
462                (Readable, 18),
463                (Readable, 64),
464            ],
465            0,
466        )
467        .expect("create_descriptor_chain failed");
468        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
469        assert_eq!(reader.available_bytes(), 106);
470        assert_eq!(reader.bytes_read(), 0);
471
472        let mut buffer = [0_u8; 64];
473        if let Err(e) = reader.read_exact(&mut buffer) {
474            panic!("read_exact should not fail here: {e:?}");
475        }
476
477        assert_eq!(reader.available_bytes(), 42);
478        assert_eq!(reader.bytes_read(), 64);
479
480        match reader.read(&mut buffer) {
481            Err(e) => panic!("read should not fail here: {e:?}"),
482            Ok(length) => assert_eq!(length, 42),
483        }
484
485        assert_eq!(reader.available_bytes(), 0);
486        assert_eq!(reader.bytes_read(), 106);
487    }
488
489    #[test]
490    fn writer_test_simple_chain() {
491        use DescriptorType::*;
492
493        let memory_start_addr = GuestAddress(0x0);
494        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
495
496        let chain = create_descriptor_chain(
497            &memory,
498            GuestAddress(0x0),
499            vec![
500                (Writable, 8),
501                (Writable, 16),
502                (Writable, 18),
503                (Writable, 64),
504            ],
505            0,
506        )
507        .expect("create_descriptor_chain failed");
508        let mut writer = Writer::new(&memory, chain).expect("failed to create Writer");
509        assert_eq!(writer.available_bytes(), 106);
510        assert_eq!(writer.bytes_written(), 0);
511
512        let buffer = [0_u8; 64];
513        if let Err(e) = writer.write_all(&buffer) {
514            panic!("write_all should not fail here: {e:?}");
515        }
516
517        assert_eq!(writer.available_bytes(), 42);
518        assert_eq!(writer.bytes_written(), 64);
519
520        match writer.write(&buffer) {
521            Err(e) => panic!("write should not fail here {e:?}"),
522            Ok(length) => assert_eq!(length, 42),
523        }
524
525        assert_eq!(writer.available_bytes(), 0);
526        assert_eq!(writer.bytes_written(), 106);
527    }
528
529    #[test]
530    fn reader_test_incompatible_chain() {
531        use DescriptorType::*;
532
533        let memory_start_addr = GuestAddress(0x0);
534        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
535
536        let chain = create_descriptor_chain(&memory, GuestAddress(0x0), vec![(Writable, 8)], 0)
537            .expect("create_descriptor_chain failed");
538        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
539        assert_eq!(reader.available_bytes(), 0);
540        assert_eq!(reader.bytes_read(), 0);
541
542        assert!(reader.read_obj::<u8>().is_err());
543
544        assert_eq!(reader.available_bytes(), 0);
545        assert_eq!(reader.bytes_read(), 0);
546    }
547
548    #[test]
549    fn writer_test_incompatible_chain() {
550        use DescriptorType::*;
551
552        let memory_start_addr = GuestAddress(0x0);
553        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
554
555        let chain = create_descriptor_chain(&memory, GuestAddress(0x0), vec![(Readable, 8)], 0)
556            .expect("create_descriptor_chain failed");
557        let mut writer = Writer::new(&memory, chain).expect("failed to create Writer");
558        assert_eq!(writer.available_bytes(), 0);
559        assert_eq!(writer.bytes_written(), 0);
560
561        assert!(writer.write_obj(0u8).is_err());
562
563        assert_eq!(writer.available_bytes(), 0);
564        assert_eq!(writer.bytes_written(), 0);
565    }
566
567    #[test]
568    fn reader_writer_shared_chain() {
569        use DescriptorType::*;
570
571        let memory_start_addr = GuestAddress(0x0);
572        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
573
574        let chain = create_descriptor_chain(
575            &memory,
576            GuestAddress(0x0),
577            vec![
578                (Readable, 16),
579                (Readable, 16),
580                (Readable, 96),
581                (Writable, 64),
582                (Writable, 1),
583                (Writable, 3),
584            ],
585            0,
586        )
587        .expect("create_descriptor_chain failed");
588        let mut reader = Reader::new(&memory, chain.clone()).expect("failed to create Reader");
589        let mut writer = Writer::new(&memory, chain).expect("failed to create Writer");
590
591        assert_eq!(reader.bytes_read(), 0);
592        assert_eq!(writer.bytes_written(), 0);
593
594        let mut buffer = Vec::with_capacity(200);
595
596        assert_eq!(
597            reader
598                .read_to_end(&mut buffer)
599                .expect("read should not fail here"),
600            128
601        );
602
603        // The writable descriptors are only 68 bytes long.
604        writer
605            .write_all(&buffer[..68])
606            .expect("write should not fail here");
607
608        assert_eq!(reader.available_bytes(), 0);
609        assert_eq!(reader.bytes_read(), 128);
610        assert_eq!(writer.available_bytes(), 0);
611        assert_eq!(writer.bytes_written(), 68);
612    }
613
614    #[test]
615    fn reader_writer_shattered_object() {
616        use DescriptorType::*;
617
618        let memory_start_addr = GuestAddress(0x0);
619        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
620
621        let secret: Le32 = 0x1234_5678.into();
622
623        // Create a descriptor chain with memory regions that are properly separated.
624        let chain_writer = create_descriptor_chain(
625            &memory,
626            GuestAddress(0x0),
627            vec![(Writable, 1), (Writable, 1), (Writable, 1), (Writable, 1)],
628            123,
629        )
630        .expect("create_descriptor_chain failed");
631        let mut writer = Writer::new(&memory, chain_writer).expect("failed to create Writer");
632        if let Err(e) = writer.write_obj(secret) {
633            panic!("write_obj should not fail here: {e:?}");
634        }
635
636        // Now create new descriptor chain pointing to the same memory and try to read it.
637        let chain_reader = create_descriptor_chain(
638            &memory,
639            GuestAddress(0x0),
640            vec![(Readable, 1), (Readable, 1), (Readable, 1), (Readable, 1)],
641            123,
642        )
643        .expect("create_descriptor_chain failed");
644        let mut reader = Reader::new(&memory, chain_reader).expect("failed to create Reader");
645        match reader.read_obj::<Le32>() {
646            Err(e) => panic!("read_obj should not fail here: {e:?}"),
647            Ok(read_secret) => assert_eq!(read_secret, secret),
648        }
649    }
650
651    #[test]
652    fn reader_unexpected_eof() {
653        use DescriptorType::*;
654
655        let memory_start_addr = GuestAddress(0x0);
656        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
657
658        let chain = create_descriptor_chain(
659            &memory,
660            GuestAddress(0x0),
661            vec![(Readable, 256), (Readable, 256)],
662            0,
663        )
664        .expect("create_descriptor_chain failed");
665
666        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
667
668        let mut buf = vec![0; 1024];
669
670        assert_eq!(
671            reader
672                .read_exact(&mut buf[..])
673                .expect_err("read more bytes than available")
674                .kind(),
675            io::ErrorKind::UnexpectedEof
676        );
677    }
678
679    #[test]
680    fn split_border() {
681        use DescriptorType::*;
682
683        let memory_start_addr = GuestAddress(0x0);
684        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
685
686        let chain = create_descriptor_chain(
687            &memory,
688            GuestAddress(0x0),
689            vec![
690                (Readable, 16),
691                (Readable, 16),
692                (Readable, 96),
693                (Writable, 64),
694                (Writable, 1),
695                (Writable, 3),
696            ],
697            0,
698        )
699        .expect("create_descriptor_chain failed");
700        let mut reader = Reader::new(&memory, chain.clone()).expect("failed to create Reader");
701
702        let other = reader.split_at(32).expect("failed to split Reader");
703        assert_eq!(reader.available_bytes(), 32);
704        assert_eq!(other.available_bytes(), 96);
705
706        let mut writer = Writer::new(&memory, chain.clone()).expect("failed to create Writer");
707        let other = writer.split_at(64).expect("failed to split Writer");
708        assert_eq!(writer.available_bytes(), 64);
709        assert_eq!(other.available_bytes(), 4);
710    }
711
712    #[test]
713    fn split_middle() {
714        use DescriptorType::*;
715
716        let memory_start_addr = GuestAddress(0x0);
717        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
718
719        let chain = create_descriptor_chain(
720            &memory,
721            GuestAddress(0x0),
722            vec![
723                (Readable, 16),
724                (Readable, 16),
725                (Readable, 96),
726                (Writable, 64),
727                (Writable, 1),
728                (Writable, 3),
729            ],
730            0,
731        )
732        .expect("create_descriptor_chain failed");
733        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
734
735        let other = reader.split_at(24).expect("failed to split Reader");
736        assert_eq!(reader.available_bytes(), 24);
737        assert_eq!(other.available_bytes(), 104);
738    }
739
740    #[test]
741    fn split_end() {
742        use DescriptorType::*;
743
744        let memory_start_addr = GuestAddress(0x0);
745        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
746
747        let chain = create_descriptor_chain(
748            &memory,
749            GuestAddress(0x0),
750            vec![
751                (Readable, 16),
752                (Readable, 16),
753                (Readable, 96),
754                (Writable, 64),
755                (Writable, 1),
756                (Writable, 3),
757            ],
758            0,
759        )
760        .expect("create_descriptor_chain failed");
761        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
762
763        let other = reader.split_at(128).expect("failed to split Reader");
764        assert_eq!(reader.available_bytes(), 128);
765        assert_eq!(other.available_bytes(), 0);
766    }
767
768    #[test]
769    fn split_beginning() {
770        use DescriptorType::*;
771
772        let memory_start_addr = GuestAddress(0x0);
773        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
774
775        let chain = create_descriptor_chain(
776            &memory,
777            GuestAddress(0x0),
778            vec![
779                (Readable, 16),
780                (Readable, 16),
781                (Readable, 96),
782                (Writable, 64),
783                (Writable, 1),
784                (Writable, 3),
785            ],
786            0,
787        )
788        .expect("create_descriptor_chain failed");
789        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
790
791        let other = reader.split_at(0).expect("failed to split Reader");
792        assert_eq!(reader.available_bytes(), 0);
793        assert_eq!(other.available_bytes(), 128);
794    }
795
796    #[test]
797    fn split_outofbounds() {
798        use DescriptorType::*;
799
800        let memory_start_addr = GuestAddress(0x0);
801        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
802
803        let chain = create_descriptor_chain(
804            &memory,
805            GuestAddress(0x0),
806            vec![
807                (Readable, 16),
808                (Readable, 16),
809                (Readable, 96),
810                (Writable, 64),
811                (Writable, 1),
812                (Writable, 3),
813            ],
814            0,
815        )
816        .expect("create_descriptor_chain failed");
817        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
818
819        if reader.split_at(256).is_ok() {
820            panic!("successfully split Reader with out of bounds offset");
821        }
822    }
823
824    #[test]
825    fn read_full() {
826        use DescriptorType::*;
827
828        let memory_start_addr = GuestAddress(0x0);
829        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
830
831        let chain = create_descriptor_chain(
832            &memory,
833            GuestAddress(0x0),
834            vec![(Readable, 16), (Readable, 16), (Readable, 16)],
835            0,
836        )
837        .expect("create_descriptor_chain failed");
838        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
839
840        let mut buf = [0u8; 64];
841        assert_eq!(
842            reader.read(&mut buf[..]).expect("failed to read to buffer"),
843            48
844        );
845    }
846
847    #[test]
848    fn write_full() {
849        use DescriptorType::*;
850
851        let memory_start_addr = GuestAddress(0x0);
852        let memory = GuestMemoryMmap::from_ranges(&[(memory_start_addr, 0x10000)]).unwrap();
853
854        let chain = create_descriptor_chain(
855            &memory,
856            GuestAddress(0x0),
857            vec![(Writable, 16), (Writable, 16), (Writable, 16)],
858            0,
859        )
860        .expect("create_descriptor_chain failed");
861        let mut writer = Writer::new(&memory, chain).expect("failed to create Writer");
862
863        let buf = [0xdeu8; 64];
864        assert_eq!(
865            writer.write(&buf[..]).expect("failed to write from buffer"),
866            48
867        );
868
869        assert!(writer.flush().is_ok());
870    }
871}