mirror of
				https://gitlab.com/ytdl-org/youtube-dl.git
				synced 2025-11-04 04:37:06 -05: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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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()
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user