【问题标题】:Understanding a runtime error triggered by the undefined behavior sanitizer (UBSan)了解由未定义行为清理程序 (UBSan) 触发的运行时错误
【发布时间】:2020-12-22 14:10:56
【问题描述】:

当启用未定义的消毒剂时,我在 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的定义在这里,在同一个文件中:

[添加] 调用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_init() 的代码。为什么该代码将未对齐的地址传递给函数?此外,您应该在问题中发布代码,而不是代码的图像。
  • @JonathanLeffler 请在上面查看我的编辑。谢谢你的好建议。

标签: security gsl sanitizer ubsan


【解决方案1】:

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

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_size 返回的值未对齐到8。通过快速测试,我们可以看到,确实,ringbuf_size 返回未对齐的值。通过一个简单的程序,我打印了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

【讨论】:

  • 非常感谢您的详细分析。你说“我用一个简单的程序打印了 n、sizeof(ringbuf)、n * sizeof(ringbuf_type_t) 和最终结果。”你愿意和我们分享你的程序吗?您的程序是否调用 GSL?
  • 您也说过“由此我们可以判断 state->rbuf 未对齐或 ringbuf_size 返回的值未对齐到 8。”一般来说,如果 a=b+c,a 可以是 8 的倍数,而 b 或 c 都不是 8 的倍数,例如 16=14+2。所以我猜你不会得出这个结论。
  • 1) 该程序是用 C++ 编写的,它是可用的 here。我只是复制了最少量的声明以使其工作。 2) 理论上你是对的,这可能发生在这两个位置都没有对齐,但是state->rbuf 设置为state + sizeof(mmacc_state_t),这对我来说听起来很正常。不过你说得对,我的解释不清楚。
猜你喜欢
  • 2021-08-02
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 2018-07-04
  • 2012-08-08
相关资源
最近更新 更多