From 8009a8cecbca4b7c47e72947cc10e317ed51beb9 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 27 May 2013 11:45:10 -0700 Subject: [PATCH] Condor interface: various fixes, mostly from Jaime Frey - XML parser: for parse_string(), malloc the 256KB buffer instead of allocating it on the stack; the latter crashes threads with 32KB stacks. However, do the malloc() only if we've actually seen the start tag (this required a bit of code shuffle). - BOINC GAHP: escape spaces in error msgs --- lib/parse.cpp | 59 +++++++++++++++++--------- lib/parse.h | 31 ++------------ lib/parse_test.cpp | 9 +++- lib/remote_submit.cpp | 4 +- samples/condor/boinc_gahp.cpp | 78 ++++++++++++++++++++++------------- 5 files changed, 100 insertions(+), 81 deletions(-) diff --git a/lib/parse.cpp b/lib/parse.cpp index 716fd8f665..f49aa08c2a 100644 --- a/lib/parse.cpp +++ b/lib/parse.cpp @@ -540,18 +540,9 @@ int XML_PARSER::scan_cdata(char* buf, int len) { } } -#define MAX_XML_STRING 262144 - -// We just parsed "parsed_tag". -// If it matches "start_tag", and is followed by a string -// and by the matching close tag, return the string in "buf", -// and return true. -// -bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) { - bool eof; - char end_tag[TAG_BUF_LEN], tag[TAG_BUF_LEN]; - +static inline bool is_empty_string(char* parsed_tag, const char* start_tag) { size_t n = strlen(parsed_tag); + char tag[TAG_BUF_LEN]; // handle the archaic form , which means empty string // @@ -559,14 +550,17 @@ bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) { strcpy(tag, parsed_tag); tag[n-1] = 0; if (!strcmp(tag, start_tag)) { - strcpy(buf, ""); return true; } } + return false; +} - // check for start tag - // - if (strcmp(parsed_tag, start_tag)) return false; +// we've parsed the start tag of a string; parse the string itself. +// +bool XML_PARSER::parse_str_aux(const char* start_tag, char* buf, int len) { + bool eof; + char end_tag[TAG_BUF_LEN], tag[TAG_BUF_LEN]; end_tag[0] = '/'; strcpy(end_tag+1, start_tag); @@ -598,12 +592,37 @@ bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) { return true; } +// We just parsed "parsed_tag". +// If it matches "start_tag", and is followed by a string +// and by the matching close tag, return the string in "buf", +// and return true. +// +bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) { + if (is_empty_string(parsed_tag, start_tag)) { + strcpy(buf, ""); + return true; + } + if (strcmp(parsed_tag, start_tag)) return false; + return parse_str_aux(start_tag, buf, len); +} + +#define MAX_XML_STRING 262144 + +// same, for std::string +// bool XML_PARSER::parse_string(const char* start_tag, string& str) { - char buf[MAX_XML_STRING]; - bool flag = parse_str(start_tag, buf, sizeof(buf)); - if (!flag) return false; - str = buf; - return true; + if (is_empty_string(parsed_tag, start_tag)) { + str = ""; + return true; + } + if (strcmp(parsed_tag, start_tag)) return false; + char *buf=(char *)malloc(MAX_XML_STRING); + bool flag = parse_str_aux(start_tag, buf, MAX_XML_STRING); + if (flag) { + str = buf; + } + free(buf); + return flag; } // Same, for integers diff --git a/lib/parse.h b/lib/parse.h index 00cd49cc20..7c29cd6fa5 100644 --- a/lib/parse.h +++ b/lib/parse.h @@ -244,7 +244,10 @@ struct XML_PARSER { strip_whitespace(buf); return retval; } + bool parse_str_aux(const char*, char*, int); + // interface starts here + // bool parse_start(const char*); bool parse_str(const char*, char*, int); bool parse_string(const char*, std::string&); @@ -332,34 +335,6 @@ inline bool parse_double(const char* buf, const char* tag, double& x) { return true; } -#if 0 -// Same, for unsigned long -// -inline bool parse_ulong(const char* buf, const char* tag, unsigned long& x) { - const char* p = strstr(buf, tag); - if (!p) return false; - errno = 0; - unsigned long y = strtoul(p+strlen(tag), NULL, 0); - if (errno) return false; - x = y; - return true; -} - -// Same, for unsigned long long -// -inline bool parse_ulonglong( - const char* buf, const char* tag, unsigned long long& x -) { - const char* p = strstr(buf, tag); - if (!p) return false; - errno = 0; - unsigned long long y = boinc_strtoull(p+strlen(tag), NULL, 0); - if (errno) return false; - x = y; - return true; -} -#endif - extern bool parse(char* , char* ); extern bool parse_str(const char*, const char*, char*, int); extern bool parse_str(const char* buf, const char* tag, std::string& dest); diff --git a/lib/parse_test.cpp b/lib/parse_test.cpp index 2f9d85bd34..e388e1fd1e 100644 --- a/lib/parse_test.cpp +++ b/lib/parse_test.cpp @@ -1,6 +1,9 @@ // test program for XML parser #include +#include + +using std::string; #include "parse.h" @@ -12,6 +15,7 @@ void parse(FILE* f) { char foo[64]; int val; double x; + string s; strcpy(name, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); mf.init_file(f); @@ -29,8 +33,9 @@ void parse(FILE* f) { if (xp.match_tag("/blah")) { printf("success\n"); return; - } else if (xp.parse_str("str", name, 33)) { - printf("got str: [%s]\n", name); + } else if (xp.parse_str("str", name, 64)) { + //} else if (xp.parse_string("str", s)) { + printf("got str: [%s]\n", s.c_str()); } else if (xp.parse_int("int", val)) { printf("got int: %d\n", val); } else if (xp.parse_double("double", x)) { diff --git a/lib/remote_submit.cpp b/lib/remote_submit.cpp index 6200aa030b..399a7007e5 100644 --- a/lib/remote_submit.cpp +++ b/lib/remote_submit.cpp @@ -317,7 +317,7 @@ int submit_jobs( error_msg = ""; int temp; while (fgets(buf, 256, reply)) { - printf("submit_batch reply: %s", buf); + //printf("submit_batch reply: %s", buf); if (parse_int(buf, "", temp)) { retval = 0; continue; @@ -527,7 +527,7 @@ int get_output_file( sprintf(url, "%sget_output.php?cmd=workunit_file&auth_str=%s&wu_name=%s&file_num=%d", project_url, authenticator, job_name, file_num ); - printf("fetching %s to %s\n", url, dst_path); + //printf("fetching %s to %s\n", url, dst_path); int retval = do_http_get(url, dst_path); error_msg = ""; if (retval) { diff --git a/samples/condor/boinc_gahp.cpp b/samples/condor/boinc_gahp.cpp index c8749b1241..3b37e61774 100644 --- a/samples/condor/boinc_gahp.cpp +++ b/samples/condor/boinc_gahp.cpp @@ -87,6 +87,24 @@ int compute_md5(string path, LOCAL_FILE& f) { return md5_file(path.c_str(), f.md5, f.nbytes); } +const char *escape_str(const string &str) +{ + static string out; + out = ""; + for ( const char *ptr = str.c_str(); *ptr; ptr++ ) { + switch ( *ptr ) { + case ' ': + case '\\': + case '\r': + case '\n': + out += '\\'; + default: + out += *ptr; + } + } + return out.c_str(); +} + // Get a list of the input files used by the batch. // Get their MD5s. // See if they're already on the server. @@ -206,8 +224,8 @@ void handle_submit(COMMAND& c) { project_url, authenticator, req.app_name, NULL, td, error_msg ); if (retval) { - sprintf(buf, "error getting templates: %d\n", retval); - s = string(buf) + error_msg; + sprintf(buf, "error\\ getting\\ templates:\\ %d\\ ", retval); + s = string(buf) + escape_str(error_msg); c.out = strdup(s.c_str()); return; } @@ -215,22 +233,22 @@ void handle_submit(COMMAND& c) { project_url, authenticator, req.batch_name, req.app_name, req.batch_id, error_msg ); if (retval) { - sprintf(buf, "error creating batch: %d ", retval); - s = string(buf) + error_msg; + sprintf(buf, "error\\ creating\\ batch:\\ %d\\ ", retval); + s = string(buf) + escape_str(error_msg); c.out = strdup(s.c_str()); return; } retval = process_input_files(req, error_msg); if (retval) { - sprintf(buf, "error processing input files: %d ", retval); - s = string(buf) + error_msg; + sprintf(buf, "error\\ processing\\ input\\ files:\\ %d\\ ", retval); + s = string(buf) + escape_str(error_msg); c.out = strdup(s.c_str()); return; } retval = submit_jobs(project_url, authenticator, req, error_msg); if (retval) { - sprintf(buf, "error submitting jobs: %d ", retval); - s = string(buf) + error_msg; + sprintf(buf, "error\\ submitting\\ jobs:\\ %d\\ ", retval); + s = string(buf) + escape_str(error_msg); } else { s = "NULL"; } @@ -254,13 +272,15 @@ void handle_query_batches(COMMAND&c) { project_url, authenticator, c.batch_names, reply, error_msg ); if (retval) { - sprintf(buf, "error querying batch: %d ", retval); - s = string(buf) + error_msg; + sprintf(buf, "error\\ querying\\ batch:\\ %d\\ ", retval); + s = string(buf) + escape_str(error_msg); } else { s = string("NULL "); + sprintf(buf, "%d", (int)reply.jobs.size()); + s += string(buf); for (unsigned int i=0; i