1 // -*- mode: C++ -*-
2 //
3 // Copyright (c) 2007, 2008, 2009, 2010, 2011, 2015, 2017 The University of Utah
4 // All rights reserved.
5 //
6 // This file is part of `csmith', a random generator of C programs.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are met:
10 //
11 //   * Redistributions of source code must retain the above copyright notice,
12 //     this list of conditions and the following disclaimer.
13 //
14 //   * Redistributions in binary form must reproduce the above copyright
15 //     notice, this list of conditions and the following disclaimer in the
16 //     documentation and/or other materials provided with the distribution.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 
30 #if HAVE_CONFIG_H
31 #  include <config.h>
32 #endif
33 
34 #include "DFSRndNumGenerator.h"
35 
36 #include <cassert>
37 #include <iostream>
38 #include <sstream>
39 
40 #include "CGOptions.h"
41 #include "Filter.h"
42 #include "SequenceFactory.h"
43 #include "Sequence.h"
44 #include "Error.h"
45 #include "SequenceLineParser.h"
46 
47 // Represents the data for each random choice
48 class DFSRndNumGenerator::SearchState
49 {
50 public:
51 	explicit SearchState(int index);
52 	SearchState(const SearchState &s);
53 	~SearchState();
54 
55 	void initSearchState(bool init, int value, int bound);
56 	void dump(const string &where);
57 
58 	// getters and setters
init()59 	bool init() { return init_; }
set_init(bool init)60 	void set_init(bool init) { init_ = init; }
61 
value()62 	int value() { return value_; }
set_value(int value)63 	void set_value(int value) { value_ = value; }
inc_value(void)64 	void inc_value(void) { ++value_; }
65 
bound()66 	int bound() { return bound_; }
set_bound(int bound)67 	void set_bound(int bound) { bound_ = bound; }
68 
index()69 	int index() { return index_; }
70 
71 private:
72 	// Whether this state has been initialized
73 	bool init_;
74 	// Current value from 0...(bound - 1)
75 	int value_;
76 
77 	int bound_;
78 
79 	int index_;
80 };
81 
82 /*
83  *
84  */
SearchState(int index)85 DFSRndNumGenerator::SearchState::SearchState(int index)
86 	: init_(false),
87 	  value_(0),
88 	  bound_(0),
89 	  index_(index)
90 {
91 	// Nothing to do
92 }
93 
SearchState(const DFSRndNumGenerator::SearchState & state)94 DFSRndNumGenerator::SearchState::SearchState(const DFSRndNumGenerator::SearchState &state)
95 	: init_(state.init_),
96 	  value_(state.value_),
97 	  bound_(state.bound_),
98 	  index_(state.index_)
99 {
100 
101 }
102 /*
103  *
104  */
~SearchState()105 DFSRndNumGenerator::SearchState::~SearchState()
106 {
107 	// Nothing to do
108 }
109 
110 /*
111  *
112  */
113 void
initSearchState(bool init,int value,int bound)114 DFSRndNumGenerator::SearchState::initSearchState(bool init, int value, int bound)
115 {
116 	init_ = init;
117 	value_ = value;
118 	bound_ = bound;
119 }
120 
121 #define DEBUG
122 #ifdef DEBUG
dump(const string & where)123 void DFSRndNumGenerator::SearchState::dump(const string &where)
124 {
125 	cout << "[state]" << where << ", index = " << index_ << ", init = " << init_ << ", value = " << value_ << ", bound = " \
126 		<< bound_ << std::endl;
127 }
128 #else
dump(const string &)129 void DFSRndNumGenerator::SearchState::dump(const string &)
130 {
131 }
132 #endif
133 // ----------------------------------------------------------------------------------------------
134 
135 DFSRndNumGenerator *DFSRndNumGenerator::impl_ = 0;
136 
DFSRndNumGenerator(Sequence * concrete_seq)137 DFSRndNumGenerator::DFSRndNumGenerator(Sequence *concrete_seq)
138 	: trace_string_(""),
139 	  decision_depth_(-1),
140 	  current_pos_(-1),
141 	  all_done_(false),
142 	  seq_(concrete_seq),
143 	  use_debug_sequence_(false)
144 {
145 	init_states(CGOptions::max_exhaustive_depth());
146 }
147 
~DFSRndNumGenerator()148 DFSRndNumGenerator::~DFSRndNumGenerator()
149 {
150 	std::vector<DFSRndNumGenerator::SearchState *>::iterator i;
151 	for (i = states_.begin(); i != states_.end(); ++i) {
152 		delete (*i);
153 	}
154 	states_.clear();
155 	SequenceFactory::destroy_sequences();
156 }
157 
158 /*
159  * Singleton
160  */
161 DFSRndNumGenerator*
make_rndnum_generator()162 DFSRndNumGenerator::make_rndnum_generator()
163 {
164 	if (impl_)
165 		return impl_;
166 
167 	Sequence *seq = SequenceFactory::make_sequence();
168 
169 	impl_ = new DFSRndNumGenerator(seq);
170 
171 	assert(impl_);
172 
173 	std::string debug_sequence = CGOptions::dfs_debug_sequence();
174 	if (!debug_sequence.empty()) {
175 		std::vector<int> nums;
176 		if (!SequenceLineParser<vector<int> >::parse_sequence(nums, debug_sequence, SequenceFactory::current_sep_char())) {
177 			assert("dfs debugging sequence error!" && 0);
178 		}
179 		impl_->initialize_sequence(nums);
180 		impl_->use_debug_sequence_ = true;
181 	}
182 
183 	return impl_;
184 }
185 
186 void
initialize_sequence(const vector<int> & v)187 DFSRndNumGenerator::initialize_sequence(const vector<int> &v)
188 {
189 	size_t i = 0;
190 	for (i = 0; i < v.size(); i++) {
191 		seq_->add_number(v[i], 0, i);
192 	}
193 }
194 
195 #ifdef DEBUG
196 void
dumpCurrentState(int bound,const string & where)197 DFSRndNumGenerator::dumpCurrentState(int bound, const string &where)
198 {
199 	cout << "[current]" << where << ", current_pos = " << current_pos_ \
200 		<< ", decision_depth = " << decision_depth_ << " , bound = " \
201 		<< bound << ", all_done = " << all_done_ << std::endl;
202 }
203 #else
204 void
dumpCurrentState(int,const string &)205 DFSRndNumGenerator::dumpCurrentState(int, const string &)
206 {
207 }
208 #endif
209 
210 /*
211  * invoked from DepthSpec.cpp.
212  * returning true means that we do eager backtracking.
213  */
214 bool
eager_backtracking(int depth_needed)215 DFSRndNumGenerator::eager_backtracking(int depth_needed)
216 {
217 	if (current_pos_ <= 0) {
218 		// all_done_ = true;
219 		// Error::set_error(BACKTRACKING_ERROR);
220 		// return true;
221 		return false;
222 	}
223 
224 	int max_depth = CGOptions::max_exhaustive_depth();
225 	int remain_depth = max_depth - current_pos_;
226 	if (remain_depth >= depth_needed)
227 		return false;
228 
229 	if (current_pos_ > decision_depth_) {
230 		Error::set_error(BACKTRACKING_ERROR);
231 		return true;
232 	}
233 
234 	// reset decision depth
235 	decision_depth_ = current_pos_;
236 	for (int i = current_pos_ + 1; i < max_depth; ++i)
237 		states_[i]->set_init(false);
238 
239 	Error::set_error(BACKTRACKING_ERROR);
240 	return true;
241 }
242 
243 int
revisit_node(DFSRndNumGenerator::SearchState * state,int local_current_pos,int bound,const Filter * filter,const string *)244 DFSRndNumGenerator::revisit_node(DFSRndNumGenerator::SearchState *state, int local_current_pos,
245 					int bound, const Filter *filter, const string *)
246 {
247 	int rv = state->value();
248 	if (filter) {
249 		if (rv >= bound) {
250 			state->dump("");
251 			dumpCurrentState(bound, "");
252 			cout << "rv = " << rv << ", bound = " << bound << std::endl;
253 			assert(0);
254 		}
255 
256 		filter->filter(rv);
257 
258 		ERROR_GUARD(-1);
259 
260 		assert(current_pos_ < CGOptions::max_exhaustive_depth());
261 
262 	}
263 	seq_->add_number(rv, bound, local_current_pos);
264 	return rv;
265 }
266 
267 bool
filter_invalid_nums(vector<int> * invalid_nums,int v)268 DFSRndNumGenerator::filter_invalid_nums(vector<int> *invalid_nums, int v)
269 {
270 	if (!invalid_nums)
271 		return false;
272 
273 	vector<int>::iterator i = find(invalid_nums->begin(), invalid_nums->end(), v);
274 	return (i != invalid_nums->end());
275 }
276 
277 int
random_choice(int bound,const Filter * filter,const string * where,vector<int> * invalid_nums)278 DFSRndNumGenerator::random_choice (int bound, const Filter *filter, const string *where, vector<int> *invalid_nums)
279 {
280 	int err = Error::get_error();
281 
282 	if (err == BACKTRACKING_ERROR) {
283 		return -1;
284 	}
285 	else if (err != SUCCESS) {
286 		assert("request random number in an error state. " && 0);
287 	}
288 
289 	++current_pos_;
290 	if (use_debug_sequence_) {
291 		int rv = seq_->get_number_by_pos(current_pos_);
292 		if (filter)
293 			filter->filter(rv);
294 		//cout << "current_pos _ = " << current_pos_ << ", length = " << seq_->sequence_length() << std::endl;
295 		if (static_cast<unsigned int>(current_pos_) >= seq_->sequence_length() - 1) {
296 			all_done_ = true;
297 		}
298 		return rv;
299 	}
300 
301 	int local_current_pos = current_pos_;
302 
303 	if (current_pos_ >= CGOptions::max_exhaustive_depth() ||
304 		decision_depth_ >= CGOptions::max_exhaustive_depth()) {
305 		Error::set_error(EXCEED_MAX_DEPTH_ERROR);
306 		return -1;
307 	}
308 
309 	DFSRndNumGenerator::SearchState *state = states_[current_pos_];
310 
311 	state->set_bound(bound);
312 	//dumpCurrentState(bound, "");
313 	//state->dump("");
314 
315 	// Revisit a node
316 	if (current_pos_ < decision_depth_ && state->init()) {
317 		return revisit_node(state, local_current_pos, bound, filter, where);
318 	}
319 
320 	if (state->init()) {
321 		int v = state->value();
322 		int local_decision_depth = decision_depth_;
323 		do { // Filter out invalid value
324 			++v;
325 			state->set_value(v);
326 			current_pos_ = local_current_pos;
327 			decision_depth_ = local_decision_depth;
328 			ERROR_GUARD(-1);
329 		} while (v < bound && ((filter && filter->filter(v)) || filter_invalid_nums(invalid_nums, v)));
330 
331 		state->set_value(v);
332 
333 		if (state->value() >= bound) { // backtracking
334 			current_pos_ = local_current_pos;
335 			for (int i = current_pos_; i < CGOptions::max_exhaustive_depth(); ++i) {
336 				states_[i]->set_init(false);
337 			}
338 			--decision_depth_;
339 			if (decision_depth_ < 0)
340 				all_done_ = true;
341 			Error::set_error(BACKTRACKING_ERROR);
342 			return -1;
343 		}
344 		else { // switch branch
345 			ERROR_GUARD(-1);
346 
347 			int rv = state->value();
348 			seq_->add_number(rv, bound, local_current_pos);
349 			return rv;
350 		}
351 	}
352 	else { // First time to visit this node
353 		int v = 0;
354 
355 		++decision_depth_;
356 		state->initSearchState(true, v, bound);
357 
358 		while (v < bound && ((filter && (filter->filter(v))) || filter_invalid_nums(invalid_nums, v))) { // Filter out invalid value
359 			for (int i = decision_depth_; i < CGOptions::max_exhaustive_depth(); ++i) {
360 				states_[i]->set_value(0);
361 			}
362 			ERROR_GUARD(-1);
363 			decision_depth_ = current_pos_;
364 			current_pos_ = local_current_pos;
365 			++v;
366 		}
367 		decision_depth_ = current_pos_;
368 
369 		if (v >= bound) {
370 			current_pos_ = local_current_pos;
371 			for (int i = current_pos_; i < CGOptions::max_exhaustive_depth(); ++i) {
372 				states_[i]->set_init(false);
373 			}
374 			--decision_depth_;
375 			if (decision_depth_ < 0)
376 				all_done_ = true;
377 			Error::set_error(BACKTRACKING_ERROR);
378 			return -1;
379 		}
380 
381 		state->set_value(v);
382 
383 		ERROR_GUARD(-1);
384 
385 		seq_->add_number(v, bound, local_current_pos);
386 		return v;
387 	}
388 }
389 
390 void
log_depth(int d,const string * where,const char * log)391 DFSRndNumGenerator::log_depth(int d, const string *where, const char *log)
392 {
393 	std::ostringstream ss1;
394 
395 	if (log)
396 		ss1 << "[" << log << "]";
397 
398 	if (where)
399 		ss1 << d << "(" << *where << ", pos = " << current_pos_ << ", current_decision_depth=" << decision_depth_ << ")->";
400 	else
401 		ss1 << d << "(..., pos = " << current_pos_ << ", current_decision_depth=" << decision_depth_ << ")->";
402 	trace_string_ += ss1.str();
403 }
404 
405 void
init_states(int size)406 DFSRndNumGenerator::init_states(int size)
407 {
408 	for (int i = 0; i < size; ++i) {
409 		DFSRndNumGenerator::SearchState *state = new SearchState(i);
410 		assert(state && "new SearchState: error!");
411 		states_.push_back(state);
412 	}
413 }
414 
415 void
reset_state(void)416 DFSRndNumGenerator::reset_state(void)
417 {
418 	current_pos_ = -1;
419 	trace_string_ = "";
420 	seq_->clear();
421 }
422 
423 /*
424  *
425  */
426 void
get_sequence(std::string & sequence)427 DFSRndNumGenerator::get_sequence(std::string &sequence)
428 {
429 	std::ostringstream ss;
430 	seq_->get_sequence(ss);
431 	sequence = ss.str();
432 }
433 
434 std::string
get_prefixed_name(const std::string & name)435 DFSRndNumGenerator::get_prefixed_name(const std::string &name)
436 {
437 	std::ostringstream ss;
438 	ss << "p_";
439 	seq_->get_sequence(ss);
440 	ss << seq_->get_sep_char() << name;
441 	return ss.str();
442 }
443 
444 /*
445  * Print the tracing information for debugging.
446  */
447 std::string &
trace_depth()448 DFSRndNumGenerator::trace_depth()
449 {
450 	return trace_string_;
451 }
452 
453 unsigned int
rnd_upto(const unsigned int n,const Filter * f,const std::string * where)454 DFSRndNumGenerator::rnd_upto(const unsigned int n, const Filter *f, const std::string *where)
455 {
456 	int x = random_choice(n, f, where);
457 	assert(x == -1 || (x >= 0 && x < static_cast<int>(n)));
458 	return x;
459 }
460 
461 bool
rnd_flipcoin(const unsigned int n,const Filter * f,const std::string * where)462 DFSRndNumGenerator::rnd_flipcoin(const unsigned int n, const Filter *f, const std::string *where)
463 {
464 	vector<int> invalid;
465 	int y;
466 	if (n == 100) {
467 		invalid.push_back(0);
468 		y = random_choice(2, f, where, &invalid);
469 	}
470 	else if (n == 0) {
471 		invalid.push_back(1);
472 		y = random_choice(2, f, where, &invalid);
473 	}
474 	else {
475 		y = random_choice(2, f, where);
476 	}
477 	assert(y == -1 || (y >= 0 && y < 2));
478 	return y;
479 }
480 
481 unsigned long
genrand(void)482 DFSRndNumGenerator::genrand(void)
483 {
484 	return AbsRndNumGenerator::genrand();
485 }
486 
487 std::string
RandomHexDigits(int num)488 DFSRndNumGenerator::RandomHexDigits( int num )
489 {
490 	return AbsRndNumGenerator::RandomHexDigits(num);
491 }
492 
493 std::string
RandomDigits(int num)494 DFSRndNumGenerator::RandomDigits( int num )
495 {
496 	return AbsRndNumGenerator::RandomDigits(num);
497 }
498 
499