[librsvg: 12/14] Add helper function to avoid of trivial pointer casts that only appear on aarch64




commit 8a225a3c5a4f2c89746d6d6d6cc83465da80ff87
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon Sep 26 17:29:54 2022 -0500

    Add helper function to avoid of trivial pointer casts that only appear on aarch64
    
    On aarch64, libc::c_char is unsigned, so this produces a trivial cast
    to u8:
    
       let my_slice: &[u8] = std::slice::from_raw_parts(p as *const u8, len);
    
    On Intel, libc::c_char is signed, and produces no such warning.
    
    I couldn't find a way to do this without waerning; "*const _" fails;
    plain "_" fails.
    
    Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/754>

 src/util.rs           | 20 ++++++++++++++++++++
 src/xml/attributes.rs |  4 ++--
 src/xml/xml2_load.rs  |  6 +++---
 3 files changed, 25 insertions(+), 5 deletions(-)
---
diff --git a/src/util.rs b/src/util.rs
index e308359a1..1375b8603 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -2,6 +2,7 @@
 
 use std::borrow::Cow;
 use std::ffi::CStr;
+use std::mem::transmute;
 use std::str;
 
 /// Converts a `char *` which is known to be valid UTF-8 into a `&str`
@@ -32,6 +33,25 @@ pub unsafe fn cstr<'a>(s: *const libc::c_char) -> Cow<'a, str> {
     CStr::from_ptr(s).to_string_lossy()
 }
 
+/// Casts a pointer to `c_char` to a pointer to `u8`.
+///
+/// The obvious `p as *const u8` or `p as *const _` produces a
+/// trivial_casts warning when compiled on aarch64, where `c_char` is
+/// unsigned (on Intel, it is signed, so the cast works).
+///
+/// We do this here with a `transmute`, which is awkward to type,
+/// so wrap it in a function.
+pub unsafe fn c_char_as_u8_ptr(p: *const libc::c_char) -> *const u8 {
+    transmute::<_, *const u8>(p)
+}
+
+/// Casts a pointer to `c_char` to a pointer to mutable `u8`.
+///
+/// See [`c_char_as_u8_ptr`] for the reason for this.
+pub unsafe fn c_char_as_u8_ptr_mut(p: *mut libc::c_char) -> *mut u8 {
+    transmute::<_, *mut u8>(p)
+}
+
 pub fn clamp<T: PartialOrd>(val: T, low: T, high: T) -> T {
     if val < low {
         low
diff --git a/src/xml/attributes.rs b/src/xml/attributes.rs
index 9c8ebe96b..844066cd0 100644
--- a/src/xml/attributes.rs
+++ b/src/xml/attributes.rs
@@ -10,7 +10,7 @@ use string_cache::DefaultAtom;
 
 use crate::error::{ImplementationLimit, LoadingError};
 use crate::limits;
-use crate::util::{opt_utf8_cstr, utf8_cstr};
+use crate::util::{c_char_as_u8_ptr, opt_utf8_cstr, utf8_cstr};
 
 /// Type used to store attribute values.
 ///
@@ -103,7 +103,7 @@ impl Attributes {
                     let end = value_end as usize;
                     let len = end - start;
 
-                    let value_slice = slice::from_raw_parts(value_start as *const u8, len);
+                    let value_slice = slice::from_raw_parts(c_char_as_u8_ptr(value_start), len);
                     let value_str = str::from_utf8_unchecked(value_slice);
                     let value_atom = DefaultAtom::from(value_str);
 
diff --git a/src/xml/xml2_load.rs b/src/xml/xml2_load.rs
index c916c4f78..9dcdac4e8 100644
--- a/src/xml/xml2_load.rs
+++ b/src/xml/xml2_load.rs
@@ -16,7 +16,7 @@ use glib::translate::*;
 use markup5ever::{namespace_url, ns, LocalName, Namespace, Prefix, QualName};
 
 use crate::error::LoadingError;
-use crate::util::{cstr, opt_utf8_cstr, utf8_cstr};
+use crate::util::{c_char_as_u8_ptr, c_char_as_u8_ptr_mut, cstr, opt_utf8_cstr, utf8_cstr};
 
 use super::xml2::*;
 use super::Attributes;
@@ -267,7 +267,7 @@ unsafe extern "C" fn sax_characters_cb(
 
     // libxml2 already validated the incoming string as UTF-8.  Note that
     // it is *not* nul-terminated; this is why we create a byte slice first.
-    let bytes = std::slice::from_raw_parts(unterminated_text as *const u8, len as usize);
+    let bytes = std::slice::from_raw_parts(c_char_as_u8_ptr(unterminated_text), len as usize);
     let utf8 = str::from_utf8_unchecked(bytes);
 
     xml2_parser.state.characters(utf8);
@@ -347,7 +347,7 @@ unsafe extern "C" fn stream_ctx_read(
         return -1;
     }
 
-    let buf: &mut [u8] = slice::from_raw_parts_mut(buffer as *mut u8, len as usize);
+    let buf: &mut [u8] = slice::from_raw_parts_mut(c_char_as_u8_ptr_mut(buffer), len as usize);
 
     match ctx.stream.read(buf, ctx.cancellable.as_ref()) {
         Ok(size) => size as libc::c_int,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]