Spdk/test/app/fuzz/common/fuzz_common.h
paul luse a6dbe3721e update Intel copyright notices
per Intel policy to include file commit date using git cmd
below.  The policy does not apply to non-Intel (C) notices.

git log --follow -C90% --format=%ad --date default <file> | tail -1

and then pull just the 4 digit year from the result.

Intel copyrights were not added to files where Intel either had
no contribution ot the contribution lacked substance (ie license
header updates, formatting changes, etc).  Contribution date used
"--follow -C95%" to get the most accurate date.

Note that several files in this patch didn't end the license/(c)
block with a blank comment line so these were added as the vast
majority of files do have this last blank line.  Simply there for
consistency.

Signed-off-by: paul luse <paul.e.luse@intel.com>
Change-Id: Id5b7ce4f658fe87132f14139ead58d6e285c04d4
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15192
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Community-CI: Mellanox Build Bot
2022-11-10 08:28:53 +00:00

276 lines
5.7 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2018 Intel Corporation.
* All rights reserved.
*/
#include "spdk/stdinc.h"
#include "spdk/env.h"
#include "spdk/file.h"
#include "spdk/base64.h"
#include "spdk/json.h"
#define DEFAULT_RUNTIME 30 /* seconds */
#define MAX_RUNTIME_S 86400 /* 24 hours */
#define IO_TIMEOUT_S 5
#define UNSIGNED_2BIT_MAX ((1 << 2) - 1)
#define UNSIGNED_4BIT_MAX ((1 << 4) - 1)
#define UNSIGNED_8BIT_MAX ((1 << 8) - 1)
typedef bool (*json_parse_fn)(void *ele, struct spdk_json_val *val, size_t num_vals);
static void
fuzz_fill_random_bytes(char *character_repr, size_t len, unsigned int *rand_seed)
{
size_t i;
for (i = 0; i < len; i++) {
character_repr[i] = rand_r(rand_seed) % UINT8_MAX;
}
}
static uint64_t
fuzz_refresh_timeout(void)
{
uint64_t current_ticks;
uint64_t new_timeout_ticks;
current_ticks = spdk_get_ticks();
new_timeout_ticks = current_ticks + IO_TIMEOUT_S * spdk_get_ticks_hz();
assert(new_timeout_ticks > current_ticks);
return new_timeout_ticks;
}
static char *
fuzz_get_value_base_64_buffer(void *item, size_t len)
{
char *value_string;
size_t total_size;
int rc;
/* Null pointer */
total_size = spdk_base64_get_encoded_strlen(len) + 1;
value_string = calloc(1, total_size);
if (value_string == NULL) {
return NULL;
}
rc = spdk_base64_encode(value_string, item, len);
if (rc < 0) {
free(value_string);
return NULL;
}
return value_string;
}
static int
fuzz_get_base_64_buffer_value(void *item, size_t len, char *buf, size_t buf_len)
{
size_t size_of_data;
char *new_buf;
int rc;
new_buf = malloc(buf_len + 1);
if (new_buf == NULL) {
return -ENOMEM;
}
snprintf(new_buf, buf_len + 1, "%s", buf);
size_of_data = spdk_base64_get_decoded_len(buf_len);
if (size_of_data < len) {
free(new_buf);
return -EINVAL;
}
rc = spdk_base64_decode(item, &size_of_data, new_buf);
if (rc || size_of_data != len) {
free(new_buf);
return -EINVAL;
}
free(new_buf);
return 0;
}
static ssize_t
read_json_into_buffer(const char *filename, struct spdk_json_val **values, void **file_data)
{
FILE *file = fopen(filename, "r");
size_t file_data_size;
ssize_t num_json_values = 0, rc;
if (file == NULL) {
/* errno is set by fopen */
return 0;
}
*file_data = spdk_posix_file_load(file, &file_data_size);
if (*file_data == NULL) {
fclose(file);
return 0;
}
fclose(file);
num_json_values = spdk_json_parse(*file_data, file_data_size, NULL, 0, NULL,
SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
*values = calloc(num_json_values, sizeof(**values));
if (values == NULL) {
free(*file_data);
*file_data = NULL;
return 0;
}
rc = spdk_json_parse(*file_data, file_data_size, *values, num_json_values, NULL,
SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
if (num_json_values != rc) {
free(*values);
*values = NULL;
free(*file_data);
*file_data = NULL;
return 0;
}
return num_json_values;
}
static size_t
double_arr_size(void **buffer, size_t num_ele, size_t ele_size)
{
void *tmp;
size_t new_num_ele, allocation_size;
if (num_ele > SIZE_MAX / 2) {
return 0;
}
new_num_ele = num_ele * 2;
if (new_num_ele > SIZE_MAX / ele_size) {
return 0;
}
allocation_size = new_num_ele * ele_size;
tmp = realloc(*buffer, allocation_size);
if (tmp != NULL) {
*buffer = tmp;
return new_num_ele;
}
return 0;
}
static uint64_t
fuzz_parse_args_into_array(const char *file, void **arr, size_t ele_size, const char *obj_name,
json_parse_fn cb_fn)
{
ssize_t i, num_json_values;
struct spdk_json_val *values = NULL, *values_head = NULL, *obj_start;
void *file_data = NULL;;
char *arr_idx_pointer;
size_t num_arr_elements, arr_elements_used, values_in_obj;
bool rc;
num_json_values = read_json_into_buffer(file, &values_head, &file_data);
values = values_head;
if (num_json_values == 0 || values == NULL) {
if (file_data != NULL) {
free(file_data);
}
fprintf(stderr, "The file provided does not exist or we were unable to parse it.\n");
return 0;
}
num_arr_elements = 10;
arr_elements_used = 0;
*arr = calloc(num_arr_elements, ele_size);
arr_idx_pointer = (char *)*arr;
if (arr_idx_pointer == NULL) {
free(values);
free(file_data);
return 0;
}
i = 0;
while (i < num_json_values) {
if (values->type != SPDK_JSON_VAL_NAME) {
i++;
values++;
continue;
}
if (!strncmp(values->start, obj_name, values->len)) {
i++;
values++;
assert(values->type == SPDK_JSON_VAL_OBJECT_BEGIN);
obj_start = values;
values_in_obj = spdk_json_val_len(obj_start);
values += values_in_obj;
i += values_in_obj;
rc = cb_fn((void *)arr_idx_pointer, obj_start, values_in_obj);
if (rc == false) {
fprintf(stderr, "failed to parse file after %zu elements.\n", arr_elements_used);
goto fail;
}
arr_idx_pointer += ele_size;
arr_elements_used++;
if (arr_elements_used == num_arr_elements) {
num_arr_elements = double_arr_size(arr, num_arr_elements, ele_size);
if (num_arr_elements == 0) {
fprintf(stderr, "failed to allocate enough space for all json elements in your file.\n");
goto fail;
} else {
/* reset the array element position in case the pointer changed. */
arr_idx_pointer = ((char *)*arr) + arr_elements_used * ele_size;
}
}
continue;
} else {
i++;
values++;
continue;
}
}
if (arr_elements_used == 0) {
goto fail;
}
free(values_head);
free(file_data);
return arr_elements_used;
fail:
free(values_head);
free(file_data);
free(*arr);
*arr = NULL;
return 0;
}
static int
fuzz_parse_json_num(struct spdk_json_val *val, uint64_t max_val, uint64_t *val_ptr)
{
uint64_t tmp_val;
int rc;
rc = spdk_json_number_to_uint64(val, &tmp_val);
if (rc || tmp_val > max_val) {
return -EINVAL;
} else {
*val_ptr = tmp_val;
return 0;
}
}