Fix some json schema validation bugs
There were a couple of places where we would add null objects when
they were not allowed. Fix them.
Change-Id: I7c4c12ea1fa2913014e79603995267a9e560e288
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/tests/fuzz_cper_buf_to_ir.cpp b/tests/fuzz_cper_buf_to_ir.cpp
index 586c2ba..4baef7b 100644
--- a/tests/fuzz_cper_buf_to_ir.cpp
+++ b/tests/fuzz_cper_buf_to_ir.cpp
@@ -1,11 +1,28 @@
#include "libcper/cper-parse.h"
+#include "test-utils.hpp"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
json_object *ir = cper_buf_to_ir(data, size);
- if (ir != NULL) {
- json_object_put(ir);
+ if (ir == NULL) {
+ return 0;
}
+ char *str = strdup(json_object_to_json_string(ir));
+
+ nlohmann::json jsonData = nlohmann::json::parse(str, nullptr, false);
+ free(str);
+ assert(jsonData.is_discarded() == false);
+ std::string error_message;
+ static std::unique_ptr<valijson::Schema> schema =
+ load_schema(AddRequiredProps::NO, 0);
+
+ int valid = schema_validate_from_file(*schema, jsonData, error_message);
+ if (!valid) {
+ std::cout << "JSON: " << jsonData.dump(4) << std::endl;
+ std::cout << "Error: " << error_message << std::endl;
+ }
+ assert(valid);
+ json_object_put(ir);
return 0;
}
diff --git a/tests/ir-tests.cpp b/tests/ir-tests.cpp
index 97dad1b..d255353 100644
--- a/tests/ir-tests.cpp
+++ b/tests/ir-tests.cpp
@@ -194,13 +194,14 @@
//Validate against schema.
std::string error_message;
-
- int valid = schema_validate_from_file(LIBCPER_JSON_SPEC, jsonData,
- error_message);
+ std::unique_ptr<valijson::Schema> schema =
+ load_schema(AddRequiredProps::YES, single_section);
+ int valid = schema_validate_from_file(*schema, jsonData, error_message);
json_object_put(ir);
ASSERT_TRUE(valid)
<< "IR validation test failed (single section mode = "
- << single_section << ") with message: " << error_message;
+ << single_section << ") with message: " << error_message
+ << jsonData.dump(4) << "\n";
}
std::string to_hex(char *input, size_t size)
diff --git a/tests/meson.build b/tests/meson.build
index e86f26b..f65dc41 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -38,13 +38,14 @@
valijson_dep = valijson_proj.get_variable('valijson_dep')
endif
-sources = ['ir-tests.cpp', 'test-utils.cpp', 'base64_test.cpp']
+test_sources = ['test-utils.cpp', 'base64_test.cpp']
test_include_dirs = ['.', '../include']
cper_tests = executable(
'cper-tests',
- sources,
+ 'ir-tests.cpp',
+ test_sources,
implicit_include_directories: false,
include_directories: include_directories(test_include_dirs),
cpp_args: '-fpermissive',
@@ -74,7 +75,7 @@
foreach fuzzer_test : ['fuzz_cper_buf_to_ir']
fuzz_exe = executable(
fuzzer_test,
- [fuzzer_test + '.cpp'] + libcper_parse_sources + edk_sources,
+ [fuzzer_test + '.cpp'] + libcper_parse_sources + edk_sources + test_sources + libcper_generate_sources,
implicit_include_directories: false,
include_directories: include_directories(test_include_dirs),
cpp_args: fuzz_args,
diff --git a/tests/test-utils.cpp b/tests/test-utils.cpp
index 88f9d7d..b38b36c 100644
--- a/tests/test-utils.cpp
+++ b/tests/test-utils.cpp
@@ -28,6 +28,11 @@
{ "faultReason", "description" } },
{ "./sections/cper-cxl-component.json",
{ "cxlComponentEventLog" } },
+ { "./sections/cper-ia32x64-processor.json",
+ { "addressSpace", "errorType", "participationType",
+ "timedOut", "level", "operation", "preciseIP",
+ "restartableIP", "overflow", "uncorrected",
+ "transactionType" } },
};
nlohmann::json loadJson(const char *filePath)
@@ -121,22 +126,26 @@
}
// Document loader callback function
-const nlohmann::json *documentLoader(const std::string &uri)
+const nlohmann::json *documentLoader(const std::string &uri,
+ AddRequiredProps add_required_props)
{
// Load the schema from a file
- nlohmann::json *ref_schema = new nlohmann::json;
+ std::unique_ptr<nlohmann::json> ref_schema =
+ std::make_unique<nlohmann::json>();
*ref_schema = loadJson(uri.c_str());
if (ref_schema->is_discarded()) {
std::cerr << "Could not open schema file: " << uri << std::endl;
}
- std::vector<std::string> opt = {};
- const auto it_optional_file = optional_properties_map.find(uri);
- if (it_optional_file != optional_properties_map.end()) {
- opt = it_optional_file->second;
+ if (add_required_props == AddRequiredProps::YES) {
+ std::vector<std::string> opt = {};
+ const auto it_optional_file = optional_properties_map.find(uri);
+ if (it_optional_file != optional_properties_map.end()) {
+ opt = it_optional_file->second;
+ }
+ iterate_make_required_props(*ref_schema, opt);
}
- iterate_make_required_props(*ref_schema, opt);
- return ref_schema;
+ return ref_schema.release();
}
// Document release callback function
@@ -145,20 +154,19 @@
delete adapter; // Free the adapter memory
}
-int schema_validate_from_file(const char *schema_file_path,
- nlohmann::json &jsonData,
- std::string &error_message)
+std::unique_ptr<valijson::Schema>
+load_schema(AddRequiredProps add_required_props, int single_section)
{
// Load the schema
- nlohmann::json schema_root = loadJson(schema_file_path);
- if (schema_root.is_discarded()) {
- std::cerr << "Could not open schema file: " << schema_file_path
- << std::endl;
- return 0;
- }
+ fs::path pathObj(LIBCPER_JSON_SPEC);
- fs::path pathObj(schema_file_path);
- fs::path base_path = pathObj.parent_path();
+ if (single_section) {
+ pathObj /= "cper-json-section-log.json";
+ } else {
+ pathObj /= "cper-json-full-log.json";
+ }
+ nlohmann::json schema_root = loadJson(pathObj.c_str());
+ fs::path base_path(LIBCPER_JSON_SPEC);
try {
fs::current_path(base_path);
// std::cout << "Changed directory to: " << fs::current_path()
@@ -168,21 +176,31 @@
}
// Parse the json schema into an internal schema format
- valijson::Schema schema;
+ std::unique_ptr<valijson::Schema> schema =
+ std::make_unique<valijson::Schema>();
valijson::SchemaParser parser;
valijson::adapters::NlohmannJsonAdapter schemaDocumentAdapter(
schema_root);
// Set up callbacks for resolving external references
try {
- parser.populateSchema(schemaDocumentAdapter, schema,
- documentLoader, documentRelease);
+ parser.populateSchema(
+ schemaDocumentAdapter, *schema,
+ [add_required_props](const std::string &uri) {
+ return documentLoader(uri, add_required_props);
+ },
+ documentRelease);
} catch (std::exception &e) {
std::cerr << "Failed to parse schema: " << e.what()
<< std::endl;
- return 0;
}
+ return schema;
+}
+int schema_validate_from_file(const valijson::Schema &schema,
+ nlohmann::json &jsonData,
+ std::string &error_message)
+{
// Perform validation
valijson::Validator validator(valijson::Validator::kStrongTypes);
valijson::ValidationResults results;
diff --git a/tests/test-utils.hpp b/tests/test-utils.hpp
index 42e41bc..ec5f064 100644
--- a/tests/test-utils.hpp
+++ b/tests/test-utils.hpp
@@ -13,12 +13,23 @@
#include <libcper/generator/sections/gen-section.h>
}
+// Controls whether required properties are added to the majority of property
+// definitions. This is useful for unit tests that are validating JSON where
+// all fields are valid
+enum class AddRequiredProps { YES, NO };
+
FILE *generate_record_memstream(const char **types, UINT16 num_types,
char **buf, size_t *buf_size,
int single_section,
GEN_VALID_BITS_TEST_TYPE validBitsType);
-int schema_validate_from_file(const char *file_path, nlohmann::json &jsonData,
+
+std::unique_ptr<valijson::Schema>
+load_schema(AddRequiredProps add_required_props, int single_section);
+
+int schema_validate_from_file(const valijson::Schema &schema,
+ nlohmann::json &jsonData,
std::string &error_message);
+
nlohmann::json loadJson(const char *filePath);
#endif