对函数指针的断言失败
Assertion —to a function pointer— failed
我正在玩 Signal 的 libsignal 库,试图猜测如何编译和 运行 一个小玩具程序。但是,我一开始就被困住了。我知道我必须用指向稍后将在库中使用的函数的指针填充一个变量,即使我试图复制库在其测试中所做的事情,我也看不出测试和我的代码,以及为什么我的程序在 运行 时间内失败。我使用的代码如下:
#include <stdlib>
#include <signal/signal_protocol.h>
#include <signal/key_helper.h>
#include <openssl/rand.h>
int random(uint8_t *data, size_t len, void *user_data)
{
if(RAND_bytes(data, len)) {
return 0;
}
else {
return SG_ERR_UNKNOWN;
}
}
int main(int argc, char **argv) {
signal_crypto_provider provider = {
.random_func = random
/*.hmac_sha256_init_func = HMAC_CTX_new,
.hmac_sha256_update_func = HMAC_Update,
.hmac_sha256_final_func = HMAC_Final,
.hmac_sha256_cleanup_func = HMAC_CTX_free,
.sha512_digest_init_func = SHA512_Init,
.sha512_digest_update_func = SHA512_Update,
.sha512_digest_final_func = SHA512_Final,
.sha512_digest_cleanup_func = EVP_MD_CTX_free,
.encrypt_func = EVP_aes_256_cbc,
.decrypt_func = EVP_aes_256_cbc,
.user_data = 0*/
};
signal_context *global_context;
signal_context_create(&global_context, 0);
signal_context_set_crypto_provider(global_context, &provider);
//signal_context_set_locking_functions(global_context, lock_function,
//unlock_function);
ratchet_identity_key_pair *identity_key_pair;
uint32_t registration_id;
signal_protocol_key_helper_pre_key_list_node *pre_keys_head;
session_signed_pre_key *signed_pre_key;
signal_protocol_key_helper_generate_identity_key_pair(
&identity_key_pair,
global_context
);
exit(EXIT_SUCCESS);
}
程序运行到signal_protocol_key_helper_generate_identity_key_pair
时出现问题。浏览库并跟踪它的调用,我得到了以下函数:
int signal_crypto_random(signal_context *context, uint8_t *data, size_t len)
{
assert(context);
assert(context->crypto_provider.random_func);
return context->crypto_provider.random_func(data, len, context->crypto_provider.user_data);
}
失败的断言是第二个,给我以下错误:
signal_crypto_random: Assertion `context->crypto_provider.random_func' failed.
我能想到的唯一解释——我是 C 的新手——不知何故指针没有指向我之前指定的函数。如果这个猜测是正确的,为什么会这样?
检查他们的测试代码,并将其与我的代码进行比较,我看不出是什么导致我的程序失败的关键区别。调试时,变量似乎有正确的内容。
谢谢。
void setup_test_crypto_provider(signal_context *context)
{
signal_crypto_provider provider = {
.random_func = test_random_generator,
.hmac_sha256_init_func = test_hmac_sha256_init,
.hmac_sha256_update_func = test_hmac_sha256_update,
.hmac_sha256_final_func = test_hmac_sha256_final,
.hmac_sha256_cleanup_func = test_hmac_sha256_cleanup,
.sha512_digest_init_func = test_sha512_digest_init,
.sha512_digest_update_func = test_sha512_digest_update,
.sha512_digest_final_func = test_sha512_digest_final,
.sha512_digest_cleanup_func = test_sha512_digest_cleanup,
.encrypt_func = test_encrypt,
.decrypt_func = test_decrypt,
.user_data = 0
};
signal_context_set_crypto_provider(context, &provider);
}
int test_random_generator(uint8_t *data, size_t len, void *user_data)
{
if(RAND_bytes(data, len)) {
return 0;
}
else {
return SG_ERR_UNKNOWN;
}
}
在signal_context_set_crypto_provider()
中有一个检查:
if(!crypto_provider
|| !crypto_provider->hmac_sha256_init_func
|| !crypto_provider->hmac_sha256_update_func
|| !crypto_provider->hmac_sha256_final_func
|| !crypto_provider->hmac_sha256_cleanup_func) {
return SG_ERR_INVAL;
}
所以,答案是您不能不设置这些回调,这就是为什么没有任何内容被复制到上下文并且 assert()
最终触发的原因。
我理解为什么测试代码不检查 return 代码,但在生产代码中您需要检查 return 值以留意错误 - 它被简单地认为是好的做法。
我正在玩 Signal 的 libsignal 库,试图猜测如何编译和 运行 一个小玩具程序。但是,我一开始就被困住了。我知道我必须用指向稍后将在库中使用的函数的指针填充一个变量,即使我试图复制库在其测试中所做的事情,我也看不出测试和我的代码,以及为什么我的程序在 运行 时间内失败。我使用的代码如下:
#include <stdlib>
#include <signal/signal_protocol.h>
#include <signal/key_helper.h>
#include <openssl/rand.h>
int random(uint8_t *data, size_t len, void *user_data)
{
if(RAND_bytes(data, len)) {
return 0;
}
else {
return SG_ERR_UNKNOWN;
}
}
int main(int argc, char **argv) {
signal_crypto_provider provider = {
.random_func = random
/*.hmac_sha256_init_func = HMAC_CTX_new,
.hmac_sha256_update_func = HMAC_Update,
.hmac_sha256_final_func = HMAC_Final,
.hmac_sha256_cleanup_func = HMAC_CTX_free,
.sha512_digest_init_func = SHA512_Init,
.sha512_digest_update_func = SHA512_Update,
.sha512_digest_final_func = SHA512_Final,
.sha512_digest_cleanup_func = EVP_MD_CTX_free,
.encrypt_func = EVP_aes_256_cbc,
.decrypt_func = EVP_aes_256_cbc,
.user_data = 0*/
};
signal_context *global_context;
signal_context_create(&global_context, 0);
signal_context_set_crypto_provider(global_context, &provider);
//signal_context_set_locking_functions(global_context, lock_function,
//unlock_function);
ratchet_identity_key_pair *identity_key_pair;
uint32_t registration_id;
signal_protocol_key_helper_pre_key_list_node *pre_keys_head;
session_signed_pre_key *signed_pre_key;
signal_protocol_key_helper_generate_identity_key_pair(
&identity_key_pair,
global_context
);
exit(EXIT_SUCCESS);
}
程序运行到signal_protocol_key_helper_generate_identity_key_pair
时出现问题。浏览库并跟踪它的调用,我得到了以下函数:
int signal_crypto_random(signal_context *context, uint8_t *data, size_t len)
{
assert(context);
assert(context->crypto_provider.random_func);
return context->crypto_provider.random_func(data, len, context->crypto_provider.user_data);
}
失败的断言是第二个,给我以下错误:
signal_crypto_random: Assertion `context->crypto_provider.random_func' failed.
我能想到的唯一解释——我是 C 的新手——不知何故指针没有指向我之前指定的函数。如果这个猜测是正确的,为什么会这样?
检查他们的测试代码,并将其与我的代码进行比较,我看不出是什么导致我的程序失败的关键区别。调试时,变量似乎有正确的内容。
谢谢。
void setup_test_crypto_provider(signal_context *context)
{
signal_crypto_provider provider = {
.random_func = test_random_generator,
.hmac_sha256_init_func = test_hmac_sha256_init,
.hmac_sha256_update_func = test_hmac_sha256_update,
.hmac_sha256_final_func = test_hmac_sha256_final,
.hmac_sha256_cleanup_func = test_hmac_sha256_cleanup,
.sha512_digest_init_func = test_sha512_digest_init,
.sha512_digest_update_func = test_sha512_digest_update,
.sha512_digest_final_func = test_sha512_digest_final,
.sha512_digest_cleanup_func = test_sha512_digest_cleanup,
.encrypt_func = test_encrypt,
.decrypt_func = test_decrypt,
.user_data = 0
};
signal_context_set_crypto_provider(context, &provider);
}
int test_random_generator(uint8_t *data, size_t len, void *user_data)
{
if(RAND_bytes(data, len)) {
return 0;
}
else {
return SG_ERR_UNKNOWN;
}
}
在signal_context_set_crypto_provider()
中有一个检查:
if(!crypto_provider
|| !crypto_provider->hmac_sha256_init_func
|| !crypto_provider->hmac_sha256_update_func
|| !crypto_provider->hmac_sha256_final_func
|| !crypto_provider->hmac_sha256_cleanup_func) {
return SG_ERR_INVAL;
}
所以,答案是您不能不设置这些回调,这就是为什么没有任何内容被复制到上下文并且 assert()
最终触发的原因。
我理解为什么测试代码不检查 return 代码,但在生产代码中您需要检查 return 值以留意错误 - 它被简单地认为是好的做法。