Skip to content

Commit e3e67ee

Browse files
committed
Start implementing function calls.
1 parent 2d7f176 commit e3e67ee

File tree

5 files changed

+40
-11
lines changed

5 files changed

+40
-11
lines changed

src/lib.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,20 @@ impl fmt::Display for InterpreterError {
2222
}
2323
}
2424

25-
pub fn run_module<R: io::Read>(reader: &mut R) -> Result<(), InterpreterError> {
25+
pub fn run_module<R: io::Read, EP: sandbox::EnvProxy>(reader: &mut R, envproxy: &mut EP) -> Result<(), InterpreterError> {
2626
let mut buf = [0; 12];
2727
try!(reader.read_exact(&mut buf).map_err(InterpreterError::Io));
2828
// TODO: do something with the content of the buffer
2929
let mut store = objects::ObjectStore::new();
3030
let module = try!(marshal::read_object(reader, &mut store).map_err(InterpreterError::Unmarshal));
31-
let mut envproxy = sandbox::MockEnvProxy::new();
32-
processor::run_code_object(&mut envproxy, module, &mut store);
31+
processor::run_code_object(envproxy, &mut store, module);
3332
Ok(())
3433
}
3534

3635
#[test]
3736
fn test_hello_world() {
3837
let mut reader: &[u8] = b"\xee\x0c\r\n\x15j\nW\x15\x00\x00\x00\xe3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00@\x00\x00\x00s\x0e\x00\x00\x00e\x00\x00d\x00\x00\x83\x01\x00\x01d\x01\x00S)\x02z\x0bHello worldN)\x01\xda\x05print\xa9\x00r\x02\x00\x00\x00r\x02\x00\x00\x00\xfa\x0b/tmp/foo.py\xda\x08<module>\x01\x00\x00\x00s\x00\x00\x00\x00";
39-
run_module(&mut reader);
38+
let mut envproxy = sandbox::MockEnvProxy::new();
39+
run_module(&mut reader, &mut envproxy).unwrap();
40+
assert_eq!(*envproxy.stdout_content.lock().unwrap(), b"Hello world\n");
4041
}

src/processor/instructions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub enum Instruction {
88
LoadConst(usize),
99
LoadName(usize),
1010
LoadFast(u16),
11-
CallFunction(u8, u8),
11+
CallFunction(usize, usize), // nb_args, nb_kwargs
1212
}
1313

1414
#[derive(Debug)]
@@ -49,7 +49,7 @@ impl<'a, I> Iterator for InstructionDecoder<I> where I: Iterator<Item=&'a u8> {
4949
100 => Instruction::LoadConst(self.read_argument() as usize),
5050
101 => Instruction::LoadName(self.read_argument() as usize),
5151
124 => Instruction::LoadFast(self.read_argument()),
52-
131 => Instruction::CallFunction(self.read_byte(), self.read_byte()),
52+
131 => Instruction::CallFunction(self.read_byte() as usize, self.read_byte() as usize),
5353
_ => panic!(format!("Opcode not supported: {}", opcode)),
5454
}
5555
})

src/processor/mod.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@ pub enum ProcessorError {
1616
InvalidNameIndex,
1717
}
1818

19-
fn run_code<EP: EnvProxy>(envproxy: &mut EP, code: Code, store: &mut ObjectStore) -> Result<ObjectRef, ProcessorError> {
19+
fn call_function<EP: EnvProxy>(envproxy: &mut EP, store: &mut ObjectStore, func_ref: &ObjectRef, args: Vec<ObjectRef>, kwags: Vec<ObjectRef>) -> Result<ObjectRef, ProcessorError> {
20+
let code = match store.deref(func_ref).content {
21+
ObjectContent::Code(ref code) => code.clone(),
22+
_ => return Err(ProcessorError::NotACodeObject),
23+
};
24+
run_code(envproxy, store, code)
25+
}
26+
27+
fn run_code<EP: EnvProxy>(envproxy: &mut EP, store: &mut ObjectStore, code: Code) -> Result<ObjectRef, ProcessorError> {
2028
let bytecode: Vec<u8> = code.code;
2129
let instructions: Vec<Instruction> = instructions::InstructionDecoder::new(bytecode.iter()).into_iter().collect();
2230
let mut program_counter = 0 as usize;
@@ -28,16 +36,25 @@ fn run_code<EP: EnvProxy>(envproxy: &mut EP, code: Code, store: &mut ObjectStore
2836
Instruction::ReturnValue => return Ok(try!(stack.pop().ok_or(ProcessorError::StackTooSmall))),
2937
Instruction::LoadConst(i) => stack.push(try!(code.names.get(i).ok_or(ProcessorError::InvalidConstIndex)).clone()),
3038
Instruction::LoadName(i) => stack.push(try!(code.names.get(i).ok_or(ProcessorError::InvalidNameIndex)).clone()),
39+
Instruction::CallFunction(nb_args, nb_kwargs) => {
40+
// See “Call constructs” at:
41+
// http://security.coverity.com/blog/2014/Nov/understanding-python-bytecode.html
42+
let kwargs = try!(stack.pop_many(nb_kwargs*2).ok_or(ProcessorError::StackTooSmall));
43+
let args = try!(stack.pop_many(nb_args).ok_or(ProcessorError::StackTooSmall));
44+
let func = try!(stack.pop().ok_or(ProcessorError::StackTooSmall));
45+
let ret_value = call_function(envproxy, store, &func, args, kwargs);
46+
stack.push(try!(ret_value))
47+
}
3148
_ => panic!(format!("todo: instruction {:?}", *instruction)),
3249
}
3350
};
3451
panic!("Unreachable")
3552
}
3653

37-
pub fn run_code_object<EP: EnvProxy>(envproxy: &mut EP, module: ObjectRef, store: &mut ObjectStore) -> Result<ObjectRef, ProcessorError> {
54+
pub fn run_code_object<EP: EnvProxy>(envproxy: &mut EP, store: &mut ObjectStore, module: ObjectRef) -> Result<ObjectRef, ProcessorError> {
3855
let code = match store.deref(&module).content {
3956
ObjectContent::Code(ref code) => code.clone(),
4057
_ => return Err(ProcessorError::NotACodeObject),
4158
};
42-
run_code(envproxy, code, store)
59+
run_code(envproxy, store, code)
4360
}

src/sandbox/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl EnvProxy for RealEnvProxy {
2828

2929

3030

31-
struct VectorWriter {
31+
pub struct VectorWriter {
3232
vector: Arc<Mutex<Vec<u8>>>,
3333
}
3434

@@ -49,7 +49,7 @@ impl io::Write for VectorWriter {
4949
}
5050

5151
pub struct MockEnvProxy {
52-
stdout_content: Arc<Mutex<Vec<u8>>>,
52+
pub stdout_content: Arc<Mutex<Vec<u8>>>,
5353
}
5454

5555
impl MockEnvProxy {

src/stack.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pub trait Stack {
33

44
fn top(&self) -> Option<&Self::Item>;
55
fn pop(&mut self) -> Option<Self::Item>;
6+
fn pop_many(&mut self, count: usize) -> Option<Vec<Self::Item>>;
67
fn push(&mut self, value: Self::Item);
78
}
89

@@ -27,6 +28,16 @@ impl<Item> Stack for VectorStack<Item> {
2728
self.vector.pop()
2829
}
2930

31+
fn pop_many(&mut self, count: usize) -> Option<Vec<Self::Item>> {
32+
if count > self.vector.len() {
33+
None
34+
}
35+
else {
36+
let length = self.vector.len();
37+
Some(self.vector.drain((length-count)..length).into_iter().collect())
38+
}
39+
}
40+
3041
fn push(&mut self, value: Self::Item) {
3142
self.vector.push(value)
3243
}

0 commit comments

Comments
 (0)