了解由未定义行为消毒剂 (UBSan) 触发的运行时错误

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

我在 GNU 科学图书馆 (GSL) 中发现了一个 运行 时间的错误,当未定义的消毒剂被启用时:

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
              ^ 

但我不知道这些错误的原因或修复方法。有人可以帮忙解释一下吗?此外,这是一个应该向开发人员提出的重要问题吗(例如,这只蜜蜂是否会被用作安全攻击)?

源代码“deque.c”可在here找到,相关运行行错误如下所示(错误出现在第58、59、60、61行).

双端队列的定义在这里,在同一个文件中:

[已添加] 调用 deque_init 的代码如下,在 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;
}

上面代码中的ringbuf_size函数引用了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;
}

我不太熟悉该库,但这就是您收到错误的原因。

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
              ^ 

我们可以看到,确实,指针移动了4。让我们找出原因。

指针来自

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

由此判断,要么是state->rbuf错位,要么是ringbuf_sizereturns值没有对齐到8。通过快速测试,我们可以看到,确实, ringbuf_size returns 未对齐值。通过一个简单的程序,我打印了 nsizeof(ringbuf)n * sizeof(ringbuf_type_t) 和最终结果。

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

如您所见,如果您使用奇数作为 size,那么您会得到未对齐的指针(在您的例子中是 5)。原因是:

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

示例修复可以是添加

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

ringbuf_size 函数中。这样,结果变为:

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