Repository: plotters-rs/plotters (language: rust)

Issue:
[BUG] Panic in unsafe `fill_rect_fast`
**Describe the bug**

When using Rust nightly compiler, attempting to draw a line is likely to cause a panic (depending on color / line coordinates):

```
thread 'main' panicked at 'misaligned pointer dereference: address must be a multiple of 0x8 but is 0x1ab590c7fd3', [redacted]\plotters-bitmap-0.3.2\src\bitmap_pixel\rgb.rs:215:29
```

The offending line is: https://github.com/plotters-rs/plotters/blob/acf5158c6f49b8bfe8a5431c64b0867a1a8b36d1/plotters-bitmap/src/bitmap_pixel/rgb.rs#L215

I believe the relevant Nightly change is https://github.com/rust-lang/rust/pull/98112, but this seems to be a plotters bug and not a rustc regression (from my limited understanding).

**To Reproduce**

```rust
use plotters::prelude::*;

fn main() {
    let mut backend = BitMapBackend::new("test.png", (256, 256));
    backend.draw_line((1, 0), (100, 0), &RED).unwrap();
}
```
Sample project: https://github.com/agersant/plotter-panic

**Version Information**
Plotters `0.3.4`



Discussion / hints:
That code does seem very broken:
* The transmute call is wrong, because `(u64, u64, u64)` does not have any layout guarantees.
* `ptr` comes from `*mut [u8; 24]`, which doesn't have the correct alignment for u64.
I'm hitting this as well, but only when plotting a line series with a certain number of data points... i.e. purely _adding_ more points to the same exact line "fixes" the issue.
I'm getting this as well, most of the examples I tried in the docs fail when using bitmap backend. I tried this example in a sample project and always got a panic, no issues when switching to SVG backend. Only fails on nightly (I'm using `nightly-x86_64-unknown-linux-gnu` ), stable works fine.
```rust
use plotters::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut backend = BitMapBackend::new("1.png", (300, 200));
    backend.draw_rect((50, 50), (200, 150), &RED, true)?;
    backend.present()?;
    Ok(())
}
```
I also trigger this issue when trying to use plotters with slint with nightly toolchain. Anyway this code is broken, because you should use write_unaligned.

Fix patch:
diff --git a/plotters-bitmap/src/bitmap_pixel/bgrx.rs b/plotters-bitmap/src/bitmap_pixel/bgrx.rs
index 16bcd25e..2f90d9d5 100644
--- a/plotters-bitmap/src/bitmap_pixel/bgrx.rs
+++ b/plotters-bitmap/src/bitmap_pixel/bgrx.rs
@@ -87,7 +87,7 @@ impl PixelFormat for BGRXPixel {
             let slice = unsafe { std::slice::from_raw_parts_mut(start_ptr, (count - 1) / 2) };
             for rp in slice.iter_mut() {
                 let ptr = rp as *mut [u8; 8] as *mut u64;
-                let d1 = unsafe { *ptr };
+                let d1 = unsafe { ptr.read_unaligned() };
                 let mut h = (d1 >> 8) & M;
                 let mut l = d1 & M;
 
@@ -104,7 +104,7 @@ impl PixelFormat for BGRXPixel {
                 }
 
                 unsafe {
-                    *ptr = h | l;
+                    ptr.write_unaligned(h | l);
                 }
             }
 
@@ -196,7 +196,7 @@ impl PixelFormat for BGRXPixel {
                             let d: u64 = std::mem::transmute([
                                 b, g, r, 0, b, g, r, 0, // QW1
                             ]);
-                            *ptr = d;
+                            ptr.write_unaligned(d);
                         }
                     }
 
diff --git a/plotters-bitmap/src/bitmap_pixel/rgb.rs b/plotters-bitmap/src/bitmap_pixel/rgb.rs
index e8b88216..39b3f502 100644
--- a/plotters-bitmap/src/bitmap_pixel/rgb.rs
+++ b/plotters-bitmap/src/bitmap_pixel/rgb.rs
@@ -67,7 +67,7 @@ impl PixelFormat for RGBPixel {
         // Since we should always make sure the RGB payload occupies the logic lower bits
         // thus, this type purning should work for both LE and BE CPUs
         #[rustfmt::skip]
-        let (p1, p2, p3): (u64, u64, u64) = unsafe {
+        let [p1, p2, p3]: [u64; 3] = unsafe {
             std::mem::transmute([
                 u16::from(r), u16::from(b), u16::from(g), u16::from(r), // QW1
                 u16::from(b), u16::from(g), u16::from(r), u16::from(b), // QW2
@@ -76,7 +76,7 @@ impl PixelFormat for RGBPixel {
         };
 
         #[rustfmt::skip]
-        let (q1, q2, q3): (u64, u64, u64) = unsafe {
+        let [q1, q2, q3]: [u64; 3] = unsafe {
             std::mem::transmute([
                 u16::from(g), u16::from(r), u16::from(b), u16::from(g), // QW1
                 u16::from(r), u16::from(b), u16::from(g), u16::from(r), // QW2
@@ -94,8 +94,8 @@ impl PixelFormat for RGBPixel {
             let start_ptr = &mut dst[start * Self::PIXEL_SIZE] as *mut u8 as *mut [u8; 24];
             let slice = unsafe { std::slice::from_raw_parts_mut(start_ptr, (count - 1) / 8) };
             for p in slice.iter_mut() {
-                let ptr = p as *mut [u8; 24] as *mut (u64, u64, u64);
-                let (d1, d2, d3) = unsafe { *ptr };
+                let ptr = p as *mut [u8; 24] as *mut [u64; 3];
+                let [d1, d2, d3] = unsafe { ptr.read_unaligned() };
                 let (mut h1, mut h2, mut h3) = ((d1 >> 8) & M, (d2 >> 8) & M, (d3 >> 8) & M);
                 let (mut l1, mut l2, mut l3) = (d1 & M, d2 & M, d3 & M);
 
@@ -120,7 +120,7 @@ impl PixelFormat for RGBPixel {
                 }
 
                 unsafe {
-                    *ptr = (h1 | l1, h2 | l2, h3 | l3);
+                    ptr.write_unaligned([h1 | l1, h2 | l2, h3 | l3]);
                 }
             }
 
@@ -207,14 +207,14 @@ impl PixelFormat for RGBPixel {
                         // TODO: Consider using AVX instructions when possible
                         let ptr = p as *mut [u8; 24] as *mut u64;
                         unsafe {
-                            let (d1, d2, d3): (u64, u64, u64) = std::mem::transmute([
+                            let [d1, d2, d3]: [u64; 3] = std::mem::transmute([
                                 r, g, b, r, g, b, r, g, // QW1
                                 b, r, g, b, r, g, b, r, // QW2
                                 g, b, r, g, b, r, g, b, // QW3
                             ]);
-                            *ptr = d1;
-                            *ptr.offset(1) = d2;
-                            *ptr.offset(2) = d3;
+                            ptr.write_unaligned(d1);
+                            ptr.offset(1).write_unaligned(d2);
+                            ptr.offset(2).write_unaligned(d3);
                         }
                     }
 


Test patch: