aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Hagemeister <phihag@phihag.de>2014-07-20 00:03:54 +0200
committerPhilipp Hagemeister <phihag@phihag.de>2014-07-20 00:03:54 +0200
commite75c24e88907f329c57cf05d729dbf599349bb50 (patch)
tree9a414da9c75e08fbf948a69ebdd5084994160f77
parent0cb2056304178ae8944e84c5bc72f96102291a12 (diff)
downloadyoutube-dl-e75c24e88907f329c57cf05d729dbf599349bb50.tar.xz
[swfinterp] Extend tests and fix parsing
-rw-r--r--test/swftests/StaticAssignment.as13
-rw-r--r--test/swftests/StaticRetrieval.as16
-rw-r--r--test/test_swfinterp.py9
-rw-r--r--youtube_dl/swfinterp.py47
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()