Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/flb_pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -941,7 +941,7 @@ static inline int try_to_write(char *buf, int *off, size_t left,
if (str_len <= 0){
str_len = strlen(str);
}
if (left <= *off+str_len) {
if (left < *off + str_len) {
return FLB_FALSE;
}
memcpy(buf+*off, str, str_len);
Expand Down Expand Up @@ -1151,18 +1151,20 @@ static int msgpack2json(char *buf, int *off, size_t left,
* @param json_str The buffer to fill JSON string.
* @param json_size The size of json_str.
* @param data The msgpack_unpacked data.
* @return success ? a number characters filled : negative value
* @return characters written on success, zero if the buffer is too small,
* or a negative value for invalid arguments.
*/
int flb_msgpack_to_json(char *json_str, size_t json_size,
const msgpack_object *obj, int escape_unicode)
{
int ret = -1;
int off = 0;

if (json_str == NULL || obj == NULL) {
if (json_str == NULL || obj == NULL || json_size == 0) {
return -1;
}

/* Reserve the terminator once; writers may use all remaining bytes. */
ret = msgpack2json(json_str, &off, json_size - 1, obj, escape_unicode);
json_str[off] = '\0';
return ret ? off: ret;
Expand Down
88 changes: 88 additions & 0 deletions tests/internal/pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -1287,7 +1287,95 @@ void test_json_pack_token_count_overflow()
flb_pack_state_reset(&state);
}


void test_json_pack_buffer_capacity(void)
{
struct {
const char *packed;
size_t packed_size;
const char *raw;
const char *escaped;
} cases[] = {
{"\xc0", 1, "null", "null"},
{"\xc3", 1, "true", "true"},
{"\xc2", 1, "false", "false"},
{"\x2a", 1, "42", "42"},
{"\xd0\xd6", 2, "-42", "-42"},
{"\xcb\x3f\xf8\x00\x00\x00\x00\x00\x00", 9, "1.5", "1.5"},
{"\xa0", 1, "\"\"", "\"\""},
{"\xa4" "abcd", 5, "\"abcd\"", "\"abcd\""},
{"\xa6" "a\n\"\\\xc3\xa9", 7,
"\"a\\n\\\"\\\\\xc3\xa9\"", "\"a\\n\\\"\\\\\\u00e9\""},
{"\xa4\xf0\x9f\x98\x80", 5,
"\"\xf0\x9f\x98\x80\"", "\"\\ud83d\\ude00\""},
{"\xd9\x20" "0123456789abcdef0123456789abcdef", 34,
"\"0123456789abcdef0123456789abcdef\"",
"\"0123456789abcdef0123456789abcdef\""},
{"\xc4\x04" "abcd", 6, "\"abcd\"", "\"abcd\""},
{"\xd4\x01" "a", 3, "\"\\x61\"", "\"\\x61\""},
{"\x90", 1, "[]", "[]"},
{"\x80", 1, "{}", "{}"},
{"\x81\xa1" "a" "\x93\xc0\x81\xa1" "b" "\xa4" "abcd" "\x90", 14,
"{\"a\":[null,{\"b\":\"abcd\"},[]]}",
"{\"a\":[null,{\"b\":\"abcd\"},[]]}"},
};
size_t i;
size_t capacity;
size_t expected_size;
size_t offset;
int escape_unicode;
int ret;
char *allocation;
char *buffer;
const char *expected;
msgpack_unpacked unpacked;

for (i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
offset = 0;
msgpack_unpacked_init(&unpacked);
ret = msgpack_unpack_next(&unpacked, cases[i].packed,
cases[i].packed_size, &offset);
TEST_ASSERT(ret == MSGPACK_UNPACK_SUCCESS);
TEST_CHECK(offset == cases[i].packed_size);

for (escape_unicode = FLB_FALSE; escape_unicode <= FLB_TRUE; escape_unicode++) {
expected = escape_unicode ? cases[i].escaped : cases[i].raw;
expected_size = strlen(expected);

for (capacity = 0; capacity <= expected_size + 2; capacity++) {
allocation = flb_malloc(capacity + 2);
TEST_ASSERT(allocation != NULL);
memset(allocation, 'X', capacity + 2);
buffer = allocation + 1;

ret = flb_msgpack_to_json(buffer, capacity, &unpacked.data,
escape_unicode);
TEST_CHECK(allocation[0] == 'X');
TEST_CHECK(buffer[capacity] == 'X');
TEST_MSG("case=%zu capacity=%zu escape_unicode=%d",
i, capacity, escape_unicode);
if (capacity == 0) {
TEST_CHECK(ret == -1);
}
else if (capacity <= expected_size) {
TEST_CHECK(ret == 0);
TEST_CHECK(memchr(buffer, '\0', capacity) != NULL);
}
else {
TEST_CHECK(ret == expected_size);
TEST_MSG("case=%zu capacity=%zu escape_unicode=%d ret=%d",
i, capacity, escape_unicode, ret);
TEST_CHECK(memcmp(buffer, expected, expected_size + 1) == 0);
}
flb_free(allocation);
}
}
msgpack_unpacked_destroy(&unpacked);
}
}

TEST_LIST = {
{ "json_pack_buffer_capacity", test_json_pack_buffer_capacity },
/* JSON maps iteration */
{ "json_pack" , test_json_pack },
{ "json_pack_ext_default_backend", test_json_pack_ext_default_backend },
Expand Down
Loading