diff options
| -rw-r--r-- | test/swftests/StaticAssignment.as | 13 | ||||
| -rw-r--r-- | test/swftests/StaticRetrieval.as | 16 | ||||
| -rw-r--r-- | test/test_swfinterp.py | 9 | ||||
| -rw-r--r-- | youtube_dl/swfinterp.py | 47 | 
4 files changed, 70 insertions, 15 deletions
| diff --git a/test/swftests/StaticAssignment.as b/test/swftests/StaticAssignment.as new file mode 100644 index 000000000..b061c219d --- /dev/null +++ b/test/swftests/StaticAssignment.as @@ -0,0 +1,13 @@ +// input: [1] +// output: 1 + +package { +public class StaticAssignment { +	public static var v:int; + +    public static function main(a:int):int{ +        v = a; +        return v; +    } +} +} diff --git a/test/swftests/StaticRetrieval.as b/test/swftests/StaticRetrieval.as new file mode 100644 index 000000000..c8352d819 --- /dev/null +++ b/test/swftests/StaticRetrieval.as @@ -0,0 +1,16 @@ +// input: [] +// output: 1 + +package { +public class StaticRetrieval { +	public static var v:int; + +    public static function main():int{ +        if (v) { +        	return 0; +        } else { +        	return 1; +        } +    } +} +} diff --git a/test/test_swfinterp.py b/test/test_swfinterp.py index 98a14a006..3bb5a6308 100644 --- a/test/test_swfinterp.py +++ b/test/test_swfinterp.py @@ -23,10 +23,10 @@ class TestSWFInterpreter(unittest.TestCase):      pass -for testfile in os.listdir(TEST_DIR): +def _make_testfunc(testfile):      m = re.match(r'^(.*)\.(as)$', testfile)      if not m: -        continue +        return      test_id = m.group(1)      def test_func(self): @@ -36,7 +36,7 @@ for testfile in os.listdir(TEST_DIR):                  or os.path.getmtime(swf_file) < os.path.getmtime(as_file)):              # Recompile              try: -                subprocess.check_call(['mxmlc', '--output', swf_file, as_file]) +                subprocess.check_call(['mxmlc', '-output', swf_file, as_file])              except OSError as ose:                  if ose.errno == errno.ENOENT:                      print('mxmlc not found! Skipping test.') @@ -69,5 +69,8 @@ for testfile in os.listdir(TEST_DIR):      setattr(TestSWFInterpreter, test_func.__name__, test_func) +for testfile in os.listdir(TEST_DIR): +    _make_testfunc(testfile) +  if __name__ == '__main__':      unittest.main() diff --git a/youtube_dl/swfinterp.py b/youtube_dl/swfinterp.py index 49fade364..64a518fc6 100644 --- a/youtube_dl/swfinterp.py +++ b/youtube_dl/swfinterp.py @@ -39,6 +39,16 @@ def _extract_tags(file_contents):          pos += tag_len +class _AVM_Object(object): +    def __init__(self, value=None, name_hint=None): +        self.value = value +        self.name_hint = name_hint + +    def __repr__(self): +        nh = '' if self.name_hint is None else (' %s' % self.name_hint) +        return 'AVMObject%s(%r)' % (nh, self.value) + +  class _AVMClass_Object(object):      def __init__(self, avm_class):          self.avm_class = avm_class @@ -92,8 +102,8 @@ def _s32(reader):  def _s24(reader):      bs = reader.read(3)      assert len(bs) == 3 -    first_byte = b'\xff' if (ord(bs[0:1]) >= 0x80) else b'\x00' -    return struct.unpack('!i', first_byte + bs) +    last_byte = b'\xff' if (ord(bs[2:3]) >= 0x80) else b'\x00' +    return struct.unpack('<i', bs + last_byte)[0]  def _read_string(reader): @@ -341,8 +351,9 @@ class SWFInterpreter(object):              u30 = lambda: _u30(coder)              print('Invoking %s.%s(%r)' % (avm_class.name, func_name, tuple(args))) -            registers = ['(this)'] + list(args) + [None] * m.local_count +            registers = [avm_class.variables] + list(args) + [None] * m.local_count              stack = [] +            scopes = collections.deque([avm_class.variables])              while True:                  opcode = _read_byte(coder)                  print('opcode: %r, stack(%d): %r' % (opcode, len(stack), stack)) @@ -351,6 +362,11 @@ class SWFInterpreter(object):                      value = stack.pop()                      if value:                          coder.seek(coder.tell() + offset) +                elif opcode == 18:  # iffalse +                    offset = s24() +                    value = stack.pop() +                    if not value: +                        coder.seek(coder.tell() + offset)                  elif opcode == 36:  # pushbyte                      v = _read_byte(coder)                      stack.append(v) @@ -361,9 +377,8 @@ class SWFInterpreter(object):                      idx = u30()                      stack.append(constant_strings[idx])                  elif opcode == 48:  # pushscope -                    # We don't implement the scope register, so we'll just -                    # ignore the popped value                      new_scope = stack.pop() +                    scopes.append(new_scope)                  elif opcode == 70:  # callproperty                      index = u30()                      mname = self.multinames[index] @@ -435,20 +450,28 @@ class SWFInterpreter(object):                          arr.append(stack.pop())                      arr = arr[::-1]                      stack.append(arr) -                elif opcode == 93:  # findpropstrict -                    index = u30() -                    mname = self.multinames[index] -                    res = self.extract_function(avm_class, mname) -                    stack.append(res)                  elif opcode == 94:  # findproperty                      index = u30()                      mname = self.multinames[index] -                    res = avm_class.variables.get(mname) +                    for s in reversed(scopes): +                        if mname in s: +                            res = s +                            break +                    else: +                        res = scopes[0]                      stack.append(res)                  elif opcode == 96:  # getlex                      index = u30()                      mname = self.multinames[index] -                    res = avm_class.variables.get(mname, None) +                    for s in reversed(scopes): +                        if mname in s: +                            scope = s +                            break +                    else: +                        scope = scopes[0] +                    # I cannot find where static variables are initialized +                    # so let's just return None +                    res = scope.get(mname)                      stack.append(res)                  elif opcode == 97:  # setproperty                      index = u30() | 
