Skip to content

Commit 0f74597

Browse files
committed
Limit when coverage happens to only one build target
1 parent f465d2c commit 0f74597

7 files changed

Lines changed: 417 additions & 26 deletions

File tree

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ matrix:
3030
compiler: gcc
3131
- os: linux
3232
sudo: false
33-
env: GCC_VER="5" CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE"
33+
env: GCC_VER="5" CPPCHECK=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE"
3434
compiler: gcc
3535
- os: linux
3636
sudo: false

CMakeLists.txt

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -314,32 +314,17 @@ if (RUN_FUZZY_TESTS)
314314
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/unittests")
315315

316316
execute_process(
317-
COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2016-06-29.tar.bz2
317+
COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2017-07-20.tar.bz2
318318
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittests
319319
)
320320

321321

322-
file(GLOB FUZZY_CRASH_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/crashes/id*)
323-
list(SORT FUZZY_CRASH_TESTS)
322+
file(GLOB FUZZY_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/MINIMIZED/*)
323+
list(SORT FUZZY_TESTS)
324324

325-
file(GLOB FUZZY_EXCEPTION_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/exceptions/id*)
326-
list(SORT FUZZY_EXCEPTION_TESTS)
327-
328-
329-
foreach(filename ${FUZZY_CRASH_TESTS})
330-
message(STATUS "Adding test ${filename}")
331-
add_test(${filename} chai "-e" ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/crashes/unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename})
332-
endforeach()
333-
334-
set_property(TEST ${FUZZY_CRASH_TESTS}
335-
PROPERTY ENVIRONMENT
336-
"CHAI_USE_PATH=${CMAKE_BINARY_DIR}/unittests/"
337-
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
338-
)
339-
340-
foreach(filename ${FUZZY_EXCEPTION_TESTS})
325+
foreach(filename ${FUZZY_TESTS})
341326
message(STATUS "Adding test ${filename}")
342-
add_test(${filename} chai "--exception" ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/exceptions/unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename})
327+
add_test(fuzz.${filename} chai "-e" "--exception" "--any-exception" ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzz_unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename})
343328
endforeach()
344329

345330
set_property(TEST ${FUZZY_EXCEPTION_TESTS}

src/libfuzzer_client.cpp

Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
// This file is distributed under the BSD License.
2+
// See "license.txt" for details.
3+
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4+
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
5+
// http://www.chaiscript.com
6+
7+
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
8+
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9+
10+
11+
#include <iostream>
12+
#include <list>
13+
#include <regex>
14+
15+
#ifdef _MSC_VER
16+
#define _CRT_SECURE_NO_WARNINGS
17+
#endif
18+
19+
#include <chaiscript/chaiscript.hpp>
20+
#include "../static_libs/chaiscript_parser.hpp"
21+
#include "../static_libs/chaiscript_stdlib.hpp"
22+
23+
24+
#ifdef READLINE_AVAILABLE
25+
#include <readline/readline.h>
26+
#include <readline/history.h>
27+
#else
28+
29+
char *mystrdup (const char *s) {
30+
size_t len = strlen(s); // Space for length plus nul
31+
char *d = static_cast<char*>(malloc (len+1));
32+
if (d == nullptr) { return nullptr; } // No memory
33+
#ifdef CHAISCRIPT_MSVC
34+
strcpy_s(d, len+1, s); // Copy the characters
35+
#else
36+
strncpy(d,s,len); // Copy the characters
37+
#endif
38+
d[len] = '\0';
39+
return d; // Return the new string
40+
}
41+
42+
char* readline(const char* p)
43+
{
44+
std::string retval;
45+
std::cout << p ;
46+
std::getline(std::cin, retval);
47+
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
48+
}
49+
50+
51+
void add_history(const char* /*unused*/){}
52+
void using_history(){}
53+
#endif
54+
55+
56+
57+
void *cast_module_symbol(std::vector<std::string> (*t_path)())
58+
{
59+
union cast_union
60+
{
61+
std::vector<std::string> (*in_ptr)();
62+
void *out_ptr;
63+
};
64+
65+
cast_union c;
66+
c.in_ptr = t_path;
67+
return c.out_ptr;
68+
}
69+
70+
std::vector<std::string> default_search_paths()
71+
{
72+
std::vector<std::string> paths;
73+
74+
#ifndef CHAISCRIPT_NO_DYNLOAD
75+
#ifdef CHAISCRIPT_WINDOWS // force no unicode
76+
CHAR path[4096];
77+
int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1);
78+
79+
std::string exepath(path, size);
80+
81+
size_t lastslash = exepath.rfind('\\');
82+
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
83+
if (lastslash != std::string::npos)
84+
{
85+
paths.push_back(exepath.substr(0, lastslash));
86+
}
87+
88+
if (secondtolastslash != std::string::npos)
89+
{
90+
return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"};
91+
}
92+
#else
93+
94+
std::string exepath;
95+
96+
std::vector<char> buf(2048);
97+
ssize_t size = -1;
98+
99+
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) >= 0)
100+
{
101+
exepath = std::string(&buf.front(), static_cast<size_t>(size));
102+
}
103+
104+
if (exepath.empty())
105+
{
106+
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0)
107+
{
108+
exepath = std::string(&buf.front(), static_cast<size_t>(size));
109+
}
110+
}
111+
112+
if (exepath.empty())
113+
{
114+
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0)
115+
{
116+
exepath = std::string(&buf.front(), static_cast<size_t>(size));
117+
}
118+
}
119+
120+
if (exepath.empty())
121+
{
122+
Dl_info rInfo;
123+
memset( &rInfo, 0, sizeof(rInfo) );
124+
if ( dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr ) {
125+
return paths;
126+
}
127+
128+
exepath = std::string(rInfo.dli_fname);
129+
}
130+
131+
size_t lastslash = exepath.rfind('/');
132+
133+
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
134+
if (lastslash != std::string::npos)
135+
{
136+
paths.push_back(exepath.substr(0, lastslash+1));
137+
}
138+
139+
if (secondtolastslash != std::string::npos)
140+
{
141+
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
142+
}
143+
#endif
144+
#endif // ifndef CHAISCRIPT_NO_DYNLOAD
145+
146+
return paths;
147+
}
148+
149+
void help(int n) {
150+
if ( n >= 0 ) {
151+
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>.\n";
152+
std::cout << "Additionally, you can inspect the runtime system using:\n";
153+
std::cout << " dump_system() - outputs all functions registered to the system\n";
154+
std::cout << " dump_object(x) - dumps information about the given symbol\n";
155+
} else {
156+
std::cout << "usage : chai [option]+\n";
157+
std::cout << "option:" << '\n';
158+
std::cout << " -h | --help" << '\n';
159+
std::cout << " -i | --interactive" << '\n';
160+
std::cout << " -c | --command cmd" << '\n';
161+
std::cout << " -v | --version" << '\n';
162+
std::cout << " - --stdin" << '\n';
163+
std::cout << " filepath" << '\n';
164+
}
165+
}
166+
167+
bool throws_exception(const std::function<void ()> &f)
168+
{
169+
try {
170+
f();
171+
} catch (...) {
172+
return true;
173+
}
174+
175+
return false;
176+
}
177+
178+
chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f)
179+
{
180+
try {
181+
f();
182+
} catch (const chaiscript::exception::eval_error &e) {
183+
return e;
184+
}
185+
186+
throw std::runtime_error("no exception throw");
187+
}
188+
189+
std::string get_next_command() {
190+
std::string retval("quit");
191+
if ( ! std::cin.eof() ) {
192+
char *input_raw = readline("eval> ");
193+
if ( input_raw != nullptr ) {
194+
add_history(input_raw);
195+
196+
std::string val(input_raw);
197+
size_t pos = val.find_first_not_of("\t \n");
198+
if (pos != std::string::npos)
199+
{
200+
val.erase(0, pos);
201+
}
202+
pos = val.find_last_not_of("\t \n");
203+
if (pos != std::string::npos)
204+
{
205+
val.erase(pos+1, std::string::npos);
206+
}
207+
208+
retval = val;
209+
210+
::free(input_raw);
211+
}
212+
}
213+
if( retval == "quit"
214+
|| retval == "exit"
215+
|| retval == "help"
216+
|| retval == "version")
217+
{
218+
retval += "(0)";
219+
}
220+
return retval;
221+
}
222+
223+
// We have to wrap exit with our own because Clang has a hard time with
224+
// function pointers to functions with special attributes (system exit being marked NORETURN)
225+
void myexit(int return_val) {
226+
exit(return_val);
227+
}
228+
229+
void interactive(chaiscript::ChaiScript_Basic& chai)
230+
{
231+
using_history();
232+
233+
for (;;) {
234+
std::string input = get_next_command();
235+
try {
236+
// evaluate input
237+
chaiscript::Boxed_Value val = chai.eval(input);
238+
239+
//Then, we try to print the result of the evaluation to the user
240+
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
241+
try {
242+
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << '\n';
243+
}
244+
catch (...) {} //If we can't, do nothing
245+
}
246+
}
247+
catch (const chaiscript::exception::eval_error &ee) {
248+
std::cout << ee.what();
249+
if ( !ee.call_stack.empty() ) {
250+
std::cout << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")";
251+
}
252+
std::cout << '\n';
253+
}
254+
catch (const std::exception &e) {
255+
std::cout << e.what();
256+
std::cout << '\n';
257+
}
258+
}
259+
}
260+
261+
double now()
262+
{
263+
using namespace std::chrono;
264+
auto now = high_resolution_clock::now();
265+
return duration_cast<duration<double>>(now.time_since_epoch()).count();
266+
}
267+
268+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
269+
chaiscript::ChaiScript chai;
270+
271+
chai.eval( R"chaiscript(
272+
def assert_equal(x, y)
273+
{
274+
if (x == y)
275+
{
276+
// Passes
277+
} else {
278+
// Fails
279+
print("assert_equal failure: got '" + to_string(y) + "' expected '" + to_string(x) + "'");
280+
// exit(-1);
281+
}
282+
}
283+
284+
def assert_false(f)
285+
{
286+
if (f)
287+
{
288+
print("assert_false failure");
289+
// exit(-1);
290+
}
291+
}
292+
293+
def assert_true(f)
294+
{
295+
if (!f)
296+
{
297+
print("assert_true failure");
298+
// exit(-1);
299+
}
300+
}
301+
302+
def assert_not_equal(x, y)
303+
{
304+
if (!(x == y))
305+
{
306+
// Passes
307+
} else {
308+
// Fails
309+
print("assert_not_equal failure: got " + to_string(y) + " which was not expected.");
310+
// exit(-1);
311+
}
312+
}
313+
314+
def assert_throws(desc, x)
315+
{
316+
if (throws_exception(x))
317+
{
318+
// Passes
319+
} else {
320+
// Fails
321+
print("assert_throws failure, function did not throw exception: " + to_string(desc));
322+
// exit(-1);
323+
}
324+
})chaiscript");
325+
326+
try {
327+
chai.eval(std::string(reinterpret_cast<const char *>(data), size));
328+
} catch (const chaiscript::exception::eval_error &ee) {
329+
std::cout << ee.pretty_print();
330+
std::cout << '\n';
331+
} catch (const chaiscript::Boxed_Value &e) {
332+
std::cout << "Unhandled exception thrown of type " << e.get_type_info().name() << '\n';
333+
} catch (const chaiscript::exception::load_module_error &e) {
334+
std::cout << "Unhandled module load error\n" << e.what() << '\n';
335+
} catch (const std::exception &e) {
336+
std::cout << "unhandled unknown exception: " << e.what() << '\n';
337+
}
338+
339+
return 0;
340+
}
341+
342+

0 commit comments

Comments
 (0)