Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding a runtime error triggered by the undefined behavior sanitizer (UBSan)

I find a run-time error in GNU Scientific Library (GSL) when undefined sanitizer is enabled:

deque.c:58:11: runtime error: member access within misaligned address 0x0000024010f4 for type 'struct deque', which requires 8 byte alignment
0x0000024010f4: note: pointer points here
  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
              ^ 
deque.c:59:11: runtime error: member access within misaligned address 0x0000024010f4 for type 'struct deque', which requires 8 byte alignment
0x0000024010f4: note: pointer points here
  00 00 00 00 ff ff ff ff  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
              ^ 
deque.c:60:11: runtime error: member access within misaligned address 0x0000024010f4 for type 'struct deque', which requires 8 byte alignment
0x0000024010f4: note: pointer points here
  00 00 00 00 ff ff ff ff  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
              ^ 
deque.c:61:12: runtime error: member access within misaligned address 0x0000024010f4 for type 'struct deque', which requires 8 byte alignment
0x0000024010f4: note: pointer points here
  00 00 00 00 ff ff ff ff  00 00 00 00 05 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
              ^ 

But I have no idea how to the cause of these errors, or how to fix them. Can someone help explain? Besides, Is it an important issue that should be raised to developers (e.g. could this bee exploited as security attacks)?

The source code "deque.c" can be found here, with relevant lines of runtime errors shown below (the errors occur in lines 58,59,60,61).

enter image description here

And the definition of deque is here, in the same file:

here

[ADDED] The code invoking deque_init is below, in mmacc.c of GSL's movstat library:

static int
mmacc_init(const size_t n, void * vstate)
{
  mmacc_state_t * state = (mmacc_state_t *) vstate;

  state->n = n;
  state->k = 0;
  state->xprev = 0.0;

  state->rbuf = (ringbuf *) ((unsigned char *) vstate + sizeof(mmacc_state_t));
  state->minque = (deque *) ((unsigned char *) state->rbuf + ringbuf_size(n));
  state->maxque = (deque *) ((unsigned char *) state->minque + deque_size(n + 1));

  ringbuf_init(n, state->rbuf);
  deque_init(n + 1, state->minque);
  deque_init(n + 1, state->maxque);

  return GSL_SUCCESS;
}

The ringbuf_size function in the code above refers to the following code in ringbuf.c of the movstat library of GSL.

static size_t
ringbuf_size(const size_t n)
{
  size_t size = 0;

  size += sizeof(ringbuf);
  size += n * sizeof(ringbuf_type_t); /* b->array */

  return size;
}
like image 695
zell Avatar asked Oct 15 '22 23:10

zell


1 Answers

I'm not too familiar with the library, but here's the reason why you get the error.

deque.c:58:11: runtime error: member access within misaligned address 0x0000024010f4 for type 'struct deque', which requires 8 byte alignment
0x0000024010f4: note: pointer points here
  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
              ^ 

We can see, that indeed, pointer is shifted by 4. Let's figure out why.

The pointer comes from

state->minque = (deque *) ((unsigned char *) state->rbuf + ringbuf_size(n));

From this we can judge that either state->rbuf is misaligned or ringbuf_size returns value which is not aligned to 8. With a quick test, we can see, that indeed, ringbuf_size returns not aligned values. With a simple program I printed n, sizeof(ringbuf), n * sizeof(ringbuf_type_t) and final result.

0 24 + 0 = 24
1 24 + 4 = 28
2 24 + 8 = 32
3 24 + 12 = 36
4 24 + 16 = 40
5 24 + 20 = 44
6 24 + 24 = 48
7 24 + 28 = 52
8 24 + 32 = 56
9 24 + 36 = 60
10 24 + 40 = 64
11 24 + 44 = 68
12 24 + 48 = 72
13 24 + 52 = 76
14 24 + 56 = 80
15 24 + 60 = 84

As you can see, if you use odd number as size, then you get misaligned pointer (in your case it was 5). The reason being:

sizeof(size_t) = 8
sizeof(ringbuf_type_t) = 4

Example fix could be to add

size += (size % sizeof(size_t));

in ringbuf_size function. That way, the result changes to:

0 24 + 0 = 24
1 24 + 4 = 32
2 24 + 8 = 32
3 24 + 12 = 40
4 24 + 16 = 40
5 24 + 20 = 48
6 24 + 24 = 48
7 24 + 28 = 56
8 24 + 32 = 56
9 24 + 36 = 64
10 24 + 40 = 64
11 24 + 44 = 72
12 24 + 48 = 72
13 24 + 52 = 80
14 24 + 56 = 80
15 24 + 60 = 88
like image 159
BonusPlay Avatar answered Jan 04 '23 06:01

BonusPlay