Initial TrustInSoft CI configuration

This commit is contained in:
guillaumemillot 2020-10-07 16:46:50 +02:00 committed by Jakub Zwolakowski
parent d2735278ed
commit 11de03fbd2
7 changed files with 619 additions and 0 deletions

View File

@ -536,6 +536,9 @@ cJSON is written in ANSI C (or C89, C90). If your compiler or C library doesn't
NOTE: ANSI C is not C++ therefore it shouldn't be compiled with a C++ compiler. You can compile it with a C compiler and link it with your C++ code however. Although compiling with a C++ compiler might work, correct behavior is not guaranteed.
Absence of Undefined Behaviors on the test suite guaranteed by [TrustInSoft CI](https://ci.trust-in-soft.com/projects/DaveGamble/cJSON/latest):
[![TrustInSoft CI](https://ci.trust-in-soft.com/projects/DaveGamble/cJSON.svg)](https://ci.trust-in-soft.com/projects/DaveGamble/cJSON)
#### Floating Point Numbers
cJSON does not officially support any `double` implementations other than IEEE754 double precision floating point numbers. It might still work with other implementations but bugs with these will be considered invalid.

View File

@ -640,7 +640,9 @@ static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
ptr1 = item1->valuestring;
return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), long_valuestring);
TEST_ASSERT_NOT_NULL(return_value);
#ifndef __TRUSTINSOFT_ANALYZER__ /* ptr1 was already freed, comparing it with another pointer is Undefined Behavior */
TEST_ASSERT_NOT_EQUAL_MESSAGE(ptr1, return_value, "new valuestring longer than old should reallocate memory")
#endif /* __TRUSTINSOFT_ANALYZER__ */
TEST_ASSERT_EQUAL_STRING(long_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "two"), long_valuestring);

View File

@ -34,7 +34,12 @@ static void parse_hex4_should_parse_all_combinations(void)
unsigned char digits_lower[6];
unsigned char digits_upper[6];
/* test all combinations */
#if defined(__TRUSTINSOFT_ANALYZER__)
/* Reduce the test's size for TIS CI. */
for (number = 0; number <= 0xFFF; number++)
#else
for (number = 0; number <= 0xFFFF; number++)
#endif
{
TEST_ASSERT_EQUAL_INT_MESSAGE(4, sprintf((char*)digits_lower, "%.4x", number), "sprintf failed.");
TEST_ASSERT_EQUAL_INT_MESSAGE(4, sprintf((char*)digits_upper, "%.4X", number), "sprintf failed.");

233
tis.config Normal file
View File

@ -0,0 +1,233 @@
[
{
"name": "cjson_add.c",
"files": [
"tests/cjson_add.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "compare_tests.c",
"files": [
"tests/compare_tests.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "json_patch_tests.c",
"files": [
"tests/json_patch_tests.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "minify_tests.c",
"files": [
"tests/minify_tests.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "misc_tests.c",
"files": [
"tests/misc_tests.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "misc_utils_tests.c",
"files": [
"tests/misc_utils_tests.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "old_utils_tests.c",
"files": [
"tests/old_utils_tests.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "parse_array.c",
"files": [
"tests/parse_array.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "parse_examples.c",
"files": [
"tests/parse_examples.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "parse_hex4.c",
"files": [
"tests/parse_hex4.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "parse_number.c",
"files": [
"tests/parse_number.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "parse_object.c",
"files": [
"tests/parse_object.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "parse_string.c",
"files": [
"tests/parse_string.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "parse_value.c",
"files": [
"tests/parse_value.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "parse_with_opts.c",
"files": [
"tests/parse_with_opts.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "print_array.c",
"files": [
"tests/print_array.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "print_number.c",
"files": [
"tests/print_number.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "print_object.c",
"files": [
"tests/print_object.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "print_string.c",
"files": [
"tests/print_string.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "print_value.c",
"files": [
"tests/print_value.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "readme_examples.c",
"files": [
"tests/readme_examples.c"
],
"include": "trustinsoft/common.config"
},
{
"name": "afl.c test1",
"val-args": " fuzzing/inputs/test1",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test10",
"val-args": " fuzzing/inputs/test10",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test11",
"val-args": " fuzzing/inputs/test11",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test2",
"val-args": " fuzzing/inputs/test2",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test3",
"val-args": " fuzzing/inputs/test3",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test3.bu",
"val-args": " fuzzing/inputs/test3.bu",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test3.uf",
"val-args": " fuzzing/inputs/test3.uf",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test3.uu",
"val-args": " fuzzing/inputs/test3.uu",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test4",
"val-args": " fuzzing/inputs/test4",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test5",
"val-args": " fuzzing/inputs/test5",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test6",
"val-args": " fuzzing/inputs/test6",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test7",
"val-args": " fuzzing/inputs/test7",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test8",
"val-args": " fuzzing/inputs/test8",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
},
{
"name": "afl.c test9",
"val-args": " fuzzing/inputs/test9",
"include": "trustinsoft/common.config",
"include": "trustinsoft/fuzz.config"
}
]

112
trustinsoft/common.config Normal file
View File

@ -0,0 +1,112 @@
{
"files": [
"../cJSON_Utils.c",
"../tests/unity/src/unity.c"
],
"compilation_cmd": "-DUNITY_EXCLUDE_SETJMP_H",
"val-clone-on-recursive-calls-max-depth": 10000,
"filesystem": {
"files": [
{
"name": "json-patch-tests/cjson-utils-tests.json",
"from": "../tests/json-patch-tests/cjson-utils-tests.json"
},
{
"name": "json-patch-tests/package.json",
"from": "../tests/json-patch-tests/package.json"
},
{
"name": "json-patch-tests/spec_tests.json",
"from": "../tests/json-patch-tests/spec_tests.json"
},
{
"name": "json-patch-tests/tests.json",
"from": "../tests/json-patch-tests/tests.json"
},
{
"name": "inputs/test1",
"from": "../tests/inputs/test1"
},
{
"name": "inputs/test1.expected",
"from": "../tests/inputs/test1.expected"
},
{
"name": "inputs/test10",
"from": "../tests/inputs/test10"
},
{
"name": "inputs/test10.expected",
"from": "../tests/inputs/test10.expected"
},
{
"name": "inputs/test11",
"from": "../tests/inputs/test11"
},
{
"name": "inputs/test11.expected",
"from": "../tests/inputs/test11.expected"
},
{
"name": "inputs/test2",
"from": "../tests/inputs/test2"
},
{
"name": "inputs/test2.expected",
"from": "../tests/inputs/test2.expected"
},
{
"name": "inputs/test3",
"from": "../tests/inputs/test3"
},
{
"name": "inputs/test3.expected",
"from": "../tests/inputs/test3.expected"
},
{
"name": "inputs/test4",
"from": "../tests/inputs/test4"
},
{
"name": "inputs/test4.expected",
"from": "../tests/inputs/test4.expected"
},
{
"name": "inputs/test5",
"from": "../tests/inputs/test5"
},
{
"name": "inputs/test5.expected",
"from": "../tests/inputs/test5.expected"
},
{
"name": "inputs/test6",
"from": "../tests/inputs/test6"
},
{
"name": "inputs/test7",
"from": "../tests/inputs/test7"
},
{
"name": "inputs/test7.expected",
"from": "../tests/inputs/test7.expected"
},
{
"name": "inputs/test8",
"from": "../tests/inputs/test8"
},
{
"name": "inputs/test8.expected",
"from": "../tests/inputs/test8.expected"
},
{
"name": "inputs/test9",
"from": "../tests/inputs/test9"
},
{
"name": "inputs/test9.expected",
"from": "../tests/inputs/test9.expected"
}
]
}
}

66
trustinsoft/fuzz.config Normal file
View File

@ -0,0 +1,66 @@
{
"files": [
"../cJSON.c",
"../fuzzing/afl.c"
],
"filesystem": {
"files": [
{
"name": "fuzzing/inputs/test1",
"from": "../fuzzing/inputs/test1"
},
{
"name": "fuzzing/inputs/test10",
"from": "../fuzzing/inputs/test10"
},
{
"name": "fuzzing/inputs/test11",
"from": "../fuzzing/inputs/test11"
},
{
"name": "fuzzing/inputs/test2",
"from": "../fuzzing/inputs/test2"
},
{
"name": "fuzzing/inputs/test3",
"from": "../fuzzing/inputs/test3"
},
{
"name": "fuzzing/inputs/test3.bu",
"from": "../fuzzing/inputs/test3.bu"
},
{
"name": "fuzzing/inputs/test3.uf",
"from": "../fuzzing/inputs/test3.uf"
},
{
"name": "fuzzing/inputs/test3.uu",
"from": "../fuzzing/inputs/test3.uu"
},
{
"name": "fuzzing/inputs/test4",
"from": "../fuzzing/inputs/test4"
},
{
"name": "fuzzing/inputs/test5",
"from": "../fuzzing/inputs/test5"
},
{
"name": "fuzzing/inputs/test6",
"from": "../fuzzing/inputs/test6"
},
{
"name": "fuzzing/inputs/test7",
"from": "../fuzzing/inputs/test7"
},
{
"name": "fuzzing/inputs/test8",
"from": "../fuzzing/inputs/test8"
},
{
"name": "fuzzing/inputs/test9",
"from": "../fuzzing/inputs/test9"
}
]
}
}

198
trustinsoft/regenerate.py Normal file
View File

@ -0,0 +1,198 @@
#! /usr/bin/env python3
# This script regenerates TrustInSoft CI configuration.
# Run from the root of the cJSON project:
# $ python3 trustinsoft/regenerate.py
import re # sub
import json # dumps, load
from os import path # basename, isdir, join
import glob # iglob
# Outputting JSON.
def string_of_json(obj):
# Output standard pretty-printed JSON (RFC 7159) with 4-space indentation.
s = json.dumps(obj, indent=4)
# Sometimes we need to have multiple "include" fields in the outputted
# JSON, which is unfortunately impossible in the internal python
# representation (OK, it is technically possible, but too cumbersome to
# bother implementing it here), so we can name these fields 'include_',
# 'include__', etc, and they are all converted to 'include' before
# outputting as JSON.
s = re.sub(r'"include_+"', '"include"', s)
return s
# Make a command line from a dictionary of lists.
def string_of_options(options):
elts = []
for opt_prefix in options: # e.g. opt_prefix == "-D"
for opt_value in options[opt_prefix]: # e.g. opt_value == "HAVE_OPEN"
elts.append(opt_prefix + opt_value) # e.g. "-DHAVE_OPEN"
return " ".join(elts)
# Directories.
test_files_dir = "tests"
fuzz_input_dir = path.join("fuzzing", "inputs")
# --------------------------------------------------------------------------- #
# ---------------------------------- CHECKS --------------------------------- #
# --------------------------------------------------------------------------- #
def check_dir(dir):
if path.isdir(dir):
print(" > OK! Directory '%s' exists." % dir)
else:
exit("Directory '%s' not found." % dir)
# Initial check.
print("1. Check if all necessary directories and files exist...")
check_dir("trustinsoft")
check_dir(test_files_dir)
check_dir(fuzz_input_dir)
# --------------------------------------------------------------------------- #
# -------------------- GENERATE trustinsoft/common.config ------------------- #
# --------------------------------------------------------------------------- #
common_config_path = path.join("trustinsoft", "common.config")
def make_common_config():
# C files.
c_files = [
"cJSON_Utils.c",
path.join("tests", "unity", "src", "unity.c"),
]
# Compilation options.
compilation_cmd = (
{
"-I": [],
"-D": [
"UNITY_EXCLUDE_SETJMP_H"
],
"-U": [],
}
)
# Filesystem.
json_patch_tests = list(
map(lambda file:
{
"name": path.join("json-patch-tests", path.basename(file)),
"from": path.join("..", file),
},
sorted(glob.iglob(path.join("tests", "json-patch-tests", "*.json"),
recursive=False)))
)
tests_and_expected = list(
map(lambda file:
{
"name": path.join("inputs", path.basename(file)),
"from": path.join("..", file),
},
sorted(glob.iglob(path.join("tests", "inputs", "test*"),
recursive=False)))
)
# Whole common.config JSON.
config = (
{
"files": list(map(lambda file: path.join("..", file), c_files)),
"compilation_cmd": string_of_options(compilation_cmd),
"val-clone-on-recursive-calls-max-depth": 10000,
"filesystem": { "files": json_patch_tests + tests_and_expected },
}
)
# Done.
return config
common_config = make_common_config()
with open(common_config_path, "w") as file:
print("2. Generate the '%s' file." % common_config_path)
file.write(string_of_json(common_config))
# --------------------------------------------------------------------------- #
# -------------------- GENERATE trustinsoft/fuzz.config --------------------- #
# --------------------------------------------------------------------------- #
fuzz_config_path = path.join("trustinsoft", "fuzz.config")
def make_fuzz_config():
# C files.
c_files = [
"cJSON.c",
path.join("fuzzing", "afl.c"),
]
# Filesystem.
fuzzing_files = list(
map(lambda file:
{
"name": path.join(fuzz_input_dir, path.basename(file)),
"from": path.join("..", file),
},
sorted(glob.iglob(path.join(fuzz_input_dir, "test*"),
recursive=False)))
)
# Whole fuzz.config JSON.
config = (
{
"files": list(map(lambda file: path.join("..", file), c_files)),
"filesystem": { "files": fuzzing_files },
}
)
# Done.
return config
fuzz_config = make_fuzz_config()
with open(fuzz_config_path, "w") as file:
print("3. Generate the '%s' file." % fuzz_config_path)
file.write(string_of_json(fuzz_config))
# --------------------------------------------------------------------------- #
# -------------------------------- tis.config ------------------------------- #
# --------------------------------------------------------------------------- #
exclude_tests = [
"unity_setup.c"
]
def test_files():
test_files = sorted(
glob.iglob(path.join(test_files_dir, "*.c"), recursive=False)
)
for exclude_test in exclude_tests:
test_files.remove(path.join("tests", exclude_test))
return test_files
def make_test(test_file):
basename = path.basename(test_file)
return (
{
"name": basename,
"files": [ test_file ],
"include": common_config_path,
}
)
def fuzz_input_files():
return sorted(
glob.iglob(path.join(fuzz_input_dir, "test*"), recursive=False)
)
def make_fuzz_test(fuzz_input_file):
basename = path.basename(fuzz_input_file)
return (
{
"name": ("afl.c " + basename),
"val-args": " " + path.join(fuzz_input_dir, basename),
"include": common_config_path,
"include_": fuzz_config_path,
}
)
tis_config = (
list(map(make_test, test_files())) +
list(map(make_fuzz_test, fuzz_input_files()))
)
with open("tis.config", "w") as file:
print("4. Generate the 'tis.config' file.")
file.write(string_of_json(tis_config))