2014-10-22 05:06:22 +00:00
|
|
|
// This file is part of BOINC.
|
|
|
|
// http://boinc.berkeley.edu
|
2020-08-01 23:00:10 +00:00
|
|
|
// Copyright (C) 2020 University of California
|
2014-10-22 05:06:22 +00:00
|
|
|
//
|
|
|
|
// BOINC is free software; you can redistribute it and/or modify it
|
|
|
|
// under the terms of the GNU Lesser General Public License
|
|
|
|
// as published by the Free Software Foundation,
|
|
|
|
// either version 3 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// BOINC is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
// See the GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2014-10-22 05:14:57 +00:00
|
|
|
// A validator that runs scripts to check and compare results,
|
2014-10-24 21:22:07 +00:00
|
|
|
// so that you can do your validation in Python, PHP, Perl, bash, etc.
|
2014-10-22 05:14:57 +00:00
|
|
|
//
|
2014-10-24 21:22:07 +00:00
|
|
|
// cmdline args to this program:
|
|
|
|
// --init_script "scriptname arg1 ... argn"
|
|
|
|
// --compare_script "scriptname arg1 ... argn"
|
2014-10-22 05:06:22 +00:00
|
|
|
//
|
2020-08-01 23:00:10 +00:00
|
|
|
// You must specify at least one.
|
|
|
|
//
|
2014-10-24 21:22:07 +00:00
|
|
|
// The init script checks the validity of a result,
|
|
|
|
// e.g. that the output files have the proper format.
|
2014-10-22 05:06:22 +00:00
|
|
|
// It returns zero if the files are valid
|
|
|
|
//
|
2014-10-24 21:22:07 +00:00
|
|
|
// The compare script compares two results.
|
|
|
|
// If returns zero if the output files are equivalent.
|
|
|
|
//
|
|
|
|
// arg1 ... argn represent cmdline args to be passed to the scripts.
|
|
|
|
// The options for init_script are:
|
|
|
|
//
|
|
|
|
// files list of paths of output files of the result
|
|
|
|
// result_id result ID
|
|
|
|
// runtime task runtime
|
|
|
|
//
|
|
|
|
// Additional options for compare_script, for the second result:
|
|
|
|
// files2 list of paths of output files
|
|
|
|
// result_id2 result ID
|
|
|
|
// runtime2 task runtime
|
|
|
|
//
|
|
|
|
// "arg1 ... argn" can be omitted,
|
|
|
|
// in which case only the output file paths are passed to the scripts.
|
2014-10-22 05:06:22 +00:00
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
|
|
|
|
#include "validate_util2.h"
|
|
|
|
#include "error_numbers.h"
|
|
|
|
#include "boinc_db.h"
|
|
|
|
#include "sched_util.h"
|
|
|
|
#include "validate_util.h"
|
|
|
|
#include "validator.h"
|
|
|
|
|
|
|
|
using std::string;
|
|
|
|
using std::vector;
|
|
|
|
|
2014-10-24 21:22:07 +00:00
|
|
|
vector<string> init_script, compare_script;
|
|
|
|
// first element is script path, other elements are args
|
2014-10-22 05:06:22 +00:00
|
|
|
|
2016-08-16 09:06:14 +00:00
|
|
|
int validate_handler_init(int argc, char** argv) {
|
|
|
|
// handle project specific arguments here
|
|
|
|
for (int i=1; i<argc; i++) {
|
|
|
|
if (is_arg(argv[i], "init_script")) {
|
|
|
|
init_script = split(argv[++i], ' ');
|
2014-10-24 21:22:07 +00:00
|
|
|
if (init_script.size() == 1) {
|
|
|
|
init_script.push_back(string("files"));
|
|
|
|
}
|
2016-08-16 09:06:14 +00:00
|
|
|
} else if (is_arg(argv[i], "compare_script")) {
|
|
|
|
compare_script = split(argv[++i], ' ');
|
2014-10-24 21:22:07 +00:00
|
|
|
if (compare_script.size() == 1) {
|
|
|
|
compare_script.push_back("files");
|
|
|
|
compare_script.push_back("files2");
|
|
|
|
}
|
2014-10-22 05:06:22 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-16 09:06:14 +00:00
|
|
|
|
2020-08-01 23:00:10 +00:00
|
|
|
if (init_script.empty() && compare_script.empty()) {
|
2014-10-22 05:06:22 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL,
|
2020-08-01 23:00:10 +00:00
|
|
|
"command line must specify init_script or compare_script\n"
|
2014-10-22 05:06:22 +00:00
|
|
|
);
|
2016-08-16 09:06:14 +00:00
|
|
|
return 1;
|
2014-10-22 05:06:22 +00:00
|
|
|
}
|
2016-08-16 09:06:14 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void validate_handler_usage() {
|
|
|
|
// describe the project specific arguments here
|
|
|
|
fprintf(stderr,
|
|
|
|
" A validator that runs scripts to check and compare results, \n"
|
|
|
|
" so that you can do your validation in Python, PHP, Perl, bash, etc.\n"
|
|
|
|
" Custom options:\n"
|
|
|
|
" --init_script \"scriptname arg1 ... argn\" checks the validity of a task,\n"
|
|
|
|
" e.g. that the output files have the proper format. Needs to exit with zero if the files are valid.\n"
|
|
|
|
" --compare_script \"scriptname arg1 ... argn\" compares two tasks. \n"
|
|
|
|
" Needs to return zero if the output files are equivalent.\n"
|
|
|
|
" See script_validator.cpp for more usage information.\n"
|
|
|
|
);
|
2014-10-22 05:06:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int init_result(RESULT& result, void*&) {
|
2020-08-01 23:00:10 +00:00
|
|
|
if (init_script.empty()) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-24 21:22:07 +00:00
|
|
|
unsigned int i, j;
|
|
|
|
char buf[256];
|
2014-10-22 05:06:22 +00:00
|
|
|
vector<string> paths;
|
|
|
|
int retval;
|
2020-08-01 23:00:10 +00:00
|
|
|
|
2014-10-22 05:06:22 +00:00
|
|
|
retval = get_output_file_paths(result, paths);
|
|
|
|
if (retval) {
|
|
|
|
fprintf(stderr, "get_output_file_paths() returned %d\n", retval);
|
|
|
|
return retval;
|
|
|
|
}
|
script_validator segfault fix
Current script_validator implementation contains next statements:
sprintf(cmd, "../bin/%s", init_script[0].c_str());
and
sprintf(cmd, "../bin/%s", compare_script[0].c_str());
It is dangerous to use this arrays
that are filled by parsing command line
without validating whether they contain any elements
and leads to next behavior:
Program received signal SIGSEGV, Segmentation fault.
0x000000000040f838 in compare_results (r1=..., r2=..., match=match@entry=@0x7ffffffb6c17: false) at script_validator.cpp:154
154 script_validator.cpp: No such file or directory.
(gdb) bt
#0 0x000000000040f838 in compare_results (r1=..., r2=..., match=match@entry=@0x7ffffffb6c17: false) at script_validator.cpp:154
#1 0x000000000040e85d in check_set (results=std::vector of length 2, capacity 2 = {...}, wu=..., canonicalid=@0x7ffffffb6dd0: 0,
retry=@0x7ffffffb6dcf: false) at validate_util2.cpp:134
#2 0x000000000040944e in handle_wu (validator=..., items=std::vector of length 3, capacity 4 = {...}) at validator.cpp:411
#3 0x000000000040a9f2 in do_validate_scan () at validator.cpp:730
#4 0x000000000040aae4 in main_loop () at validator.cpp:756
#5 0x00000000004039f6 in main (argc=5, argv=0x7fffffffdd48) at validator.cpp:929
This fix checks whether these arrays contain some elements
and output a readable error of missed inout parameter.
Signed-off-by: Vitalii Koshura <lestat.de.lionkur@gmail.com>
2018-07-20 12:21:10 +00:00
|
|
|
|
|
|
|
|
2014-10-22 05:06:22 +00:00
|
|
|
char cmd[4096];
|
2014-10-24 21:22:07 +00:00
|
|
|
sprintf(cmd, "../bin/%s", init_script[0].c_str());
|
|
|
|
for (i=1; i<init_script.size(); i++) {
|
|
|
|
string& s = init_script[i];
|
|
|
|
if (s == "files") {
|
|
|
|
for (j=0; j<paths.size(); j++) {
|
|
|
|
strcat(cmd, " ");
|
|
|
|
strcat(cmd, paths[j].c_str());
|
|
|
|
}
|
|
|
|
} else if (s == "runtime") {
|
|
|
|
sprintf(buf, " %f", result.elapsed_time);
|
|
|
|
strcat(cmd, buf);
|
|
|
|
} else if (s == "result_id") {
|
2015-07-23 17:11:08 +00:00
|
|
|
sprintf(buf, " %lu", result.id);
|
2014-10-24 21:22:07 +00:00
|
|
|
strcat(cmd, buf);
|
|
|
|
}
|
2014-10-22 05:06:22 +00:00
|
|
|
}
|
|
|
|
retval = system(cmd);
|
|
|
|
if (retval) {
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int compare_results(RESULT& r1, void*, RESULT const& r2, void*, bool& match) {
|
2020-08-01 23:00:10 +00:00
|
|
|
if (compare_script.empty()) {
|
|
|
|
match = true;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-24 21:22:07 +00:00
|
|
|
unsigned int i, j;
|
|
|
|
char buf[256];
|
2014-10-22 05:06:22 +00:00
|
|
|
vector<string> paths1, paths2;
|
|
|
|
int retval;
|
2020-08-01 23:00:10 +00:00
|
|
|
|
2014-10-22 05:06:22 +00:00
|
|
|
retval = get_output_file_paths(r1, paths1);
|
|
|
|
if (retval) {
|
|
|
|
fprintf(stderr, "get_output_file_paths() returned %d\n", retval);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
retval = get_output_file_paths(r2, paths2);
|
|
|
|
if (retval) {
|
|
|
|
fprintf(stderr, "get_output_file_paths() returned %d\n", retval);
|
|
|
|
return retval;
|
|
|
|
}
|
script_validator segfault fix
Current script_validator implementation contains next statements:
sprintf(cmd, "../bin/%s", init_script[0].c_str());
and
sprintf(cmd, "../bin/%s", compare_script[0].c_str());
It is dangerous to use this arrays
that are filled by parsing command line
without validating whether they contain any elements
and leads to next behavior:
Program received signal SIGSEGV, Segmentation fault.
0x000000000040f838 in compare_results (r1=..., r2=..., match=match@entry=@0x7ffffffb6c17: false) at script_validator.cpp:154
154 script_validator.cpp: No such file or directory.
(gdb) bt
#0 0x000000000040f838 in compare_results (r1=..., r2=..., match=match@entry=@0x7ffffffb6c17: false) at script_validator.cpp:154
#1 0x000000000040e85d in check_set (results=std::vector of length 2, capacity 2 = {...}, wu=..., canonicalid=@0x7ffffffb6dd0: 0,
retry=@0x7ffffffb6dcf: false) at validate_util2.cpp:134
#2 0x000000000040944e in handle_wu (validator=..., items=std::vector of length 3, capacity 4 = {...}) at validator.cpp:411
#3 0x000000000040a9f2 in do_validate_scan () at validator.cpp:730
#4 0x000000000040aae4 in main_loop () at validator.cpp:756
#5 0x00000000004039f6 in main (argc=5, argv=0x7fffffffdd48) at validator.cpp:929
This fix checks whether these arrays contain some elements
and output a readable error of missed inout parameter.
Signed-off-by: Vitalii Koshura <lestat.de.lionkur@gmail.com>
2018-07-20 12:21:10 +00:00
|
|
|
|
2014-10-22 05:06:22 +00:00
|
|
|
char cmd[4096];
|
2014-10-24 21:22:07 +00:00
|
|
|
sprintf(cmd, "../bin/%s", compare_script[0].c_str());
|
|
|
|
for (i=1; i<compare_script.size(); i++) {
|
|
|
|
string& s = compare_script[i];
|
|
|
|
if (s == "files") {
|
|
|
|
for (j=0; j<paths1.size(); j++) {
|
|
|
|
strcat(cmd, " ");
|
|
|
|
strcat(cmd, paths1[j].c_str());
|
|
|
|
}
|
|
|
|
} else if (s == "files2") {
|
|
|
|
for (j=0; j<paths2.size(); j++) {
|
|
|
|
strcat(cmd, " ");
|
|
|
|
strcat(cmd, paths2[j].c_str());
|
|
|
|
}
|
|
|
|
} else if (s == "runtime") {
|
|
|
|
sprintf(buf, " %f", r1.elapsed_time);
|
|
|
|
strcat(cmd, buf);
|
|
|
|
} else if (s == "result_id") {
|
2015-07-23 17:11:08 +00:00
|
|
|
sprintf(buf, " %lu", r1.id);
|
2014-10-24 21:22:07 +00:00
|
|
|
strcat(cmd, buf);
|
|
|
|
} else if (s == "runtime2") {
|
|
|
|
sprintf(buf, " %f", r2.elapsed_time);
|
|
|
|
strcat(cmd, buf);
|
|
|
|
} else if (s == "result_id2") {
|
2015-07-23 17:11:08 +00:00
|
|
|
sprintf(buf, " %lu", r2.id);
|
2014-10-24 21:22:07 +00:00
|
|
|
strcat(cmd, buf);
|
|
|
|
}
|
2014-10-22 05:06:22 +00:00
|
|
|
}
|
|
|
|
retval = system(cmd);
|
|
|
|
if (retval) {
|
|
|
|
match = false;
|
|
|
|
} else {
|
|
|
|
match = true;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int cleanup_result(RESULT const&, void*) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|