mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-31 14:45:14 +00:00 
			
		
		
		
	[swfinterp] Extend tests and fix parsing
This commit is contained in:
		
							
								
								
									
										13
									
								
								test/swftests/StaticAssignment.as
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/swftests/StaticAssignment.as
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								test/swftests/StaticRetrieval.as
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								test/swftests/StaticRetrieval.as
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | } | ||||||
| @@ -23,10 +23,10 @@ class TestSWFInterpreter(unittest.TestCase): | |||||||
|     pass |     pass | ||||||
|  |  | ||||||
|  |  | ||||||
| for testfile in os.listdir(TEST_DIR): | def _make_testfunc(testfile): | ||||||
|     m = re.match(r'^(.*)\.(as)$', testfile) |     m = re.match(r'^(.*)\.(as)$', testfile) | ||||||
|     if not m: |     if not m: | ||||||
|         continue |         return | ||||||
|     test_id = m.group(1) |     test_id = m.group(1) | ||||||
|  |  | ||||||
|     def test_func(self): |     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)): |                 or os.path.getmtime(swf_file) < os.path.getmtime(as_file)): | ||||||
|             # Recompile |             # Recompile | ||||||
|             try: |             try: | ||||||
|                 subprocess.check_call(['mxmlc', '--output', swf_file, as_file]) |                 subprocess.check_call(['mxmlc', '-output', swf_file, as_file]) | ||||||
|             except OSError as ose: |             except OSError as ose: | ||||||
|                 if ose.errno == errno.ENOENT: |                 if ose.errno == errno.ENOENT: | ||||||
|                     print('mxmlc not found! Skipping test.') |                     print('mxmlc not found! Skipping test.') | ||||||
| @@ -69,5 +69,8 @@ for testfile in os.listdir(TEST_DIR): | |||||||
|     setattr(TestSWFInterpreter, test_func.__name__, test_func) |     setattr(TestSWFInterpreter, test_func.__name__, test_func) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | for testfile in os.listdir(TEST_DIR): | ||||||
|  |     _make_testfunc(testfile) | ||||||
|  |  | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     unittest.main() |     unittest.main() | ||||||
|   | |||||||
| @@ -39,6 +39,16 @@ def _extract_tags(file_contents): | |||||||
|         pos += tag_len |         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): | class _AVMClass_Object(object): | ||||||
|     def __init__(self, avm_class): |     def __init__(self, avm_class): | ||||||
|         self.avm_class = avm_class |         self.avm_class = avm_class | ||||||
| @@ -92,8 +102,8 @@ def _s32(reader): | |||||||
| def _s24(reader): | def _s24(reader): | ||||||
|     bs = reader.read(3) |     bs = reader.read(3) | ||||||
|     assert len(bs) == 3 |     assert len(bs) == 3 | ||||||
|     first_byte = b'\xff' if (ord(bs[0:1]) >= 0x80) else b'\x00' |     last_byte = b'\xff' if (ord(bs[2:3]) >= 0x80) else b'\x00' | ||||||
|     return struct.unpack('!i', first_byte + bs) |     return struct.unpack('<i', bs + last_byte)[0] | ||||||
|  |  | ||||||
|  |  | ||||||
| def _read_string(reader): | def _read_string(reader): | ||||||
| @@ -341,8 +351,9 @@ class SWFInterpreter(object): | |||||||
|             u30 = lambda: _u30(coder) |             u30 = lambda: _u30(coder) | ||||||
|  |  | ||||||
|             print('Invoking %s.%s(%r)' % (avm_class.name, func_name, tuple(args))) |             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 = [] |             stack = [] | ||||||
|  |             scopes = collections.deque([avm_class.variables]) | ||||||
|             while True: |             while True: | ||||||
|                 opcode = _read_byte(coder) |                 opcode = _read_byte(coder) | ||||||
|                 print('opcode: %r, stack(%d): %r' % (opcode, len(stack), stack)) |                 print('opcode: %r, stack(%d): %r' % (opcode, len(stack), stack)) | ||||||
| @@ -351,6 +362,11 @@ class SWFInterpreter(object): | |||||||
|                     value = stack.pop() |                     value = stack.pop() | ||||||
|                     if value: |                     if value: | ||||||
|                         coder.seek(coder.tell() + offset) |                         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 |                 elif opcode == 36:  # pushbyte | ||||||
|                     v = _read_byte(coder) |                     v = _read_byte(coder) | ||||||
|                     stack.append(v) |                     stack.append(v) | ||||||
| @@ -361,9 +377,8 @@ class SWFInterpreter(object): | |||||||
|                     idx = u30() |                     idx = u30() | ||||||
|                     stack.append(constant_strings[idx]) |                     stack.append(constant_strings[idx]) | ||||||
|                 elif opcode == 48:  # pushscope |                 elif opcode == 48:  # pushscope | ||||||
|                     # We don't implement the scope register, so we'll just |  | ||||||
|                     # ignore the popped value |  | ||||||
|                     new_scope = stack.pop() |                     new_scope = stack.pop() | ||||||
|  |                     scopes.append(new_scope) | ||||||
|                 elif opcode == 70:  # callproperty |                 elif opcode == 70:  # callproperty | ||||||
|                     index = u30() |                     index = u30() | ||||||
|                     mname = self.multinames[index] |                     mname = self.multinames[index] | ||||||
| @@ -435,20 +450,28 @@ class SWFInterpreter(object): | |||||||
|                         arr.append(stack.pop()) |                         arr.append(stack.pop()) | ||||||
|                     arr = arr[::-1] |                     arr = arr[::-1] | ||||||
|                     stack.append(arr) |                     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 |                 elif opcode == 94:  # findproperty | ||||||
|                     index = u30() |                     index = u30() | ||||||
|                     mname = self.multinames[index] |                     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) |                     stack.append(res) | ||||||
|                 elif opcode == 96:  # getlex |                 elif opcode == 96:  # getlex | ||||||
|                     index = u30() |                     index = u30() | ||||||
|                     mname = self.multinames[index] |                     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) |                     stack.append(res) | ||||||
|                 elif opcode == 97:  # setproperty |                 elif opcode == 97:  # setproperty | ||||||
|                     index = u30() |                     index = u30() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Philipp Hagemeister
					Philipp Hagemeister