Skip to content

Commit b05e43a

Browse files
committed
Implement CallFunctionKw.
1 parent d14c471 commit b05e43a

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

src/processor/instructions.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub enum Instruction {
6969
LoadFast(usize),
7070
StoreFast(usize),
7171
LoadGlobal(usize),
72-
CallFunction(usize, usize), // nb_args, nb_kwargs
72+
CallFunction(usize, bool), // nb_args + nb_kwargs, has_kwargs
7373
RaiseVarargs(usize),
7474
MakeFunction { has_defaults: bool, has_kwdefaults: bool, has_annotations: bool, has_closure: bool },
7575
BuildConstKeyMap(usize),
@@ -163,13 +163,14 @@ impl<'a, I> Iterator for InstructionDecoder<I> where I: Iterator<Item=&'a u8> {
163163
124 => Instruction::LoadFast(oparg),
164164
125 => Instruction::StoreFast(oparg),
165165
130 => Instruction::RaiseVarargs(oparg),
166-
131 => Instruction::CallFunction(oparg, 0),
166+
131 => Instruction::CallFunction(oparg, false),
167167
132 => Instruction::MakeFunction {
168168
has_defaults: oparg & 0x01 != 0,
169169
has_kwdefaults: oparg & 0x02 != 0,
170170
has_annotations: oparg & 0x04 != 0,
171171
has_closure: oparg & 0x08 != 0,
172172
},
173+
141 => Instruction::CallFunction(oparg, true),
173174
156 => Instruction::BuildConstKeyMap(oparg),
174175
144 => panic!("The impossible happened."),
175176
_ => panic!(format!("Opcode not supported: {:?}", (opcode, oparg))),

src/processor/mod.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -512,16 +512,27 @@ fn run_code<EP: EnvProxy>(state: &mut State<EP>, call_stack: &mut Vec<Frame>) ->
512512
panic!("Bad RaiseVarargs argument") // TODO: Raise an exception instead
513513
}
514514

515-
Instruction::CallFunction(nb_args, nb_kwargs) => {
515+
Instruction::CallFunction(nb_args, has_kwargs) => {
516516
// See “Call constructs” at:
517517
// http://security.coverity.com/blog/2014/Nov/understanding-python-bytecode.html
518-
let kwargs;
518+
let kwargs: Vec<(ObjectRef, ObjectRef)>;
519519
let args;
520520
let func;
521521
{
522522
let frame = call_stack.last_mut().unwrap();
523-
kwargs = py_unwrap!(state, frame.var_stack.pop_n_pairs(nb_kwargs), ProcessorError::StackTooSmall);
524-
args = py_unwrap!(state, frame.var_stack.pop_many(nb_args), ProcessorError::StackTooSmall);
523+
if has_kwargs {
524+
let ref obj = state.store.deref(&pop_stack!(state, frame.var_stack)).content;
525+
let names: Vec<ObjectRef> = match obj {
526+
&ObjectContent::Tuple(ref v) => v.into_iter().cloned().collect(),
527+
_ => panic!("Bad CallFunctionKw argument"),
528+
};
529+
let values: Vec<ObjectRef> = frame.var_stack.pop_many(names.len()).unwrap();
530+
kwargs = names.into_iter().zip(values).collect();
531+
}
532+
else {
533+
kwargs = Vec::new();
534+
}
535+
args = py_unwrap!(state, frame.var_stack.pop_many(nb_args - kwargs.len()), ProcessorError::StackTooSmall);
525536
func = pop_stack!(state, frame.var_stack);
526537
}
527538
call_function(state, call_stack, &func, args, kwargs)

0 commit comments

Comments
 (0)