rust-x-bindings / rust-xcb

Rust bindings and wrapper for XCB.
MIT License
161 stars 63 forks source link

Add truncation to WireOut::serialize #226

Closed ogerlach closed 1 year ago

ogerlach commented 1 year ago

When creating a new PictformInfo() I received the following error:

thread 'test::test_pictforminfo' panicked at 'source slice length (16) does not match destination slice length (20)', /home/oliver/Dokumente/dev/reMenu/target/debug/build/xcb-22e5b0ca74ae1e36/out/render.rs:639:18

This snippet can trigger the error:

        let pfi = render::Pictforminfo::new(
            render::Pictformat::none(),
            render::PictType::Direct,
            32,
            render::Directformat {
                red_shift: 16,
                red_mask: 0xFF,
                green_shift: 8,
                green_mask: 0xFF,
                blue_shift: 0,
                blue_mask: 0xFF,
                alpha_shift: 24,
                alpha_mask: 0xFF,
            },
            x::Colormap::none(),
        );

After some testing, I found that WireOut::serialize does not truncate data passed to it but consumes the whole chunk. From the documentation and its use in the code base, I concluded that this is not the intended behaviour. In case my conclusion was right, this PR fixes it.

As requested, here is the diff of the generated code:

diff --color -ur gen/previous/present.rs gen/current/present.rs
--- gen/previous/present.rs 2023-04-25 07:45:28.412228643 +0200
+++ gen/current/present.rs  2023-04-25 07:48:48.098977451 +0200
@@ -1258,7 +1258,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Notify as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
diff --color -ur gen/previous/randr.rs gen/current/randr.rs
--- gen/previous/randr.rs   2023-04-25 07:45:28.555562514 +0200
+++ gen/current/randr.rs    2023-04-25 07:48:48.242310555 +0200
@@ -982,7 +982,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const ScreenSize as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -1255,7 +1255,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const ModeInfo as _, 32) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         32
     }
 }
diff --color -ur gen/previous/record.rs gen/current/record.rs
--- gen/previous/record.rs  2023-04-25 07:45:28.628896123 +0200
+++ gen/current/record.rs   2023-04-25 07:48:48.318977099 +0200
@@ -210,7 +210,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Range8 as _, 2) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         2
     }
 }
@@ -245,7 +245,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Range16 as _, 4) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         4
     }
 }
@@ -280,7 +280,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const ExtRange as _, 6) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         6
     }
 }
diff --color -ur gen/previous/render.rs gen/current/render.rs
--- gen/previous/render.rs  2023-04-25 07:45:28.735563190 +0200
+++ gen/current/render.rs   2023-04-25 07:48:48.425643596 +0200
@@ -694,7 +694,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Directformat as _, 16) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         16
     }
 }
@@ -856,7 +856,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Pictvisual as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -1311,7 +1311,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Indexvalue as _, 12) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         12
     }
 }
@@ -1348,7 +1348,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Color as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -1383,7 +1383,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Pointfix as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -1418,7 +1418,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Linefix as _, 16) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         16
     }
 }
@@ -1454,7 +1454,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Triangle as _, 24) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         24
     }
 }
@@ -1491,7 +1491,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Trapezoid as _, 40) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         40
     }
 }
@@ -1530,7 +1530,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Glyphinfo as _, 12) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         12
     }
 }
@@ -1572,7 +1572,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Transform as _, 36) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         36
     }
 }
@@ -1607,7 +1607,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Animcursorelt as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -1643,7 +1643,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Spanfix as _, 12) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         12
     }
 }
@@ -1678,7 +1678,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Trap as _, 24) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         24
     }
 }
diff --color -ur gen/previous/res.rs gen/current/res.rs
--- gen/previous/res.rs 2023-04-25 07:45:28.808896799 +0200
+++ gen/current/res.rs  2023-04-25 07:48:48.498976812 +0200
@@ -79,7 +79,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Client as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -114,7 +114,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Type as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -156,7 +156,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const ClientIdSpec as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -391,7 +391,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const ResourceIdSpec as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -428,7 +428,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const ResourceSizeSpec as _, 20) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         20
     }
 }
diff --color -ur gen/previous/sync.rs gen/current/sync.rs
--- gen/previous/sync.rs    2023-04-25 07:45:29.105564573 +0200
+++ gen/current/sync.rs 2023-04-25 07:48:48.785643020 +0200
@@ -818,7 +818,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Int64 as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
diff --color -ur gen/previous/xf86dri.rs gen/current/xf86dri.rs
--- gen/previous/xf86dri.rs 2023-04-25 07:45:29.312232005 +0200
+++ gen/current/xf86dri.rs  2023-04-25 07:48:48.985642701 +0200
@@ -81,7 +81,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const DrmClipRect as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
diff --color -ur gen/previous/xinerama.rs gen/current/xinerama.rs
--- gen/previous/xinerama.rs    2023-04-25 07:45:29.565566276 +0200
+++ gen/current/xinerama.rs 2023-04-25 07:48:49.235642299 +0200
@@ -81,7 +81,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const ScreenInfo as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
diff --color -ur gen/previous/xinput.rs gen/current/xinput.rs
--- gen/previous/xinput.rs  2023-04-25 07:45:29.852234004 +0200
+++ gen/current/xinput.rs   2023-04-25 07:48:49.528975160 +0200
@@ -5290,7 +5290,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Fp3232 as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -5697,7 +5697,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const AxisInfo as _, 12) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         12
     }
 }
@@ -13598,7 +13598,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const GroupInfo as _, 4) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         4
     }
 }
@@ -13635,7 +13635,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const ModifierInfo as _, 16) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         16
     }
 }
diff --color -ur gen/previous/xkb.rs gen/current/xkb.rs
--- gen/previous/xkb.rs 2023-04-25 07:45:30.098901579 +0200
+++ gen/current/xkb.rs  2023-04-25 07:48:49.778974758 +0200
@@ -3800,7 +3800,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const KeyName as _, 4) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         4
     }
 }
@@ -3835,7 +3835,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const KeyAlias as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -6035,7 +6035,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Key as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -6070,7 +6070,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const OverlayKey as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
diff --color -ur gen/previous/xproto.rs gen/current/xproto.rs
--- gen/previous/xproto.rs  2023-04-25 07:45:30.485569656 +0200
+++ gen/current/xproto.rs   2023-04-25 07:48:50.158974145 +0200
@@ -5301,7 +5301,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Char2b as _, 2) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         2
     }
 }
@@ -5651,7 +5651,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Point as _, 4) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         4
     }
 }
@@ -5688,7 +5688,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Rectangle as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -5727,7 +5727,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Arc as _, 12) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         12
     }
 }
@@ -8531,7 +8531,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Timecoord as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -8601,7 +8601,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Fontprop as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
@@ -8640,7 +8640,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Charinfo as _, 12) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         12
     }
 }
@@ -9081,7 +9081,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Segment as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
diff --color -ur gen/previous/xvmc.rs gen/current/xvmc.rs
--- gen/previous/xvmc.rs    2023-04-25 07:45:30.718903841 +0200
+++ gen/current/xvmc.rs 2023-04-25 07:48:50.402307083 +0200
@@ -166,7 +166,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const SurfaceInfo as _, 24) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         24
     }
 }
diff --color -ur gen/previous/xv.rs gen/current/xv.rs
--- gen/previous/xv.rs  2023-04-25 07:45:30.812237515 +0200
+++ gen/current/xv.rs   2023-04-25 07:48:50.505640250 +0200
@@ -789,7 +789,7 @@

     fn serialize(&self, wire_buf: &mut [u8]) -> usize {
         let me = unsafe { std::slice::from_raw_parts(self as *const Rational as _, 8) };
-        wire_buf.copy_from_slice(me);
+        (&mut wire_buf[..me.len()]).copy_from_slice(me);
         8
     }
 }
rtbo commented 1 year ago

Hi,

Your fix is correct. What I don't understand is why this panic didn't show up before!

FYI, here is an example of (generated) code using serialize. wire_buf is offset by the value returned by the previous serialize.

    /// Construct a new [Pictforminfo].
    #[allow(unused_assignments, unused_unsafe)]
    pub fn new(
        id: Pictformat,
        r#type: PictType,
        depth: u8,
        direct: Directformat,
        colormap: xproto::Colormap,
    ) -> Pictforminfo {
        unsafe {
            let mut wire_buf = [0u8; 28];
            let mut wire_off = 0usize;

            wire_off += id.serialize(&mut wire_buf[wire_off..]);
            wire_off +=
                (std::mem::transmute::<_, u32>(r#type) as u8).serialize(&mut wire_buf[wire_off..]);
            wire_off += depth.serialize(&mut wire_buf[wire_off..]);
            wire_off += 2; // pad
            wire_off += direct.serialize(&mut wire_buf[wire_off..]);
            wire_off += colormap.serialize(&mut wire_buf[wire_off..]);

            Pictforminfo { data: wire_buf }
        }
    }
ogerlach commented 1 year ago

I was wondering about the same thing. It initially caused me to believe that I am wrong about the bug. Luckily the comment clearly stated the intended behavior. The last days I looked deeper into the issue. I am not fully sure (would.need more investigation) but I think that overall it comes down to this: Most types (e.g. primitive types) are not affected as they have another implementation of WiredOut. It is only structs inside structs. As one can see from the diff, the change affects quite some types but not this many central ones. And even for these types, the slices would be of same length if a struct to be serialized is the last type to be serialized. In this case, there would be no panic as well.

So I see a possible explanation why this problem is not as pervasive as looks at first glance. However, this strongly depends what features are actually used by users of this crate. I cannot say much about other extentions but for render there is a problem when working with pictures. The core protocol can be used without trouble. So if most users are fine with not affected features of core and some extensions, the error would not manifest. This is quite likely imho.

Keep in mind that this mostly guesswork and not a throughout investigation. But it is enough for me at this point.