From 167d7a9f0ffd1b4fe600193441bdb7358db2740b Mon Sep 17 00:00:00 2001 From: sepro Date: Thu, 22 May 2025 00:27:07 +0200 Subject: [PATCH] [jsinterp] Fix increment/decrement evaluation (#13238) Closes #13241 Authored by: seproDev, bashonly Co-authored-by: bashonly <88596187+bashonly@users.noreply.github.com> --- test/test_jsinterp.py | 8 ++++++ test/test_youtube_signature.py | 4 +++ yt_dlp/jsinterp.py | 49 +++++++++++++++++----------------- 3 files changed, 37 insertions(+), 24 deletions(-) diff --git a/test/test_jsinterp.py b/test/test_jsinterp.py index b14069ccc6..2e3cdc2a59 100644 --- a/test/test_jsinterp.py +++ b/test/test_jsinterp.py @@ -478,6 +478,14 @@ class TestJSInterpreter(unittest.TestCase): func = jsi.extract_function('c', {'e': 10}, {'f': 100, 'g': 1000}) self.assertEqual(func([1]), 1111) + def test_increment_decrement(self): + self._test('function f() { var x = 1; return ++x; }', 2) + self._test('function f() { var x = 1; return x++; }', 1) + self._test('function f() { var x = 1; x--; return x }', 0) + self._test('function f() { var y; var x = 1; x++, --x, x--, x--, y="z", "abc", x++; return --x }', -1) + self._test('function f() { var a = "test--"; return a; }', 'test--') + self._test('function f() { var b = 1; var a = "b--"; return a; }', 'b--') + if __name__ == '__main__': unittest.main() diff --git a/test/test_youtube_signature.py b/test/test_youtube_signature.py index 0f0885366e..3f777aed7a 100644 --- a/test/test_youtube_signature.py +++ b/test/test_youtube_signature.py @@ -316,6 +316,10 @@ _NSIG_TESTS = [ 'https://www.youtube.com/s/player/8a8ac953/tv-player-es6.vflset/tv-player-es6.js', 'MiBYeXx_vRREbiCCmh', 'RtZYMVvmkE0JE', ), + ( + 'https://www.youtube.com/s/player/59b252b9/player_ias.vflset/en_US/base.js', + 'D3XWVpYgwhLLKNK4AGX', 'aZrQ1qWJ5yv5h', + ), ] diff --git a/yt_dlp/jsinterp.py b/yt_dlp/jsinterp.py index b59fb2c615..45aeffa229 100644 --- a/yt_dlp/jsinterp.py +++ b/yt_dlp/jsinterp.py @@ -590,6 +590,29 @@ class JSInterpreter: return ret, True return ret, False + m = re.match(fr'''(?x) + (?P{_NAME_RE})(?:\[(?P{_NESTED_BRACKETS})\])?\s* + (?P{"|".join(map(re.escape, set(_OPERATORS) - _COMP_OPERATORS))})? + =(?!=)(?P.*)$ + ''', expr) + if m: # We are assigning a value to a variable + left_val = local_vars.get(m.group('out')) + + if not m.group('index'): + local_vars[m.group('out')] = self._operator( + m.group('op'), left_val, m.group('expr'), expr, local_vars, allow_recursion) + return local_vars[m.group('out')], should_return + elif left_val in (None, JS_Undefined): + raise self.Exception(f'Cannot index undefined variable {m.group("out")}', expr) + + idx = self.interpret_expression(m.group('index'), local_vars, allow_recursion) + if not isinstance(idx, (int, float)): + raise self.Exception(f'List index {idx} must be integer', expr) + idx = int(idx) + left_val[idx] = self._operator( + m.group('op'), self._index(left_val, idx), m.group('expr'), expr, local_vars, allow_recursion) + return left_val[idx], should_return + for m in re.finditer(rf'''(?x) (?P\+\+|--)(?P{_NAME_RE})| (?P{_NAME_RE})(?P\+\+|--)''', expr): @@ -606,11 +629,7 @@ class JSInterpreter: return None, should_return m = re.match(fr'''(?x) - (?P - (?P{_NAME_RE})(?:\[(?P{_NESTED_BRACKETS})\])?\s* - (?P{"|".join(map(re.escape, set(_OPERATORS) - _COMP_OPERATORS))})? - =(?!=)(?P.*)$ - )|(?P + (?P (?!if|return|true|false|null|undefined|NaN)(?P{_NAME_RE})$ )|(?P (?P{_NAME_RE})(?: @@ -622,25 +641,7 @@ class JSInterpreter: )|(?P (?P{_NAME_RE})\((?P.*)\)$ )''', expr) - if m and m.group('assign'): - left_val = local_vars.get(m.group('out')) - - if not m.group('index'): - local_vars[m.group('out')] = self._operator( - m.group('op'), left_val, m.group('expr'), expr, local_vars, allow_recursion) - return local_vars[m.group('out')], should_return - elif left_val in (None, JS_Undefined): - raise self.Exception(f'Cannot index undefined variable {m.group("out")}', expr) - - idx = self.interpret_expression(m.group('index'), local_vars, allow_recursion) - if not isinstance(idx, (int, float)): - raise self.Exception(f'List index {idx} must be integer', expr) - idx = int(idx) - left_val[idx] = self._operator( - m.group('op'), self._index(left_val, idx), m.group('expr'), expr, local_vars, allow_recursion) - return left_val[idx], should_return - - elif expr.isdigit(): + if expr.isdigit(): return int(expr), should_return elif expr == 'break':