[swfinterp] Implement various opcodes
This commit is contained in:
		
							parent
							
								
									8d05f2c16a
								
							
						
					
					
						commit
						4686ae4b64
					
				
					 1 changed files with 40 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -151,6 +151,16 @@ def _read_byte(reader):
 | 
			
		|||
StringClass = _AVMClass('(no name idx)', 'String')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _Undefined(object):
 | 
			
		||||
    def __boolean__(self):
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    def __hash__(self):
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
undefined = _Undefined()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SWFInterpreter(object):
 | 
			
		||||
    def __init__(self, file_contents):
 | 
			
		||||
        self._patched_functions = {}
 | 
			
		||||
| 
						 | 
				
			
			@ -423,6 +433,8 @@ class SWFInterpreter(object):
 | 
			
		|||
                        coder.seek(coder.tell() + offset)
 | 
			
		||||
                elif opcode == 32:  # pushnull
 | 
			
		||||
                    stack.append(None)
 | 
			
		||||
                elif opcode == 33:  # pushundefined
 | 
			
		||||
                    stack.append(undefined)
 | 
			
		||||
                elif opcode == 36:  # pushbyte
 | 
			
		||||
                    v = _read_byte(coder)
 | 
			
		||||
                    stack.append(v)
 | 
			
		||||
| 
						 | 
				
			
			@ -430,6 +442,8 @@ class SWFInterpreter(object):
 | 
			
		|||
                    stack.append(True)
 | 
			
		||||
                elif opcode == 39:  # pushfalse
 | 
			
		||||
                    stack.append(False)
 | 
			
		||||
                elif opcode == 40:  # pushnan
 | 
			
		||||
                    stack.append(float('NaN'))
 | 
			
		||||
                elif opcode == 42:  # dup
 | 
			
		||||
                    value = stack[-1]
 | 
			
		||||
                    stack.append(value)
 | 
			
		||||
| 
						 | 
				
			
			@ -493,8 +507,12 @@ class SWFInterpreter(object):
 | 
			
		|||
                    elif obj == StringClass:
 | 
			
		||||
                        if mname == 'String':
 | 
			
		||||
                            assert len(args) == 1
 | 
			
		||||
                            assert isinstance(args[0], (int, compat_str))
 | 
			
		||||
                            res = compat_str(args[0])
 | 
			
		||||
                            assert isinstance(args[0], (
 | 
			
		||||
                                int, compat_str, _Undefined))
 | 
			
		||||
                            if args[0] == undefined:
 | 
			
		||||
                                res = 'undefined'
 | 
			
		||||
                            else:
 | 
			
		||||
                                res = compat_str(args[0])
 | 
			
		||||
                            stack.append(res)
 | 
			
		||||
                            continue
 | 
			
		||||
                        else:
 | 
			
		||||
| 
						 | 
				
			
			@ -505,7 +523,7 @@ class SWFInterpreter(object):
 | 
			
		|||
                        'Unsupported property %r on %r'
 | 
			
		||||
                        % (mname, obj))
 | 
			
		||||
                elif opcode == 71:  # returnvoid
 | 
			
		||||
                    res = None
 | 
			
		||||
                    res = undefined
 | 
			
		||||
                    return res
 | 
			
		||||
                elif opcode == 72:  # returnvalue
 | 
			
		||||
                    res = stack.pop()
 | 
			
		||||
| 
						 | 
				
			
			@ -533,13 +551,13 @@ class SWFInterpreter(object):
 | 
			
		|||
                    if isinstance(obj, _AVMClass_Object):
 | 
			
		||||
                        func = self.extract_function(obj.avm_class, mname)
 | 
			
		||||
                        res = func(args)
 | 
			
		||||
                        assert res is None
 | 
			
		||||
                        assert res is undefined
 | 
			
		||||
                        continue
 | 
			
		||||
                    if isinstance(obj, _ScopeDict):
 | 
			
		||||
                        assert mname in obj.avm_class.method_names
 | 
			
		||||
                        func = self.extract_function(obj.avm_class, mname)
 | 
			
		||||
                        res = func(args)
 | 
			
		||||
                        assert res is None
 | 
			
		||||
                        assert res is undefined
 | 
			
		||||
                        continue
 | 
			
		||||
                    if mname == 'reverse':
 | 
			
		||||
                        assert isinstance(obj, list)
 | 
			
		||||
| 
						 | 
				
			
			@ -617,7 +635,7 @@ class SWFInterpreter(object):
 | 
			
		|||
                        obj = stack.pop()
 | 
			
		||||
                        assert isinstance(obj, (dict, _ScopeDict)), \
 | 
			
		||||
                            'Accessing member %r on %r' % (pname, obj)
 | 
			
		||||
                        res = obj.get(pname, None)
 | 
			
		||||
                        res = obj.get(pname, undefined)
 | 
			
		||||
                        stack.append(res)
 | 
			
		||||
                    else:  # Assume attribute access
 | 
			
		||||
                        idx = stack.pop()
 | 
			
		||||
| 
						 | 
				
			
			@ -631,8 +649,24 @@ class SWFInterpreter(object):
 | 
			
		|||
                    stack.append(intvalue)
 | 
			
		||||
                elif opcode == 128:  # coerce
 | 
			
		||||
                    u30()
 | 
			
		||||
                elif opcode == 130:  # coerce_a
 | 
			
		||||
                    value = stack.pop()
 | 
			
		||||
                    # um, yes, it's any value
 | 
			
		||||
                    stack.append(value)
 | 
			
		||||
                elif opcode == 133:  # coerce_s
 | 
			
		||||
                    assert isinstance(stack[-1], (type(None), compat_str))
 | 
			
		||||
                elif opcode == 147:  # decrement
 | 
			
		||||
                    value = stack.pop()
 | 
			
		||||
                    assert isinstance(value, int)
 | 
			
		||||
                    stack.append(value - 1)
 | 
			
		||||
                elif opcode == 149:  # typeof
 | 
			
		||||
                    value = stack.pop()
 | 
			
		||||
                    return {
 | 
			
		||||
                        _Undefined: 'undefined',
 | 
			
		||||
                        compat_str: 'String',
 | 
			
		||||
                        int: 'Number',
 | 
			
		||||
                        float: 'Number',
 | 
			
		||||
                    }[type(value)]
 | 
			
		||||
                elif opcode == 160:  # add
 | 
			
		||||
                    value2 = stack.pop()
 | 
			
		||||
                    value1 = stack.pop()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue