1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <time.h>
#include "inc/Code.h"
#include "inc/Rule.h"
#include "inc/Silf.h"
#include "inc/Face.h"
using namespace graphite2;
using namespace vm;
typedef Machine::Code Code;
const byte simple_prog[] =
{
PUSH_BYTE, 43,
PUSH_BYTE, 42,
// PUSH_LONG, 1,2,3,4, // Uncomment to cause an overflow
PUSH_BYTE, 11, PUSH_BYTE, 13, ADD,
PUSH_BYTE, 4, SUB,
COND,
// PUSH_LONG, 0x80, 0x00, 0x00, 0x00,
// PUSH_LONG, 0xff, 0xff, 0xff, 0xff,
// DIV,
// COND, // Uncomment to cause an underflow
// POP_RET
};
#define _msg(m) #m
const char * prog_error_msg[] = {
_msg(loaded),
_msg(alloc_failed),
_msg(invalid_opcode),
_msg(unimplemented_opcode_used),
_msg(jump_past_end),
_msg(arguments_exhausted),
_msg(missing_return)
};
const char * run_error_msg[] = {
_msg(finished),
_msg(stack_underflow),
_msg(stack_not_empty),
_msg(stack_overflow),
_msg(slot_offset_out_bounds),
_msg(died_early)
};
class graphite2::Segment {};
//std::vector<byte> fuzzer(int);
int main(int argc, char *argv[])
{
const char * font_path = argv[1];
size_t repeats = 1,
copies = ((1 << 20)*4 + sizeof(simple_prog)-1) / sizeof(simple_prog);
if (argc < 2)
{
std::cerr << argv[0] << ": GRAPHITE-FONT [repeats] [copies]" << std::endl;
exit(1);
}
if (argc > 2)
repeats = atoi(argv[2]);
if (argc > 3)
copies = atoi(argv[3]);
std::cout << "simple program size: " << sizeof(simple_prog)+1 << " bytes" << std::endl;
// Replicate the code copies times.
std::vector<byte> big_prog;
big_prog.push_back(simple_prog[0]);
big_prog.push_back(simple_prog[1]);
for(; copies; --copies)
big_prog.insert(big_prog.end(), &simple_prog[2], simple_prog + sizeof(simple_prog));
big_prog.push_back(POP_RET);
std::cout << "amplified program size: " << big_prog.size() << " bytes" << std::endl;
// Load the code.
Silf silf;
gr_face *face = gr_make_file_face(font_path, gr_face_dumbRendering);
if (!face)
{
std::cerr << argv[0] << ": failed to load graphite tables for font: " << font_path << std::endl;
exit(1);
}
Code prog(false, &big_prog[0], &big_prog[0] + big_prog.size(), 0, 0, silf, *face, PASS_TYPE_UNKNOWN);
if (!prog) { // Find out why it did't work
// For now just dump an error message.
std::cerr << "program failed to load due to: "
<< prog_error_msg[prog.status()] << std::endl;
return 1;
}
std::cout << "loaded program size: "
<< prog.dataSize() + prog.instructionCount()*sizeof(instr)
<< " bytes" << std::endl
<< " "
<< prog.instructionCount() << " instructions" << std::endl;
// run the program
Segment seg;
Slot s1;
uint32 ret = 0;
SlotMap smap(seg, 0, 0);
Machine m(smap);
smap.pushSlot(&s1);
slotref * map = smap.begin();
for(size_t n = repeats; n; --n) {
ret = prog.run(m, map);
switch (m.status()) {
case Machine::stack_underflow:
case Machine::stack_overflow:
case Machine::died_early:
std::cerr << "program terminated early: "
<< run_error_msg[m.status()] << std::endl;
std::cout << "--------" << std::endl
<< "between " << prog.instructionCount()*(repeats-n)
<< " and " << prog.instructionCount()*(repeats-std::min(n-1,repeats))
<< " instructions executed" << std::endl;
return 2;
case Machine::stack_not_empty:
std::cerr << "program completed but stack not empty." << std::endl;
repeats -= n-1;
n=1;
break;
case Machine::slot_offset_out_bounds:
std::cerr << "illegal slot reference." << std::endl;
repeats -= n-1;
n=1;
break;
default:
{
// noop
}
}
}
gr_face_destroy(face);
std::cout << "result of program: " << ret << std::endl
<< "--------" << std::endl
<< "equivalent of " << prog.instructionCount()*repeats
<< " instructions executed" << std::endl;
return 0;
}
std::vector<byte> random_sequence(size_t n)
{
std::vector<bool> done(n);
std::vector<byte> seq(n);
srand(static_cast<unsigned int>(time(NULL)));
while(n)
{
const size_t r = (rand()*n + RAND_MAX/2)/RAND_MAX;
if (done[r]) continue;
done[r] = true;
seq[r] = byte(r);
--n;
}
return seq;
}
/*
std::vector<byte> fuzzer(int n)
{
std::vector<byte> code(256);
std::vector<bool> covered(256);
// Track stack depth to ensure we don't create programs that
// overflow or underflow the stack.
size_t stack_depth = 0;
return code;
}
*/
|