windows-binary-fuzzing/transforms/initialize_stack_driver.cpp
2025-02-26 18:48:49 +01:00

150 lines
4.6 KiB
C++
Executable File

#include "initialize_stack.hpp"
#include <getopt.h>
using namespace std;
using namespace IRDB_SDK;
using namespace InitStack;
//
// Print usage info
//
void usage(char *p_name) {
cerr << "Usage: " << p_name << " <variant_id>\n";
cerr << "\t[--functions <file> | -f <file>] Read in the functions to "
"auto-initialize "
<< endl;
cerr << "\t[--initvalue <value> | -i <value>] Specify stack "
"initialization value (default=0)"
<< endl;
cerr << "\t[--verbose | -v] Verbose mode "
" "
<< endl;
cerr << "\t[--help,--usage,-?,-h] Display this message "
" "
<< endl;
}
//
// The entry point for a stand-alone executable transform.
// Note: Thanos-enabled transforms are easier to write, faster to execute, and
// generally preferred. Stand-alone transforms may be useful if the transform
// has issues with memory leaks and/or memory errors. Memory issues in a stand
// alone transform cannot affect correctness of other transforms.
//
int main(int argc, char **argv) {
//
// Sanity check that the command line has at least a variant ID, otherwise we
// won't know what variant to operate on.
//
if (argc < 2) {
usage(argv[0]);
exit(1);
}
// constant parameters read from argv
const auto program_name = string(argv[0]);
const auto variantID = atoi(argv[1]);
// initial values of parameters to parse
auto verbose = false;
auto funcs_filename = string();
auto init_value = 0;
// declare some options for the transform
const char *short_opts = "f:i:v?h";
struct option long_options[] = {{"functions", required_argument, 0, 'f'},
{"initvalue", required_argument, 0, 'i'},
{"verbose", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{"usage", no_argument, 0, '?'},
{0, 0, 0, 0}};
// parse the options in a standard getopts_long loop
while (true) {
int c = getopt_long(argc, argv, short_opts, long_options, nullptr);
if (c == -1)
break;
switch (c) {
case 'f':
funcs_filename = optarg;
cout << "Reading file with function specifiers: " << funcs_filename
<< endl;
break;
case 'i':
init_value = strtoll(optarg, NULL, 0);
cout << " Stack initialization value: " << hex << init_value << endl;
break;
case 'v':
verbose = true;
break;
case '?':
case 'h':
usage(argv[0]);
exit(1);
break;
default:
break;
}
}
// stand alone transforms must setup the interface to the sql server
auto pqxx_interface = pqxxDB_t::factory();
BaseObj_t::setInterface(pqxx_interface.get());
// stand alone transforms must create and read a variant ID from the database
auto pidp = VariantID_t::factory(variantID);
assert(pidp->isRegistered() == true);
// stand alone transforms must create and read the main file's IR from the
// datatbase
auto this_file = pidp->getMainFile();
auto url = this_file->getURL();
// declare for later so we can return the right value
auto success = false;
// now try to load the IR and execute a transform
try {
// Create and download the file's IR.
// Note: this is achieved differently with thanos-enabled plugins
auto firp = FileIR_t::factory(pidp.get(), this_file);
// sanity
assert(firp && pidp);
// log
cout << "Transforming " << this_file->getURL() << endl;
// create and invoke the transform
InitStack_t is(firp.get(), funcs_filename, init_value, verbose);
success = is.execute();
// conditionally write the IR back to the database on success
if (success) {
cout << "Writing changes for " << url << endl;
// Stand alone trnasforms must manually write the IR back to the IRDB and
// commit the transactions
firp->writeToDB();
// and commit the the transaction to postgres
pqxx_interface->commit();
} else {
cout << "Skipping write back on failure. " << url << endl;
}
} catch (const DatabaseError_t &db_error) {
// log any databse errors that might come up in the transform process
cerr << program_name << ": Unexpected database error: " << db_error
<< "file url: " << url << endl;
} catch (...) {
// log any other errors
cerr << program_name << ": Unexpected error file url: " << url << endl;
}
//
// return success code to driver (as a shell-style return value). 0=success,
// 1=warnings, 2=errors
//
return success ? 0 : 2;
}