[cairo] fix alignment issue on SPARC processors

Nicolas Setton setton at adacore.com
Thu Dec 4 11:44:48 PST 2014


Hello Uli,

thank you for the feedback.

>> There is an alignment issue on SPARC processors which causes a SIGBUS when
>> trying to write data to edges in the polygon scan converter.
> 
> Could you provide some more information about this? I guess you are on 32bit
> SPARC since otherwise all members of struct _pool_chunk already be 64bit in size.

Right, this is 32bit SPARC (Solaris 10).

> So size_t is a 32 bit type for you and the prev_chunk member thus starts aligned
> to a 64 bit boundary for you. Since it is a 32 bit pointer, the end of the
> struct is no longer 32bit-aligned. You fix this by adding a 16-bit member in
> front of prev_chunk so that (plus the 16-bit hole that this forces) the end of
> struct becomes 64-bit aligned.
> 
> Did I understand this correctly so far?

Right, see below.

> Also, where exactly does the SIGBUS happen? I guess that you are refering to the
> int64_t dy member of struct edge which e.g. polygon_add_edge() allocates from
> some pool via pool_alloc(). So if the struct itself isn't aligned to a 64 bit
> boundary, the dy member isn't either.


The SIGBUS happens when writing to edge->dxdy.rem, which is a long long.

Here is a reproducer:

int main(void) {
  struct polygon * polygon;
  struct edge * e;

  polygon = (struct polygon *) malloc(sizeof (struct polygon));
  polygon_init (polygon, NULL);

  e = pool_alloc (polygon->edge_pool.base, sizeof (struct edge));

  e->dxdy.quo = 42;   /* this works */
  e->dxdy.rem = 42;   /* SIGBUS here */

  /* sanity check */
  printf("%d\n", e->dxdy.quo);
  printf("%d\n", e->dxdy.rem);
  return 0;
} 

There are two cases that I could find where the pointer arithmetic
is in disagreement with the alignment rule.

In pool_alloc, we have this:

    struct _pool_chunk *chunk = pool->current;

    if (size <= chunk->capacity - chunk->size) {
        void *obj = ((unsigned char*)chunk + sizeof(*chunk) + chunk->size);
        chunk->size += size;
        return obj;

and we have the equivalent in _pool_alloc_from_new_chunk:

    obj = ((unsigned char*)chunk + sizeof(*chunk) + chunk->size);

We have sizeof(*chunk) = 12 on both cases, so obj->dxdy.rem is
not aligned after this addition.

Bumping sizeof(*chunk) to a multiple of 8 circumvents the problem in 
both cases.

> It would be nice if you submit your patch in the format produced by git
> format-patch. That includes a commit message and tracks you as the author of
> this, instead of someone else claiming the fame for this. All of the above
> reasoning and thoughts about this change could go into the commit message.

Attached. I am also happy with someone else suggesting a better patch and 
claiming the fame for this.

> The big downside of this: On 64bit platforms this adds an unused 64 bit hole to
> the struct.

Right, although my understanding of this part is that these are ephemeral, and
we want to privilege speed over memory consumption.

> I would instead suggest to add a new member "int64_t data" to the struct with a
> suitable comment explaining why it is of type int64_t. Instead of using
> ((unsigned char *)chunk + sizeof(*chunk)) for calculating the beginning of the
> data area of the chunk, the code could then use (unsigned char*)&chunk->data
> which IMO is more readable anyway.

I didn't understand this suggestion.

> However, I guess that such a change is more complicated since it requires
> reviewing the code more carefully since now sizeof(*chunk) is no longer the size
> of the "chunk header"...

Right. Perhaps we could also pre-allocate the array (embedded) as part of the pool
rather than a separate variable after the end of the pool, and keep an index on the
first free element of the array.

Nicolas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Pad-against-alignment-issue.patch
Type: application/octet-stream
Size: 1146 bytes
Desc: not available
URL: <http://lists.cairographics.org/archives/cairo/attachments/20141204/0e1150ae/attachment-0001.obj>


More information about the cairo mailing list