Merge pull request #307 from ethereum/loader_strcpy_s

loader: Fix strcpy_s()
This commit is contained in:
Paweł Bylica 2019-05-31 12:28:02 +02:00 committed by GitHub
commit 0f2416da0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 7 deletions

View File

@ -42,18 +42,33 @@
#define ATTR_FORMAT(...)
#endif
#if !_WIN32
#if _WIN32
#define strcpy_sx strcpy_s
#else
/*
* Provide strcpy_s() for GNU libc.
* Limited variant of strcpy_s().
*
* Provided for C standard libraries where strcpy_s() is not available.
* The availability check might need to adjusted for other C standard library implementations.
*/
static void strcpy_s(char* dest, size_t destsz, const char* src)
#if !defined(EVMC_LOADER_MOCK)
static
#endif
int
strcpy_sx(char* restrict dest, size_t destsz, const char* restrict src)
{
size_t len = strlen(src);
if (len > destsz - 1)
len = destsz - 1;
if (len >= destsz)
{
// The input src will not fit into the dest buffer.
// Set the first byte of the dest to null to make it effectively empty string
// and return error.
dest[0] = 0;
return 1;
}
memcpy(dest, src, len);
dest[len] = 0;
return 0;
}
#endif
@ -124,7 +139,7 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro
const char prefix[] = "evmc_create_";
const size_t prefix_length = strlen(prefix);
char prefixed_name[sizeof(prefix) + PATH_MAX_LENGTH];
strcpy_s(prefixed_name, sizeof(prefixed_name), prefix);
strcpy_sx(prefixed_name, sizeof(prefixed_name), prefix);
// Find filename in the path.
const char* sep_pos = strrchr(filename, '/');
@ -142,7 +157,7 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro
name_pos += lib_prefix_length;
char* base_name = prefixed_name + prefix_length;
strcpy_s(base_name, PATH_MAX_LENGTH, name_pos);
strcpy_sx(base_name, PATH_MAX_LENGTH, name_pos);
// Trim the file extension.
char* ext_pos = strrchr(prefixed_name, '.');

View File

@ -16,6 +16,13 @@ static constexpr bool is_windows = false;
#endif
extern "C" {
#if _WIN32
#define strcpy_sx strcpy_s
#else
/// Declaration of internal function defined in loader.c.
int strcpy_sx(char* dest, size_t destsz, const char* src);
#endif
/// The library path expected by mocked evmc_test_load_library().
extern const char* evmc_test_library_path;
@ -118,6 +125,28 @@ static evmc_instance* create_failure()
return nullptr;
}
TEST_F(loader, strcpy_sx)
{
const char input_empty[] = "";
const char input_that_fits[] = "x";
const char input_too_big[] = "12";
char buf[2] = {0x0f, 0x0f};
static_assert(sizeof(input_empty) <= sizeof(buf), "");
static_assert(sizeof(input_that_fits) <= sizeof(buf), "");
static_assert(sizeof(input_too_big) > sizeof(buf), "");
EXPECT_EQ(strcpy_sx(buf, sizeof(buf), input_empty), 0);
EXPECT_EQ(buf[0], 0);
EXPECT_EQ(buf[1], 0x0f);
EXPECT_EQ(strcpy_sx(buf, sizeof(buf), input_that_fits), 0);
EXPECT_EQ(buf[0], 'x');
EXPECT_EQ(buf[1], 0);
EXPECT_NE(strcpy_sx(buf, sizeof(buf), input_too_big), 0);
EXPECT_EQ(buf[0], 0);
}
TEST_F(loader, load_nonexistent)
{
constexpr auto path = "nonexistent";