Re: [PATCH spice-gtk v2 1/4] Avoid clang warnings on casts with stricter alignment requirements

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

 




On 16 May 2017, at 16:51, Christophe Fergeau <cfergeau@xxxxxxxxxx> wrote:

Hey,

On Thu, May 11, 2017 at 12:47:05PM +0200, Christophe de Dinechin wrote:
From: Christophe de Dinechin <dinechin@xxxxxxxxxx>

For example, something like this:
   uint8_t  *p8;
   uint32_t *p32 = (uint32_t *) p8;

generates a warning like this:
 spice-channel.c:1350:10: error: cast from 'uint8_t *' (aka 'unsigned char *') to
     'uint32_t *' (aka 'unsigned int *') increases required alignment from 1 to
     4 [-Werror,-Wcast-align]

The warning indicates that we end up with a pointer to data that
should be 4-byte aligned, but its value may be misaligned. On x86,
this does not make much of a difference, except a relatively minor
performance penalty. However, on platforms such as ARM, misaligned
accesses are emulated by the kernel, and support for them is optional.
So we may end up with a fault.

The intent of the fix here is to make it easy to identify and rework
places where actual mis-alignment occurs. Wherever casts raise the warning,
they are replaced with a macro:

- SPICE_ALIGNED_CAST(type, value) is the same as (type) value, but
 silences the warning (using an intermediate cast to (void *)) and
 adds a runtime check to verify that the pointer value is actually
 aligned as expected. If that expectation is violated, a warning
 is issued.

- SPICE_UNALIGNED_CAST(type, value) works like SPICE_ALIGNED_CAST,
 but asssumes that the value is not known to be aligned. If there
 is an alignment error, no warning is issued. It is still possible
 to know if misalignment occurs by defining environment variable
 SPICE_DEBUG_ALIGNMENT, in which case a debug message is issued for
 every misaligned pointer.

For some reason, after reading the log, it's still not 100% obvious to
me that SPICE_ALIGNED_CAST means "I checked, the cast which is being
done is legit as the pointer has the right aligment", while
SPICE_UNALIGNED_CAST means "pointer does not have the right alignment,
fixing might need to be done”.

Actually, both are “legit” on x86, except performance-wise.

Do you have a better name suggestion for naming these macros?



Signed-off-by: Christophe de Dinechin <dinechin@xxxxxxxxxx>
---
spice-common                |  2 +-
src/channel-cursor.c        |  6 +++---
src/channel-display-mjpeg.c |  2 +-
src/decode-glz-tmpl.c       |  2 +-
src/spice-channel.c         | 14 +++++++++-----
5 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/spice-common b/spice-common
index af682b1..1239c82 160000
--- a/spice-common
+++ b/spice-common
@@ -1 +1 @@
-Subproject commit af682b1b06dea55007d9aa7c37cd443e4349e43f
+Subproject commit 1239c82c54dee0244cca262cca0aa21071b23e24
diff --git a/src/channel-cursor.c b/src/channel-cursor.c
index 609243b..50de5ce 100644
--- a/src/channel-cursor.c
+++ b/src/channel-cursor.c
@@ -340,7 +340,7 @@ static display_cursor *set_cursor(SpiceChannel *channel, SpiceCursor *scursor)
        memcpy(cursor->data, data, size);
        for (i = 0; i < hdr->width * hdr->height; i++) {
            pix_mask = get_pix_mask(data, size, i);
-            if (pix_mask && *((guint32*)data + i) == 0xffffff) {
+            if (pix_mask && *(SPICE_ALIGNED_CAST(guint32*, data) + i) == 0xffffff) {
                cursor->data[i] = get_pix_hack(i, hdr->width);
            } else {
                cursor->data[i] |= (pix_mask ? 0 : 0xff000000);
@@ -350,7 +350,7 @@ static display_cursor *set_cursor(SpiceChannel *channel, SpiceCursor *scursor)
    case SPICE_CURSOR_TYPE_COLOR16:
        for (i = 0; i < hdr->width * hdr->height; i++) {
            pix_mask = get_pix_mask(data, size, i);
-            pix = *((guint16*)data + i);
+            pix = *(SPICE_ALIGNED_CAST(guint16*,data) + i);
            if (pix_mask && pix == 0x7fff) {
                cursor->data[i] = get_pix_hack(i, hdr->width);
            } else {
@@ -364,7 +364,7 @@ static display_cursor *set_cursor(SpiceChannel *channel, SpiceCursor *scursor)
        for (i = 0; i < hdr->width * hdr->height; i++) {
            pix_mask = get_pix_mask(data, size + (sizeof(uint32_t) << 4), i);
            int idx = (i & 1) ? (data[i >> 1] & 0x0f) : ((data[i >> 1] & 0xf0) >> 4);
-            pix = *((uint32_t*)(data + size) + idx);
+            pix = *(SPICE_UNALIGNED_CAST(uint32_t*,(data + size)) + idx);
            if (pix_mask && pix == 0xffffff) {
                cursor->data[i] = get_pix_hack(i, hdr->width);
            } else {
diff --git a/src/channel-display-mjpeg.c b/src/channel-display-mjpeg.c
index 3ae9d21..17c0f4f 100644
--- a/src/channel-display-mjpeg.c
+++ b/src/channel-display-mjpeg.c
@@ -151,7 +151,7 @@ static gboolean mjpeg_decoder_decode_frame(gpointer video_decoder)
#ifndef JCS_EXTENSIONS
        {
            uint8_t *s = lines[0];
-            uint32_t *d = (uint32_t *)s;
+            uint32_t *d = SPICE_ALIGNED_CAST(uint32_t *,s);

            if (back_compat) {
                for (unsigned int j = lines_read * width; j > 0; ) {
diff --git a/src/decode-glz-tmpl.c b/src/decode-glz-tmpl.c
index b337a8b..7695a28 100644
--- a/src/decode-glz-tmpl.c
+++ b/src/decode-glz-tmpl.c
@@ -178,7 +178,7 @@ static size_t FNAME(decode)(SpiceGlzDecoderWindow *window,
                            uint64_t image_id, SpicePalette *plt)
{
    uint8_t      *ip = in_buf;
-    OUT_PIXEL    *out_pix_buf = (OUT_PIXEL *)out_buf;
+    OUT_PIXEL    *out_pix_buf = SPICE_ALIGNED_CAST(OUT_PIXEL *,out_buf);
    OUT_PIXEL    *op = out_pix_buf;
    OUT_PIXEL    *op_limit = out_pix_buf + size;

diff --git a/src/spice-channel.c b/src/spice-channel.c
index 3b6231e..88d0567 100644
--- a/src/spice-channel.c
+++ b/src/spice-channel.c
@@ -1312,6 +1312,7 @@ static void spice_channel_send_link(SpiceChannel *channel)
{
    SpiceChannelPrivate *c = channel->priv;
    uint8_t *buffer, *p;
+    uint32_t *p32;
    int protocol, i;

    c->link_hdr.magic = SPICE_MAGIC;
@@ -1356,14 +1357,15 @@ static void spice_channel_send_link(SpiceChannel *channel)
    memcpy(p, &c->link_hdr, sizeof(c->link_hdr)); p += sizeof(c->link_hdr);
    memcpy(p, &c->link_msg, sizeof(c->link_msg)); p += sizeof(c->link_msg);

+    // Need this to avoid error with -Wcast-align
+    p32 = SPICE_UNALIGNED_CAST(uint32_t *,p);

I don't think the comment is necessary.
p32 could be named current_cap, caps, or something like this instead

OK. I named it that way because the old pointer was called p.


    for (i = 0; i < c->common_caps->len; i++) {
-        *(uint32_t *)p = GUINT32_TO_LE(g_array_index(c->common_caps, uint32_t, i));
-        p += sizeof(uint32_t);
+        *p32++ = GUINT32_TO_LE(g_array_index(c->common_caps, uint32_t, i));

Assignment followed by increment is more readable imo.

OK. What I really wanted to get rid of was the sizeof(uint32_t).


    }
    for (i = 0; i < c->caps->len; i++) {
-        *(uint32_t *)p = GUINT32_TO_LE(g_array_index(c->caps, uint32_t, i));
-        p += sizeof(uint32_t);
+        *p32++ = GUINT32_TO_LE(g_array_index(c->caps, uint32_t, i));
    }
+    p = (uint8_t *) p32;
    CHANNEL_DEBUG(channel, "channel type %d id %d num common caps %u num caps %u",
                  c->channel_type,
                  c->channel_id,
@@ -1887,6 +1889,7 @@ static gboolean spice_channel_recv_link_msg(SpiceChannel *channel)
    SpiceChannelPrivate *c;
    int rc, num_caps, i;
    uint32_t *caps, num_channel_caps, num_common_caps;
+    uint8_t *caps_src;
    SpiceChannelEvent event = SPICE_CHANNEL_ERROR_LINK;

    g_return_val_if_fail(channel != NULL, FALSE);
@@ -1926,7 +1929,8 @@ static gboolean spice_channel_recv_link_msg(SpiceChannel *channel)
    /* see original spice/client code: */
    /* g_return_if_fail(c->peer_msg + c->peer_msg->caps_offset * sizeof(uint32_t) > c->peer_msg + c->peer_hdr.size); */

-    caps = (uint32_t *)((uint8_t *)c->peer_msg + GUINT32_FROM_LE(c->peer_msg->caps_offset));
+    caps_src = (uint8_t *)c->peer_msg + GUINT32_FROM_LE(c->peer_msg->caps_offset);
+    caps = SPICE_UNALIGNED_CAST(uint32_t *, caps_src);

Nit: Sometimes you use a ", " inside SPICE_*_CAST, sometimes just ",”.

Will fix. I normally prefer with space, that’s also the majority style in spice AFAICT. I will send a new version with your comments. How does it work if ack-ed?


Overall looks fine to me,

Acked-by: Christophe Fergeau <cfergeau@xxxxxxxxxx>

Christophe
_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/spice-devel

_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]