| 1920 | } |
| 1921 | |
| 1922 | static void test_fuzzing(testing & t) { |
| 1923 | const int num_iterations = JINJA_FUZZ_ITERATIONS; |
| 1924 | const unsigned int seed = 42; // fixed seed for reproducibility |
| 1925 | std::mt19937 rng(seed); |
| 1926 | |
| 1927 | // Distribution helpers |
| 1928 | std::uniform_int_distribution<int> choice_dist(0, 100); |
| 1929 | std::uniform_int_distribution<int> int_dist(-1000, 1000); |
| 1930 | std::uniform_int_distribution<size_t> idx_dist(0, 1000); |
| 1931 | |
| 1932 | // Template fragments for fuzzing |
| 1933 | const std::vector<std::string> var_names = { |
| 1934 | "x", "y", "z", "arr", "obj", "items", "foo", "bar", "undefined_var", |
| 1935 | "none", "true", "false", "None", "True", "False" |
| 1936 | }; |
| 1937 | const std::vector<std::string> filters = { |
| 1938 | "length", "first", "last", "reverse", "sort", "unique", "join", "upper", "lower", |
| 1939 | "trim", "default", "tojson", "string", "int", "float", "abs", "list", "dictsort" |
| 1940 | }; |
| 1941 | const std::vector<std::string> builtins = { |
| 1942 | "range", "len", "dict", "list", "join", "str", "int", "float", "namespace" |
| 1943 | }; |
| 1944 | |
| 1945 | t.test("out of bound array access", [&](testing & t) { |
| 1946 | for (int i = 0; i < num_iterations; ++i) { |
| 1947 | int idx = int_dist(rng); |
| 1948 | std::string tmpl = "{{ arr[" + std::to_string(idx) + "] }}"; |
| 1949 | json vars = {{"arr", json::array({1, 2, 3})}}; |
| 1950 | t.assert_true("should not crash", fuzz_test_template(tmpl, vars)); |
| 1951 | } |
| 1952 | }); |
| 1953 | |
| 1954 | t.test("non-existing variables", [&](testing & t) { |
| 1955 | for (int i = 0; i < num_iterations; ++i) { |
| 1956 | std::string var = random_string(rng, 20); |
| 1957 | std::string tmpl = "{{ " + var + " }}"; |
| 1958 | json vars = json::object(); // empty context |
| 1959 | t.assert_true("should not crash", fuzz_test_template(tmpl, vars)); |
| 1960 | } |
| 1961 | }); |
| 1962 | |
| 1963 | t.test("non-existing nested attributes", [&](testing & t) { |
| 1964 | for (int i = 0; i < num_iterations; ++i) { |
| 1965 | std::string var1 = var_names[choice_dist(rng) % var_names.size()]; |
| 1966 | std::string var2 = random_string(rng, 10); |
| 1967 | std::string var3 = random_string(rng, 10); |
| 1968 | std::string tmpl = "{{ " + var1 + "." + var2 + "." + var3 + " }}"; |
| 1969 | json vars = {{var1, {{"other", 123}}}}; |
| 1970 | t.assert_true("should not crash", fuzz_test_template(tmpl, vars)); |
| 1971 | } |
| 1972 | }); |
| 1973 | |
| 1974 | t.test("invalid filter arguments", [&](testing & t) { |
| 1975 | for (int i = 0; i < num_iterations; ++i) { |
| 1976 | std::string filter = filters[choice_dist(rng) % filters.size()]; |
| 1977 | int val = int_dist(rng); |
| 1978 | std::string tmpl = "{{ " + std::to_string(val) + " | " + filter + " }}"; |
| 1979 | json vars = json::object(); |
nothing calls this directly
no test coverage detected