diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2015-04-22 22:34:34 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2015-04-22 22:40:46 -0700 |
commit | f1e953d0cf7f5669a55b1337a87e646c1262d139 (patch) | |
tree | 4202cb6dc09fee952ca0085fae95ebd78c876084 | |
parent | 547ec78bf27e37e7a1552d99185200fef460bb38 (diff) | |
download | mu-f1e953d0cf7f5669a55b1337a87e646c1262d139.tar.gz |
1146 - yet another out-of-bounds access
There's a test in this commit, but it doesn't actually fail, because by some accident the memory at index 2 of recipe 'f' has data at the is_label offset and breaks out of the loop. Graah. How did I ever misplace that "Reading One Instruction" waypoint? I could swear I was concerned about this possibility when I implemented calls. Today has been tough on my confidence. STL helps avoid memory leaks but doesn't help with buffer overflows nearly as much as I thought. Oh brilliant, valgrind caught the problem! And there weren't any others. I feel much better.
-rw-r--r-- | cpp/.traces/return_on_fallthrough | 40 | ||||
-rw-r--r-- | cpp/020run | 5 | ||||
-rw-r--r-- | cpp/035call | 23 |
3 files changed, 66 insertions, 2 deletions
diff --git a/cpp/.traces/return_on_fallthrough b/cpp/.traces/return_on_fallthrough new file mode 100644 index 00000000..4408c63a --- /dev/null +++ b/cpp/.traces/return_on_fallthrough @@ -0,0 +1,40 @@ +parse/0: instruction: 1001 +parse/0: instruction: 1 +parse/0: ingredient: {name: "34", value: 0, type: 0, properties: ["34": "literal"]} +parse/0: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "34", value: 0, type: 0, properties: ["34": "literal"]} +parse/0: product: {name: "2", value: 0, type: 1, properties: ["2": "integer"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "34", value: 0, type: 0, properties: ["34": "literal"]} +parse/0: product: {name: "3", value: 0, type: 1, properties: ["3": "integer"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "34", value: 0, type: 0, properties: ["34": "literal"]} +parse/0: product: {name: "4", value: 0, type: 1, properties: ["4": "integer"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "34", value: 0, type: 0, properties: ["34": "literal"]} +parse/0: product: {name: "5", value: 0, type: 1, properties: ["5": "integer"]} +after-brace/0: recipe f +after-brace/0: copy ... +after-brace/0: copy ... +after-brace/0: recipe main +after-brace/0: f ... +after-brace/0: copy ... +after-brace/0: copy ... +after-brace/0: copy ... +run/0: instruction main/0 +run/0: instruction f/0 +run/0: ingredient 0 is 34 +mem/0: storing 34 in location 4 +run/0: instruction f/1 +run/0: ingredient 0 is 34 +mem/0: storing 34 in location 5 +run/0: instruction main/1 +run/0: ingredient 0 is 34 +mem/0: storing 34 in location 1 +run/0: instruction main/2 +run/0: ingredient 0 is 34 +mem/0: storing 34 in location 2 +run/0: instruction main/3 +run/0: ingredient 0 is 34 +mem/0: storing 34 in location 3 diff --git a/cpp/020run b/cpp/020run index 3dad12bf..456d578a 100644 --- a/cpp/020run +++ b/cpp/020run @@ -47,11 +47,13 @@ void run(recipe_number r) { void run(routine rr) { Current_routine = &rr; while (!done(rr)) { + // Running One Instruction. vector<instruction>& instructions = steps(rr); size_t& pc = running_at(rr); - // Running one instruction. +//? trace("foo") << "2: " << pc << " " << &pc; //? 1 if (instructions[pc].is_label) { ++pc; continue; } //? cout << "AAA " << Trace_stream << " ^" << Trace_stream->dump_layer << "$\n"; //? 1 +//? trace("foo") << "2.5: " << pc << " " << &pc; //? 1 trace("run") << "instruction " << recipe_name(rr) << '/' << pc; //? cout << "operation " << instructions[pc].operation << '\n'; //? 3 //? if (!instructions[pc].products.empty()) trace("foo") << "AAA product 0 is " << instructions[pc].products[0].to_string(); //? 1 @@ -68,6 +70,7 @@ void run(routine rr) { cout << "not a primitive op: " << instructions[pc].operation << '\n'; } } +//? trace("foo") << "3: " << pc << " " << &pc; //? 1 ++pc; } Current_routine = NULL; diff --git a/cpp/035call b/cpp/035call index efb4a2a7..d5867f80 100644 --- a/cpp/035call +++ b/cpp/035call @@ -9,6 +9,24 @@ recipe f [ ] +mem: storing 4 in location 3 +:(scenario "return_on_fallthrough") +recipe main [ + f + 1:integer <- copy 34:literal + 2:integer <- copy 34:literal + 3:integer <- copy 34:literal +] +recipe f [ + 4:integer <- copy 34:literal + 5:integer <- copy 34:literal +] ++run: instruction main/0 ++run: instruction f/0 ++run: instruction f/1 ++run: instruction main/1 ++run: instruction main/2 ++run: instruction main/3 + :(before "struct routine {") // Everytime a recipe runs another, we interrupt it and start running the new // recipe. When that finishes, we continue this one where we left off. @@ -65,15 +83,18 @@ inline bool done(routine& rr) { return rr.calls.empty(); } -:(before "Running one instruction") +:(before "Running One Instruction") // when we reach the end of one call, we may reach the end of the one below // it, and the one below that, and so on +//? trace("foo") << "0: " << pc << " " << &pc; //? 1 while (running_at(rr) >= steps(rr).size()) { +//? trace("foo") << "pop"; //? 1 rr.calls.pop(); if (rr.calls.empty()) return; // todo: no results returned warning ++running_at(rr); } +//? trace("foo") << "1: " << pc << " " << &pc; //? 1 :(before "End Includes") #include <stack> |