loader: Add loading error messages

This commit is contained in:
Paweł Bylica 2019-04-16 20:12:15 +02:00
parent 51fe9f48d4
commit 4484a8b74a
No known key found for this signature in database
GPG Key ID: 7A0C037434FE77EF
2 changed files with 65 additions and 7 deletions

View File

@ -8,7 +8,9 @@
#include <evmc/evmc.h>
#include <evmc/helpers.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#if defined(EVMC_LOADER_MOCK)
@ -48,6 +50,27 @@ static void strcpy_s(char* dest, size_t destsz, const char* src)
static const char* last_error_msg = NULL;
#define LAST_ERROR_MSG_BUFFER_SIZE 511
// Buffer for formatted error messages.
// It has one null byte extra to avoid buffer read overflow during concurrent access.
static char last_error_msg_buffer[LAST_ERROR_MSG_BUFFER_SIZE + 1];
// TODO: Change that into a macro - will be simpler and we will get compilers warnings for snprintf
// misuse.
static enum evmc_loader_error_code set_error(enum evmc_loader_error_code error_code,
const char* format,
...)
{
va_list args;
va_start(args, format);
if (vsnprintf(last_error_msg_buffer, LAST_ERROR_MSG_BUFFER_SIZE, format, args) <
LAST_ERROR_MSG_BUFFER_SIZE)
last_error_msg = last_error_msg_buffer;
va_end(args);
return error_code;
}
evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* error_code)
{
@ -57,14 +80,21 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro
if (!filename)
{
ec = EVMC_LOADER_INVALID_ARGUMENT;
ec = set_error(EVMC_LOADER_INVALID_ARGUMENT, "invalid argument: file name cannot be null");
goto exit;
}
const size_t length = strlen(filename);
if (length == 0 || length > PATH_MAX_LENGTH)
if (length == 0)
{
ec = EVMC_LOADER_INVALID_ARGUMENT;
ec = set_error(EVMC_LOADER_INVALID_ARGUMENT, "invalid argument: file name cannot be empty");
goto exit;
}
else if (length > PATH_MAX_LENGTH)
{
ec = set_error(EVMC_LOADER_INVALID_ARGUMENT,
"invalid argument: file name is too long (%d, maximum allowed length is %d)",
(int)length, PATH_MAX_LENGTH);
goto exit;
}
@ -73,7 +103,10 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro
{
// Get error message if available.
last_error_msg = DLL_GET_ERROR_MSG();
ec = EVMC_LOADER_CANNOT_OPEN;
if (last_error_msg)
ec = EVMC_LOADER_CANNOT_OPEN;
else
ec = set_error(EVMC_LOADER_CANNOT_OPEN, "cannot open %s", filename);
goto exit;
}
@ -128,7 +161,8 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro
if (!create_fn)
{
DLL_CLOSE(handle);
ec = EVMC_LOADER_SYMBOL_NOT_FOUND;
ec = set_error(EVMC_LOADER_SYMBOL_NOT_FOUND, "EVMC create function not found in %s",
filename);
}
exit:
@ -156,13 +190,16 @@ struct evmc_instance* evmc_load_and_create(const char* filename,
struct evmc_instance* instance = create_fn();
if (!instance)
{
*error_code = EVMC_LOADER_INSTANCE_CREATION_FAILURE;
*error_code = set_error(EVMC_LOADER_INSTANCE_CREATION_FAILURE,
"creating EVMC instance of %s has failed", filename);
return NULL;
}
if (!evmc_is_abi_compatible(instance))
{
*error_code = EVMC_LOADER_ABI_VERSION_MISMATCH;
*error_code = set_error(EVMC_LOADER_ABI_VERSION_MISMATCH,
"EVMC ABI version %d of %s mismatches the expected version %d",
instance->abi_version, filename, EVMC_ABI_VERSION);
return NULL;
}

View File

@ -66,8 +66,14 @@ TEST_F(loader, load_long_path)
const std::string path(5000, 'a');
evmc_loader_error_code ec;
EXPECT_EQ(evmc_load(path.c_str(), &ec), nullptr);
EXPECT_STREQ(evmc_last_error_msg(),
"invalid argument: file name is too long (5000, maximum allowed length is 4096)");
EXPECT_EQ(evmc_last_error_msg(), nullptr);
EXPECT_EQ(ec, EVMC_LOADER_INVALID_ARGUMENT);
EXPECT_EQ(evmc_load(path.c_str(), nullptr), nullptr);
EXPECT_STREQ(evmc_last_error_msg(),
"invalid argument: file name is too long (5000, maximum allowed length is 4096)");
EXPECT_EQ(evmc_last_error_msg(), nullptr);
}
TEST_F(loader, load_null_path)
@ -75,15 +81,23 @@ TEST_F(loader, load_null_path)
evmc_loader_error_code ec;
EXPECT_EQ(evmc_load(nullptr, &ec), nullptr);
EXPECT_EQ(ec, EVMC_LOADER_INVALID_ARGUMENT);
EXPECT_STREQ(evmc_last_error_msg(), "invalid argument: file name cannot be null");
EXPECT_EQ(evmc_last_error_msg(), nullptr);
EXPECT_EQ(evmc_load(nullptr, nullptr), nullptr);
EXPECT_STREQ(evmc_last_error_msg(), "invalid argument: file name cannot be null");
EXPECT_EQ(evmc_last_error_msg(), nullptr);
}
TEST_F(loader, load_empty_path)
{
evmc_loader_error_code ec;
EXPECT_EQ(evmc_load("", &ec), nullptr);
EXPECT_STREQ(evmc_last_error_msg(), "invalid argument: file name cannot be empty");
EXPECT_EQ(evmc_last_error_msg(), nullptr);
EXPECT_EQ(ec, EVMC_LOADER_INVALID_ARGUMENT);
EXPECT_EQ(evmc_load("", nullptr), nullptr);
EXPECT_STREQ(evmc_last_error_msg(), "invalid argument: file name cannot be empty");
EXPECT_EQ(evmc_last_error_msg(), nullptr);
}
TEST_F(loader, load_prefix_aaa)
@ -104,6 +118,7 @@ TEST_F(loader, load_prefix_aaa)
EXPECT_EQ(ec, EVMC_LOADER_SUCCESS);
ASSERT_NE(fn, nullptr);
EXPECT_EQ((uintptr_t)fn(), 0xaaa);
EXPECT_EQ(evmc_last_error_msg(), nullptr);
}
}
@ -115,6 +130,7 @@ TEST_F(loader, load_eee_bbb)
ASSERT_NE(fn, nullptr);
EXPECT_EQ(ec, EVMC_LOADER_SUCCESS);
EXPECT_EQ((uintptr_t)fn(), 0xeeebbb);
EXPECT_EQ(evmc_last_error_msg(), nullptr);
}
@ -162,6 +178,8 @@ TEST_F(loader, load_symbol_not_found)
evmc_loader_error_code ec;
EXPECT_EQ(evmc_load(evmc_test_library_path, &ec), nullptr);
EXPECT_EQ(ec, EVMC_LOADER_SYMBOL_NOT_FOUND);
EXPECT_EQ(evmc_last_error_msg(), "EVMC create function not found in " + std::string(path));
EXPECT_EQ(evmc_last_error_msg(), nullptr);
EXPECT_EQ(evmc_load(evmc_test_library_path, nullptr), nullptr);
}
}
@ -187,6 +205,7 @@ TEST_F(loader, load_and_create_failure)
auto vm = evmc_load_and_create(evmc_test_library_path, &ec);
EXPECT_EQ(vm, nullptr);
EXPECT_EQ(ec, EVMC_LOADER_INSTANCE_CREATION_FAILURE);
EXPECT_STREQ(evmc_last_error_msg(), "creating EVMC instance of failure.vm has failed");
}
TEST_F(loader, load_and_create_abi_mismatch)
@ -197,4 +216,6 @@ TEST_F(loader, load_and_create_abi_mismatch)
auto vm = evmc_load_and_create(evmc_test_library_path, &ec);
EXPECT_EQ(vm, nullptr);
EXPECT_EQ(ec, EVMC_LOADER_ABI_VERSION_MISMATCH);
EXPECT_STREQ(evmc_last_error_msg(),
"EVMC ABI version 42 of abi42.vm mismatches the expected version 6");
}