【发布时间】:2011-12-14 03:30:00
【问题描述】:
这似乎是我以前的帖子,但这里的问题不同..
这是问题的 C 结构 -
typedef struct ip_esp_private { /* keep track of things privately */
u_int32_t type;
u_int32_t ivlen;
u_int32_t icvlen;
u_int32_t keylen; /* length of "Encryption key */
u_int32_t akeylen; /*length of authn key */
u_int32_t key[0]; /* encryption key and authentication key both */
} esp_private;
这些值在运行时提供给结构内容,如下所示 -
case 'k': /* Key */
length = stringargument(arg, &temp);
priv->keylen = length;
priv = (esp_private *)realloc(priv,
sizeof(esp_private)+/*length*/priv->keylen);
/*This one is edited */
// if(priv->akeylen)
// memmove(&priv->key[priv->keylen],
// &priv->key[0],priv->akeylen);
/*These three are commented*/
memcpy(&priv->key[0], temp, priv->keylen);
pack->private = priv;
pack->modified |= ESP_MOD_KEY;
break;
case 'K': /* Authentication Key */
length = stringargument(arg, &temp);
priv->akeylen = length; // marked line(explained below)
priv = (esp_private *)realloc(priv,
sizeof(esp_private)+/*length*/priv->keylen+priv->akeylen);
/*this one edited too */
memcpy(&priv->key[priv->keylen/sizeof(u_int32_t)],
temp,priv->akeylen);
pack->private = priv;
pack->modified |= ESP_MOD_KEY;
现在有一个使用身份验证密钥值的函数。
函数的相关部分是-
if (!epriv->akeylen) {
key = &fakekey;
keylen = 1;
} else {
key = (u_int8_t *)malloc(epriv->akeylen);
memcpy(key,&epriv->key[epriv->keylen/sizeof(u_int32_t)]
,epriv->akeylen);
现在,当我尝试运行以下程序时,遇到了这个我不知道的错误。
sendip: malloc.c:3574: mremap_chunk: Assertion `((size + offset)
& (mp_.pagesize-1)) == 0' failed.
我认为功能部分可能有错误,但我不确定它到底是什么,
因为当我评论标记的行(如上所述)时,akeylen 为空
所以采用fakekey 值和程序运行良好。
编辑 1:
我已经在三个地方编辑了代码(在上面的代码中也进行了编辑)。
现在程序可以运行,但输出不一致。
输入:
Encryption key - qwerty
Authentication key - abcdef
输出:
Encryption key - qwerab
Authentication key - abcdef
现在情况更清楚了。
这意味着realloc 声明中肯定存在问题。
请就此提出建议。
最初我在两个realloc 语句中都添加了长度,但现在我将其更改为priv->keylen 在第一位置和priv->keylen+priv->akeylen 在第二位置。
但是还有一些地方需要改进
为什么要覆盖???
【问题讨论】:
-
这纯属猜测,但你知道
stringargument(arg, &temp)的结果是什么吗?看起来您的realloc调用正在升级为mmap调用(或mremap),当您请求分配非常大的大小时会发生这种情况。如果您的stringargument函数偶然返回了一些太大的垃圾值,那么可能会发生有趣的事情。 -
请看看我的编辑
-
好的,我看到你的编辑了。但是你需要澄清你现在所看到的。你看到同样的断言失败了吗?或者您没有看到断言,但现在您正在覆盖一些内存?还是两者都见过?
-
现在没有错误了。我已经在上面显示了输入和输出,请查看密钥,加密密钥正在被身份验证密钥覆盖
-
为什么 VLA key[0] 是 uint32_t ?它似乎仅用作字符数组。此外,如果 keylen 不是 u_int32_t 的倍数,您尝试使用“&epriv->key[epriv->keylen/sizeof(u_int32_t)]”的字符串连接将覆盖内容。
标签: c memory-management memcpy memmove