@@ -89,11 +89,10 @@ mod tests {
8989 ) ;
9090 }
9191
92+ // Check if it's possible to escape the multiline restriction by closing the first parenthesis.
93+ // This tries to exploit the fact that we wrap the entire expression in extra parentheses.
9294 #[ test]
93- fn test_multiple_lines_escape ( ) {
94- // NOTE: We wrap the entire Python expression in `(\n{}\n)`, so that inside the expression
95- // we can use newlines. Here we check that it's not possible to escape this simply by closing
96- // the first parenthesis.
95+ fn test_multiple_lines_escape_1 ( ) {
9796 let result = transform_expression_string ( "x)\n \n import os; os.path.join('a', 'b')\n \n (" )
9897 . unwrap_err ( ) ;
9998 assert_eq ! (
@@ -102,6 +101,31 @@ mod tests {
102101 ) ;
103102 }
104103
104+ // This is the most that the logic can be "exploited" - constructing an expression
105+ // that makes use of the hidden parentheses.
106+ // So while `lambda x: x + 2)(5` would raise a syntax error in Python, since we wrap it
107+ // in parentheses, we actually end up with `(lambda x: x + 2)(5)`, which is valid.
108+ #[ test]
109+ fn test_multiple_lines_escape_2 ( ) {
110+ _test_transformation (
111+ "lambda x: x + 2)(5" ,
112+ "call(context, source, (0, 20), lambda x: x + 2, 5)" ,
113+ vec ! [ ] ,
114+ vec ! [ ] ,
115+ ) ;
116+ }
117+
118+ // However, it's still not possible to construct an expression that contains a statement,
119+ // as this test shows.
120+ #[ test]
121+ fn test_multiple_lines_escape_3 ( ) {
122+ let result = transform_expression_string ( "def fn(x): x + 2)(5" ) . unwrap_err ( ) ;
123+ assert_eq ! (
124+ result,
125+ "Parse error: Expected an identifier, but found a keyword 'def' that cannot be used here at byte range 0..3: 'def'"
126+ ) ;
127+ }
128+
105129 #[ test]
106130 fn test_allow_comments ( ) {
107131 _test_transformation ( "1 # comment" , "1" , vec ! [ ] , vec ! [ ] ) ;
0 commit comments