diff options
-rw-r--r-- | 011load.cc | 21 | ||||
-rw-r--r-- | 016dilated_reagent.cc | 21 | ||||
-rw-r--r-- | 017parse_tree.cc | 22 | ||||
-rw-r--r-- | 030container.cc | 10 | ||||
-rw-r--r-- | 050scenario.cc | 30 | ||||
-rw-r--r-- | 052tangle.cc | 10 | ||||
-rw-r--r-- | 053recipe_header.cc | 10 | ||||
-rw-r--r-- | 089scenario_filesystem.cc | 15 |
8 files changed, 130 insertions, 9 deletions
diff --git a/011load.cc b/011load.cc index 9dc54922..23126647 100644 --- a/011load.cc +++ b/011load.cc @@ -26,6 +26,10 @@ vector<recipe_ordinal> load(istream& in) { skip_whitespace_and_comments(in); if (!has_data(in)) break; string command = next_word(in); + if (command.empty()) { + assert(!has_data(in)); + break; + } // Command Handlers if (command == "recipe" || command == "def") { recipe_ordinal r = slurp_recipe(in); @@ -50,6 +54,11 @@ vector<recipe_ordinal> load(istream& in) { int slurp_recipe(istream& in) { recipe result; result.name = next_word(in); + if (result.name.empty()) { + assert(!has_data(in)); + raise << "file ended with 'recipe'\n" << end(); + return -1; + } // End Load Recipe Name skip_whitespace_but_not_newline(in); // End Recipe Refinements @@ -89,7 +98,7 @@ bool next_instruction(istream& in, instruction* curr) { curr->clear(); skip_whitespace_and_comments(in); if (!has_data(in)) { - raise << "0: unbalanced '[' for recipe\n" << end(); + raise << "incomplete recipe at end of file (0)\n" << end(); return false; } @@ -97,10 +106,15 @@ bool next_instruction(istream& in, instruction* curr) { while (has_data(in) && in.peek() != '\n') { skip_whitespace_but_not_newline(in); if (!has_data(in)) { - raise << "1: unbalanced '[' for recipe\n" << end(); + raise << "incomplete recipe at end of file (1)\n" << end(); return false; } string word = next_word(in); + if (word.empty()) { + assert(!has_data(in)); + raise << "incomplete recipe at end of file (2)\n" << end(); + return false; + } words.push_back(word); skip_whitespace_but_not_newline(in); } @@ -113,7 +127,7 @@ bool next_instruction(istream& in, instruction* curr) { curr->label = words.at(0); trace(9993, "parse") << "label: " << curr->label << end(); if (!has_data(in)) { - raise << "7: unbalanced '[' for recipe\n" << end(); + raise << "incomplete recipe at end of file (3)\n" << end(); return false; } return true; @@ -149,6 +163,7 @@ bool next_instruction(istream& in, instruction* curr) { return true; } +// can return empty string -- only if `in` has no more data string next_word(istream& in) { skip_whitespace_but_not_newline(in); // End next_word Special-cases diff --git a/016dilated_reagent.cc b/016dilated_reagent.cc index b7c8ecc4..1d89ba8d 100644 --- a/016dilated_reagent.cc +++ b/016dilated_reagent.cc @@ -107,7 +107,13 @@ if (starts_with(s, "{")) { return; } { - string_tree* type_names = new string_tree(next_word(in)); + string s = next_word(in); + if (s.empty()) { + assert(!has_data(in)); + raise << "incomplete dilated reagent at end of file (0)\n" << end(); + return; + } + string_tree* type_names = new string_tree(s); // End Parsing Dilated Reagent Type Property(type_names) type = new_type_tree(type_names); delete type_names; @@ -116,7 +122,13 @@ if (starts_with(s, "{")) { string key = slurp_key(in); if (key.empty()) continue; if (key == "}") continue; - string_tree* value = new string_tree(next_word(in)); + string s = next_word(in); + if (s.empty()) { + assert(!has_data(in)); + raise << "incomplete dilated reagent at end of file (1)\n" << end(); + return; + } + string_tree* value = new string_tree(s); // End Parsing Dilated Reagent Property(value) properties.push_back(pair<string, string_tree*>(key, value)); } @@ -126,6 +138,11 @@ if (starts_with(s, "{")) { :(code) string slurp_key(istream& in) { string result = next_word(in); + if (result.empty()) { + assert(!has_data(in)); + raise << "incomplete dilated reagent at end of file (2)\n" << end(); + return result; + } while (!result.empty() && *result.rbegin() == ':') strip_last(result); while (isspace(in.peek()) || in.peek() == ':') diff --git a/017parse_tree.cc b/017parse_tree.cc index c7e7473b..eb1fb85d 100644 --- a/017parse_tree.cc +++ b/017parse_tree.cc @@ -46,7 +46,13 @@ string_tree* parse_string_tree(istream& in) { return NULL; } if (in.peek() != '(') { - string_tree* result = new string_tree(next_word(in)); + string s = next_word(in); + if (s.empty()) { + assert(!has_data(in)); + raise << "incomplete string tree at end of file (0)\n" << end(); + return NULL; + } + string_tree* result = new string_tree(s); return result; } in.get(); // skip '(' @@ -57,10 +63,18 @@ string_tree* parse_string_tree(istream& in) { assert(has_data(in)); if (in.peek() == ')') break; *curr = new string_tree(NULL, NULL); - if (in.peek() == '(') + if (in.peek() == '(') { (*curr)->left = parse_string_tree(in); - else - (*curr)->left = new string_tree(next_word(in)); + } + else { + string s = next_word(in); + if (s.empty()) { + assert(!has_data(in)); + raise << "incomplete string tree at end of file (1)\n" << end(); + return NULL; + } + (*curr)->left = new string_tree(s); + } curr = &(*curr)->right; } in.get(); // skip ')' diff --git a/030container.cc b/030container.cc index 110a8970..6abbbcc6 100644 --- a/030container.cc +++ b/030container.cc @@ -721,6 +721,11 @@ Num_calls_to_transform_all_at_first_definition = -1; void insert_container(const string& command, kind_of_type kind, istream& in) { skip_whitespace_but_not_newline(in); string name = next_word(in); + if (name.empty()) { + assert(!has_data(in)); + raise << "incomplete container definition at end of file (0)\n" << end(); + return; + } // End container Name Refinements trace(9991, "parse") << "--- defining " << command << ' ' << name << end(); if (!contains_key(Type_ordinal, name) @@ -744,6 +749,11 @@ void insert_container(const string& command, kind_of_type kind, istream& in) { while (has_data(in)) { skip_whitespace_and_comments(in); string element = next_word(in); + if (element.empty()) { + assert(!has_data(in)); + raise << "incomplete container definition at end of file (1)\n" << end(); + return; + } if (element == "]") break; if (in.peek() != '\n') { raise << command << " '" << name << "' contains multiple elements on a single line. Containers and exclusive containers must only contain elements, one to a line, no code.\n" << end(); diff --git a/050scenario.cc b/050scenario.cc index 2e0d1ca7..a4f57cf5 100644 --- a/050scenario.cc +++ b/050scenario.cc @@ -78,6 +78,11 @@ else if (command == "pending-scenario") { scenario parse_scenario(istream& in) { scenario result; result.name = next_word(in); + if (result.name.empty()) { + assert(!has_data(in)); + raise << "incomplete scenario at end of file\n" << end(); + return result; + } skip_whitespace_and_comments(in); if (in.peek() != '[') { raise << "Expected '[' after scenario '" << result.name << "'\n" << end(); @@ -329,6 +334,11 @@ void check_memory(const string& s) { skip_whitespace_and_comments(in); if (!has_data(in)) break; string lhs = next_word(in); + if (lhs.empty()) { + assert(!has_data(in)); + raise << "incomplete 'memory-should-contain' block at end of file (0)\n" << end(); + return; + } if (!is_integer(lhs)) { check_type(lhs, in); continue; @@ -338,6 +348,11 @@ void check_memory(const string& s) { string _assign; in >> _assign; assert(_assign == "<-"); skip_whitespace_and_comments(in); string rhs = next_word(in); + if (rhs.empty()) { + assert(!has_data(in)); + raise << "incomplete 'memory-should-contain' block at end of file (1)\n" << end(); + return; + } if (!is_integer(rhs) && !is_noninteger(rhs)) { if (Current_scenario && !Scenario_testing_scenario) // genuine test in a mu file @@ -374,9 +389,19 @@ void check_type(const string& lhs, istream& in) { x.set_value(to_integer(x.name)); skip_whitespace_and_comments(in); string _assign = next_word(in); + if (_assign.empty()) { + assert(!has_data(in)); + raise << "incomplete 'memory-should-contain' block at end of file (2)\n" << end(); + return; + } assert(_assign == "<-"); skip_whitespace_and_comments(in); string literal = next_word(in); + if (literal.empty()) { + assert(!has_data(in)); + raise << "incomplete 'memory-should-contain' block at end of file (3)\n" << end(); + return; + } int address = x.value; // exclude quoting brackets assert(*literal.begin() == '['); literal.erase(literal.begin()); @@ -750,6 +775,11 @@ void run_mu_scenario(const string& form) { in >> std::noskipws; skip_whitespace_and_comments(in); string _scenario = next_word(in); + if (_scenario.empty()) { + assert(!has_data(in)); + raise << "no scenario in string passed into run_mu_scenario()\n" << end(); + return; + } assert(_scenario == "scenario"); scenario s = parse_scenario(in); run_mu_scenario(s); diff --git a/052tangle.cc b/052tangle.cc index 50c74076..8aaecbd1 100644 --- a/052tangle.cc +++ b/052tangle.cc @@ -34,6 +34,11 @@ Fragments_used.clear(); :(before "End Command Handlers") else if (command == "before") { string label = next_word(in); + if (label.empty()) { + assert(!has_data(in)); + raise << "incomplete 'before' block at end of file\n" << end(); + return result; + } recipe tmp; slurp_body(in, tmp); if (is_waypoint(label)) @@ -44,6 +49,11 @@ else if (command == "before") { } else if (command == "after") { string label = next_word(in); + if (label.empty()) { + assert(!has_data(in)); + raise << "incomplete 'after' block at end of file\n" << end(); + return result; + } recipe tmp; slurp_body(in, tmp); if (is_waypoint(label)) diff --git a/053recipe_header.cc b/053recipe_header.cc index b23614c8..450a0142 100644 --- a/053recipe_header.cc +++ b/053recipe_header.cc @@ -33,6 +33,11 @@ void load_recipe_header(istream& in, recipe& result) { result.has_header = true; while (has_data(in) && in.peek() != '[' && in.peek() != '\n') { string s = next_word(in); + if (s.empty()) { + assert(!has_data(in)); + raise << "incomplete recipe header at end of file (0)\n" << end(); + return; + } if (s == "<-") raise << "recipe " << result.name << " should say '->' and not '<-'\n" << end(); if (s == "->") break; @@ -42,6 +47,11 @@ void load_recipe_header(istream& in, recipe& result) { } while (has_data(in) && in.peek() != '[' && in.peek() != '\n') { string s = next_word(in); + if (s.empty()) { + assert(!has_data(in)); + raise << "incomplete recipe header at end of file (1)\n" << end(); + return; + } result.products.push_back(reagent(s)); trace(9999, "parse") << "header product: " << result.products.back().original_string << end(); skip_whitespace_but_not_newline(in); diff --git a/089scenario_filesystem.cc b/089scenario_filesystem.cc index c761ee93..6af3166b 100644 --- a/089scenario_filesystem.cc +++ b/089scenario_filesystem.cc @@ -115,6 +115,11 @@ void parse_resources(const string& data, map<string, string>& out, const string& skip_whitespace_and_comments(in); if (!has_data(in)) break; string filename = next_word(in); + if (filename.empty()) { + assert(!has_data(in)); + raise << "incomplete 'resources' block at end of file (0)\n" << end(); + return; + } if (*filename.begin() != '[') { raise << caller << ": assume-resources: filename '" << filename << "' must begin with a '['\n" << end(); break; @@ -130,6 +135,11 @@ void parse_resources(const string& data, map<string, string>& out, const string& break; } string arrow = next_word(in); + if (arrow.empty()) { + assert(!has_data(in)); + raise << "incomplete 'resources' block at end of file (1)\n" << end(); + return; + } if (arrow != "<-") { raise << caller << ": assume-resources: expected '<-' after filename '" << filename << "' but got '" << arrow << "'\n" << end(); break; @@ -139,6 +149,11 @@ void parse_resources(const string& data, map<string, string>& out, const string& break; } string contents = next_word(in); + if (contents.empty()) { + assert(!has_data(in)); + raise << "incomplete 'resources' block at end of file (2)\n" << end(); + return; + } if (*contents.begin() != '[') { raise << caller << ": assume-resources: file contents '" << contents << "' for filename '" << filename << "' must begin with a '['\n" << end(); break; |