您提到的手册页
如果 *ppout 为 NULL,将为缓冲区分配内存并将编码数据写入其中。
但是,这不适用于i2d_ASN1_OBJECT()
您使用的功能。在 a_object.c 中查看该函数的源代码,任何地方都没有分配。段错误发生在这里,在 ASN1_put_object 更深一层。
由于它不会为您分配内存,因此您必须自己提供一个缓冲区,如下所示:
unsigned char ctderarray[64];
unsigned char *ctder = ctderarray;
int ctderlen, r;
ASN1_OBJECT* obj = OBJ_txt2obj("1.2.3.4", 1);
ctderlen = i2d_ASN1_OBJECT(obj, &ctder);
if (ctderlen <= 0) {
return 0;
} else {
printf("ctderlen = %d\n", ctderlen);
}
这将打印值5
。另一个不为您进行分配的函数的示例是i2d_ASN1_BOOLEAN()
,如果您尝试将它与NULL
out 指针一起使用,它实际上也会崩溃。
那么为什么文档与您的经验相矛盾,为什么它适用于您的其他代码片段?文档不准确,但大多数其他i2d_XYZ()
功能都是通过(复杂的)模板方案由functionasn1_item_flags_i2d()
以通用方式实现的。在那里,分配确实发生在你身上:
/*
* Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
* points to a buffer to output the data to. The new i2d has one additional
* feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
* allocated and populated with the encoding.
*/
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it, int flags)
{
if (out && !*out) {
unsigned char *p, *buf;
int len;
len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
if (len <= 0)
return len;
buf = OPENSSL_malloc(len);
if (!buf)
return -1;
p = buf;
ASN1_item_ex_i2d(&val, &p, it, -1, flags);
*out = buf;
return len;
}
return ASN1_item_ex_i2d(&val, out, it, -1, flags);
}
这里的一些模板化函数(间接)调用它:
# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
{ \
return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
} \
int i2d_##fname(stname *a, unsigned char **out) \
{ \
return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
}
只要i2d_XYZ
您使用的功能是通过此模板机制定义的,(其中大多数是)该功能将为您进行分配。否则,您将不得不自己做。