1
0
mirror of https://github.com/l1ving/youtube-dl synced 2024-12-31 00:42:58 +08:00

[swfinterp] Implement various opcodes

This commit is contained in:
Philipp Hagemeister 2014-11-17 04:45:12 +01:00
parent 8d05f2c16a
commit 4686ae4b64

View File

@ -151,6 +151,16 @@ def _read_byte(reader):
StringClass = _AVMClass('(no name idx)', 'String') StringClass = _AVMClass('(no name idx)', 'String')
class _Undefined(object):
def __boolean__(self):
return False
def __hash__(self):
return 0
undefined = _Undefined()
class SWFInterpreter(object): class SWFInterpreter(object):
def __init__(self, file_contents): def __init__(self, file_contents):
self._patched_functions = {} self._patched_functions = {}
@ -423,6 +433,8 @@ class SWFInterpreter(object):
coder.seek(coder.tell() + offset) coder.seek(coder.tell() + offset)
elif opcode == 32: # pushnull elif opcode == 32: # pushnull
stack.append(None) stack.append(None)
elif opcode == 33: # pushundefined
stack.append(undefined)
elif opcode == 36: # pushbyte elif opcode == 36: # pushbyte
v = _read_byte(coder) v = _read_byte(coder)
stack.append(v) stack.append(v)
@ -430,6 +442,8 @@ class SWFInterpreter(object):
stack.append(True) stack.append(True)
elif opcode == 39: # pushfalse elif opcode == 39: # pushfalse
stack.append(False) stack.append(False)
elif opcode == 40: # pushnan
stack.append(float('NaN'))
elif opcode == 42: # dup elif opcode == 42: # dup
value = stack[-1] value = stack[-1]
stack.append(value) stack.append(value)
@ -493,7 +507,11 @@ class SWFInterpreter(object):
elif obj == StringClass: elif obj == StringClass:
if mname == 'String': if mname == 'String':
assert len(args) == 1 assert len(args) == 1
assert isinstance(args[0], (int, compat_str)) assert isinstance(args[0], (
int, compat_str, _Undefined))
if args[0] == undefined:
res = 'undefined'
else:
res = compat_str(args[0]) res = compat_str(args[0])
stack.append(res) stack.append(res)
continue continue
@ -505,7 +523,7 @@ class SWFInterpreter(object):
'Unsupported property %r on %r' 'Unsupported property %r on %r'
% (mname, obj)) % (mname, obj))
elif opcode == 71: # returnvoid elif opcode == 71: # returnvoid
res = None res = undefined
return res return res
elif opcode == 72: # returnvalue elif opcode == 72: # returnvalue
res = stack.pop() res = stack.pop()
@ -533,13 +551,13 @@ class SWFInterpreter(object):
if isinstance(obj, _AVMClass_Object): if isinstance(obj, _AVMClass_Object):
func = self.extract_function(obj.avm_class, mname) func = self.extract_function(obj.avm_class, mname)
res = func(args) res = func(args)
assert res is None assert res is undefined
continue continue
if isinstance(obj, _ScopeDict): if isinstance(obj, _ScopeDict):
assert mname in obj.avm_class.method_names assert mname in obj.avm_class.method_names
func = self.extract_function(obj.avm_class, mname) func = self.extract_function(obj.avm_class, mname)
res = func(args) res = func(args)
assert res is None assert res is undefined
continue continue
if mname == 'reverse': if mname == 'reverse':
assert isinstance(obj, list) assert isinstance(obj, list)
@ -617,7 +635,7 @@ class SWFInterpreter(object):
obj = stack.pop() obj = stack.pop()
assert isinstance(obj, (dict, _ScopeDict)), \ assert isinstance(obj, (dict, _ScopeDict)), \
'Accessing member %r on %r' % (pname, obj) 'Accessing member %r on %r' % (pname, obj)
res = obj.get(pname, None) res = obj.get(pname, undefined)
stack.append(res) stack.append(res)
else: # Assume attribute access else: # Assume attribute access
idx = stack.pop() idx = stack.pop()
@ -631,8 +649,24 @@ class SWFInterpreter(object):
stack.append(intvalue) stack.append(intvalue)
elif opcode == 128: # coerce elif opcode == 128: # coerce
u30() u30()
elif opcode == 130: # coerce_a
value = stack.pop()
# um, yes, it's any value
stack.append(value)
elif opcode == 133: # coerce_s elif opcode == 133: # coerce_s
assert isinstance(stack[-1], (type(None), compat_str)) 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 elif opcode == 160: # add
value2 = stack.pop() value2 = stack.pop()
value1 = stack.pop() value1 = stack.pop()