1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3;
18
19 import static org.apache.commons.jexl3.introspection.JexlPermissions.RESTRICTED;
20 import static org.apache.commons.jexl3.introspection.JexlPermissions.UNRESTRICTED;
21 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
22 import static org.junit.jupiter.api.Assertions.assertEquals;
23 import static org.junit.jupiter.api.Assertions.assertFalse;
24 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
25 import static org.junit.jupiter.api.Assertions.assertNotNull;
26 import static org.junit.jupiter.api.Assertions.assertNull;
27 import static org.junit.jupiter.api.Assertions.assertThrows;
28 import static org.junit.jupiter.api.Assertions.assertTrue;
29 import static org.junit.jupiter.api.Assertions.fail;
30
31 import java.io.Closeable;
32 import java.io.File;
33 import java.lang.reflect.Method;
34 import java.math.BigDecimal;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.HashMap;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Objects;
42 import java.util.concurrent.atomic.AtomicLong;
43
44 import org.apache.commons.jexl3.internal.Debugger;
45 import org.apache.commons.jexl3.internal.Engine32;
46 import org.apache.commons.jexl3.internal.Scope;
47 import org.apache.commons.jexl3.internal.TemplateEngine;
48 import org.apache.commons.jexl3.introspection.JexlPermissions;
49 import org.apache.commons.jexl3.introspection.JexlSandbox;
50 import org.apache.commons.jexl3.parser.ASTJexlScript;
51 import org.apache.commons.jexl3.parser.JexlScriptParser;
52 import org.apache.commons.jexl3.parser.Parser;
53 import org.apache.commons.jexl3.parser.StringProvider;
54 import org.junit.jupiter.api.Assertions;
55 import org.junit.jupiter.api.Test;
56
57
58
59
60 public class Issues400Test {
61
62 public static class VinzCaller {
63 private final JexlContext context;
64
65 VinzCaller(final JexlContext context) {
66 this.context = context;
67 }
68
69 public Object execute(final JexlScript script) {
70 return script.execute(context);
71 }
72 }
73
74 public static class VinzContext extends MapContext {
75 public String member(final String m, final String u) {
76 return m + '.' + u;
77 }
78 }
79
80
81
82
83 public static class XuContext extends MapContext {
84
85 public String join(final int[] list, final String str) {
86 return join(Arrays.stream(list).iterator(), str);
87 }
88
89 public String join(final Iterable<?> list, final String str) {
90 return join(list.iterator(), str);
91 }
92
93 public String join(final Iterator<?> iterator, final String str) {
94 if (!iterator.hasNext()) {
95 return "";
96 }
97 final StringBuilder strb = new StringBuilder(256);
98 strb.append(iterator.next().toString());
99 while (iterator.hasNext()) {
100 strb.append(str);
101 strb.append(Objects.toString(iterator.next(), "?"));
102 }
103 return strb.toString();
104 }
105 }
106
107 private static void run404(final JexlEngine jexl, final String src, final Object... a) {
108 final JexlScript script = jexl.createScript(src, "a", "b");
109 if (!src.endsWith(";")) {
110 assertEquals(script.getSourceText(), script.getParsedText());
111 }
112 final Object result = script.execute(null, a);
113 assertEquals(42, result);
114 }
115
116 @Test
117 void test402() {
118 final JexlContext jc = new MapContext();
119
120 final String[] sources = {
121 "if (true) { return }",
122 "if (true) { 3; return }",
123 "(x->{ 3; return })()"
124 };
125
126 final JexlEngine jexl = new JexlBuilder().create();
127 for (final String source : sources) {
128 final JexlScript e = jexl.createScript(source);
129 final Object o = e.execute(jc);
130 assertNull(o);
131 }
132 }
133
134 @Test
135 void test403() {
136
137 final String[] strings = {
138 " map1.`${item.a}` = 1;\n",
139 " map1[`${item.a}`] = 1;\n",
140 " map1[item.a] = 1;\n"
141 };
142
143 for (final String setmap : strings) {
144
145 final String src = "var a = {'a': 1};\n" +
146 "var list = [a, a];\n" +
147 "let map1 = {:};\n" +
148 "for (let item : list) {\n" +
149 setmap +
150 "}\n " +
151 "map1";
152
153 final JexlEngine jexl = new JexlBuilder().cache(64).create();
154 final JexlScript script = jexl.createScript(src);
155 for (int i = 0; i < 2; ++i) {
156 final Object result = script.execute(null);
157 assertInstanceOf(Map.class, result);
158 final Map<?, ?> map = (Map<?, ?>) result;
159 assertEquals(1, map.size());
160 final Object val = jexl.createScript("m -> m[1]").execute(null, map);
161 assertEquals(1, val);
162 }
163 }
164 }
165
166 @Test
167 void test404a() {
168 final JexlEngine jexl = new JexlBuilder().cache(64).strict(true).safe(false).create();
169 Map<String, Object> a = Collections.singletonMap("b", 42);
170
171 for (final String src : new String[]{"a.b", "a?.b", "a['b']", "a?['b']", "a?.`b`"}) {
172 run404(jexl, src, a);
173 run404(jexl, src + ";", a);
174 }
175
176 for (final String src : new String[]{"a[b]", "a?[b]", "a?.`${b}`"}) {
177 run404(jexl, src, a, "b");
178 run404(jexl, src + ";", a, "b");
179 }
180
181 final Map<String, Object> b = Collections.singletonMap("c", 42);
182 a = Collections.singletonMap("b", b);
183 for (final String src : new String[]{"a[b].c", "a?[b]?['c']", "a?.`${b}`.c"}) {
184 run404(jexl, src, a, "b");
185 }
186 }
187
188 @Test
189 void test404b() {
190
191 final JexlEngine jexl = new JexlBuilder()
192 .cache(64)
193 .strict(true)
194 .safe(false)
195 .create();
196
197 final Map<String, Object> b = Collections.singletonMap("c", 42);
198 final Map<String, Object> a = Collections.singletonMap("b", b);
199 JexlScript script;
200 Object result;
201 script = jexl.createScript("a?['B']?['C']", "a");
202 result = script.execute(null, a);
203 assertEquals(script.getSourceText(), script.getParsedText());
204 assertNull(result);
205 script = jexl.createScript("a?['b']?['C']", "a");
206 assertEquals(script.getSourceText(), script.getParsedText());
207 result = script.execute(null, a);
208 assertNull(result);
209 script = jexl.createScript("a?['b']?['c']", "a");
210 assertEquals(script.getSourceText(), script.getParsedText());
211 result = script.execute(null, a);
212 assertEquals(42, result);
213 script = jexl.createScript("a?['B']?['C']?: 1042", "a");
214 assertEquals(script.getSourceText(), script.getParsedText());
215 result = script.execute(null, a);
216 assertEquals(1042, result);
217
218 script = jexl.createScript("a? ['B']:['C']", "a");
219 result = script.execute(null, a);
220 assertArrayEquals(new String[]{"B"}, (String[]) result);
221 script = jexl.createScript("a?['b'] ?: ['C']", "a");
222 result = script.execute(null, a);
223 assertEquals(b, result);
224 script = jexl.createScript("a?['B'] ?: ['C']", "a");
225 result = script.execute(null, a);
226 assertArrayEquals(new String[]{"C"}, (String[]) result);
227 }
228
229 @Test
230 void test406a() {
231
232 final JexlEngine jexl = new JexlBuilder()
233 .cache(64)
234 .strict(true)
235 .safe(false)
236 .create();
237
238
239 final JexlContext context = new XuContext();
240
241 final List<String> list = Arrays.asList(
242 "[1, 2, 3, 4, ...].join('-')",
243 "[1, 2, 3, 4,].join('-')",
244 "(1 .. 4).join('-')",
245 "join([1, 2, 3, 4, ...], '-')",
246 "join([1, 2, 3, 4], '-')",
247 "join((1 .. 4), '-')");
248
249 for (final String src : list) {
250 final JexlScript script = jexl.createScript(src);
251 final Object result = script.execute(context);
252 assertEquals("1-2-3-4", result, src);
253 }
254
255 final String src0 = "x.join('*')";
256 final JexlScript script0 = jexl.createScript(src0, "x");
257 final String src1 = "join(x, '*')";
258 final JexlScript script1 = jexl.createScript(src1, "x");
259 for (final Object x : Arrays.asList(Arrays.asList(1, 2, 3, 4), new int[]{1, 2, 3, 4})) {
260 Object result = script0.execute(context, x);
261 assertEquals("1*2*3*4", result, src0);
262 result = script1.execute(context, x);
263 assertEquals("1*2*3*4", result, src1);
264 }
265 }
266
267 @Test
268 void test407() {
269
270 final double r = 99.0d + 7.82d - 99.0d - 7.82d;
271 assertEquals(0d, r, 8.e-15);
272
273 final JexlEngine jexl = new JexlBuilder().create();
274 final JexlScript script = jexl.createScript("a + b - a - b", "a", "b");
275
276 Number result = (Number) script.execute(null, 99.0d, 7.82d);
277 assertEquals(0d, result.doubleValue(), 8.e-15);
278
279 result = (Number) script.execute(null, new BigDecimal("99.0"), new BigDecimal("7.82"));
280 assertEquals(0d, result.doubleValue(), 3.e-32);
281 }
282
283 @Test
284 void test412() {
285 final Map<Object, Object> ctl = new HashMap<>();
286 ctl.put("one", 1);
287 ctl.put("two", 2);
288 final String fnsrc0 = "function f(x) { x }\n" + "let one = 'one', two = 'two';\n";
289
290 final List<String> list = Arrays.asList(
291 "{ one : f(1), two:f(2) }",
292 "{ one: f(1), two: f(2) }",
293 "{ one: f(1), two:f(2) }",
294 "{ one :f(1), two:f(2) }");
295
296 for (final String map0 : list) {
297 final String fnsrc = fnsrc0 + map0;
298 final JexlContext jc = new MapContext();
299 final JexlEngine jexl = new JexlBuilder().create();
300 final JexlScript e = jexl.createScript(fnsrc);
301 final Object o = e.execute(jc);
302 assertInstanceOf(Map.class, o);
303 final Map<?, ?> map = (Map<?, ?>) o;
304 assertEquals(map, ctl);
305 }
306 }
307
308 @Test
309 void test413a() {
310 final JexlBuilder builder = new JexlBuilder();
311 final JexlEngine jexl = builder.create();
312 final JexlScript script = jexl.createScript("var c = 42; var f = y -> c += y; f(z)", "z");
313 final Number result = (Number) script.execute(null, 12);
314 assertEquals(54, result);
315 }
316
317 @Test
318 void test413b() {
319 final JexlBuilder builder = new JexlBuilder();
320 final JexlOptions options = builder.options();
321 options.setConstCapture(true);
322 options.setLexical(true);
323 final JexlEngine jexl = builder.create();
324 final JexlScript script = jexl.createScript("var c = 42; var f = y -> c += y; f(z)", "z");
325 final JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> script.execute(null, 12), "c should be const");
326 assertEquals("c", xvar.getVariable());
327 }
328
329 @Test
330 void test413c() {
331 final JexlBuilder builder = new JexlBuilder();
332 final JexlEngine jexl = builder.create();
333 final JexlScript script = jexl.createScript("#pragma jexl.options '+constCapture'\nvar c = 42; var f = y -> c += y; f(z)", "z");
334 final JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> script.execute(null, 12), "c should be const");
335 assertEquals("c", xvar.getVariable());
336 }
337
338 @Test
339 void test413d() {
340 final JexlBuilder builder = new JexlBuilder().features(new JexlFeatures().constCapture(true));
341 final JexlEngine jexl = builder.create();
342 final JexlException.Parsing xparse = assertThrows(
343 JexlException.Parsing.class,
344 () -> jexl.createScript("var c = 42; var f = y -> c += y; f(z)", "z"),
345 "c should be const");
346 assertTrue(xparse.getMessage().contains("const"));
347 }
348
349 @Test
350 void test415() {
351 final JexlBuilder builder = new JexlBuilder().features(new JexlFeatures().constCapture(true));
352 final JexlEngine jexl = builder.create();
353 JexlScript script;
354 Object result;
355 script = jexl.createScript("`#${c}`", "c");
356 result = script.execute(null, 42);
357 assertEquals("#42", result.toString());
358 script = jexl.createScript("`$${c}`", "c");
359 result = script.execute(null, 42);
360 assertEquals("$42", result.toString());
361 script = jexl.createScript("`$#{c}`", "c");
362 result = script.execute(null, 42);
363 assertEquals("$42", result.toString());
364 script = jexl.createScript("`##{c}`", "c");
365 result = script.execute(null, 42);
366 assertEquals("#42", result.toString());
367 script = jexl.createScript("`--##{c}`", "c");
368 result = script.execute(null, 42);
369 assertEquals("--#42", result.toString());
370 }
371
372 @Test
373 void test419() throws NoSuchMethodException {
374
375 final Method currentTimeMillis = System.class.getMethod("currentTimeMillis");
376 assertFalse(RESTRICTED.allow(currentTimeMillis));
377
378 final JexlPermissions permissions = RESTRICTED.compose("java.lang { +System { currentTimeMillis(); } }");
379
380 assertTrue(permissions.allow(currentTimeMillis));
381 assertFalse(RESTRICTED.allow(currentTimeMillis));
382
383
384 final JexlEngine jexl = new JexlBuilder().namespaces(Collections.singletonMap("sns", System.class)).permissions(permissions).create();
385
386 final AtomicLong result = new AtomicLong();
387 assertEquals(0, result.get());
388 final long now = System.currentTimeMillis();
389
390 jexl.createScript("result.set(sns:currentTimeMillis())", "result").execute(null, result);
391 assertTrue(result.get() >= now);
392
393
394 final JexlScript script = jexl.createScript("sns:gc()");
395 final JexlException.Method method = assertThrows(JexlException.Method.class, () -> script.execute(null));
396 assertEquals("gc", method.getMethod());
397
398 }
399
400 @Test
401 void testDocBreakContinue() {
402 final JexlBuilder builder = new JexlBuilder().features(new JexlFeatures().constCapture(true));
403 final JexlEngine jexl = builder.create();
404 JexlScript script;
405 Object result;
406
407 final String srcContinue = "let text = '';\n" +
408 "for (let i : (4..2)) { if (i == 3) continue; text += i; }\n" +
409 "text;";
410
411 script = jexl.createScript(srcContinue);
412 result = script.execute(null);
413 assertEquals("42", result);
414
415 final String srcBreak = "let i = 33;\n" +
416 "while (i < 66) { if (i == 42) { break; } i += 1; }\n" +
417 "i;";
418
419 script = jexl.createScript(srcBreak);
420 result = script.execute(null);
421 assertEquals(42, result);
422 }
423
424 @Test
425 void testNamespaceVsTernary0() {
426 final VinzContext ctxt = new VinzContext();
427 ctxt.set("Users", "USERS");
428 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).silent(false).create();
429
430 JexlScript script = jexl.createScript("() -> {\n"
431 + " var fn = (user) -> {\n"
432 + " user ? user : member(Users, 'user');\n"
433 + " }\n"
434 + "}");
435
436 Object r = script.execute(ctxt);
437 assertNotNull(r);
438 script = (JexlScript) r;
439 r = script.execute(ctxt);
440 assertEquals("USERS.user", r);
441 }
442
443 @Test
444 void testNamespaceVsTernary1() {
445 final VinzContext ctxt = new VinzContext();
446 ctxt.set("Users", "USERS");
447 ctxt.set("vinz", new VinzCaller(ctxt));
448 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).silent(false).create();
449
450 final JexlScript script = jexl.createScript(
451 "vinz.execute(() -> {\n"
452 + " var test = 42;\n"
453 + " var user = useTest ? test : member(Users, 'user');\n"
454 + "})\n" , "useTest");
455
456 Object r = script.execute(ctxt, false);
457 assertNotNull(r);
458 assertEquals("USERS.user", r);
459 r = script.execute(ctxt, true);
460 assertNotNull(r);
461 assertEquals(42, r);
462 }
463
464 public static class Ns429 {
465 public int f(final int x) {
466 return x * 10000 + 42;
467 }
468 }
469
470 @Test
471 void test429a() {
472 final MapContext ctxt = new MapContext();
473 final JexlFeatures features = JexlFeatures.createDefault();
474 final JexlEngine jexl = new JexlBuilder().features(features).safe(false).strict(true).silent(false).create();
475 final JexlScript f = jexl.createScript("x -> x");
476 ctxt.set("f", f);
477 String src = "#pragma jexl.namespace.b " + Ns429.class.getName() + "\n" + "b ? b : f(2);";
478 JexlScript script = jexl.createScript(src, "b");
479 assertEquals(1, (int) script.execute(ctxt, 1));
480
481 src = "#pragma jexl.namespace.b " + Ns429.class.getName() + "\n" + "b ? b:f(2) : 1;";
482 script = jexl.createScript(src, "b");
483 assertEquals(20042, (int) script.execute(ctxt, 1));
484 }
485
486 @Test
487 void test429b() {
488 final MapContext ctxt = new MapContext();
489 ctxt.set("b", 1);
490 final JexlFeatures features = JexlFeatures.createDefault();
491 features.namespaceIdentifier(true);
492 final JexlEngine jexl = new JexlBuilder().features(features).safe(false).strict(true).silent(false).create();
493 final JexlScript f = jexl.createScript("x -> x");
494 ctxt.set("f", f);
495 String src = "#pragma jexl.namespace.b " + Ns429.class.getName() + "\n" + "b ? b : f(2);";
496 JexlScript script = jexl.createScript(src);
497 assertEquals(1, (int) script.execute(ctxt));
498
499 src = "#pragma jexl.namespace.b " + Ns429.class.getName() + "\n" + "b ? b:f(2) : 1;";
500 script = jexl.createScript(src);
501 assertEquals(20042, (int) script.execute(ctxt));
502 }
503
504 @Test
505 void test431a() {
506 final JexlEngine jexl = new JexlBuilder().create();
507 final String src = "let x = 0; try { x += 19 } catch (let error) { return 169 } try { x += 23 } catch (let error) { return 169 }";
508 final JexlScript script = jexl.createScript(src);
509 assertNotNull(script);
510 final Object result = script.execute(null);
511 assertEquals(42, result);
512 }
513
514 Closeable foo() {
515 return null;
516 }
517
518 @Test
519 void test431b() {
520 final JexlEngine jexl = new JexlBuilder().create();
521 final String src = "let x = 0; try(let error) { x += 19 } catch (let error) { return 169 } try { x += 23 } catch (let error) { return 169 }";
522 final JexlScript script = jexl.createScript(src);
523 assertNotNull(script);
524 final Object result = script.execute(null);
525 assertEquals(42, result);
526 }
527
528 @Test
529 void test431c() {
530 final JexlEngine jexl = new JexlBuilder().create();
531 final String src = "let xx = 0; try { xx += 19 } catch (let xx) { return 169 }";
532 try {
533 final JexlScript script = jexl.createScript(src);
534 fail("xx is already defined in scope");
535 } catch (final JexlException.Parsing parsing) {
536 assertTrue(parsing.getDetail().contains("xx"));
537 }
538 }
539
540 @Test
541 void test433() {
542 final JexlEngine jexl = new JexlBuilder().create();
543 final String src = "let condition = true; if (condition) { return; }";
544 final JexlScript script = jexl.createScript(src);
545 assertNotNull(script);
546 final Object result = script.execute(null);
547 assertNull(result);
548 final Debugger debugger = new Debugger();
549 assertTrue(debugger.debug(script));
550 final String dbgStr = debugger.toString();
551 assertTrue(JexlTestCase.equalsIgnoreWhiteSpace(src, dbgStr));
552 }
553
554 @Test
555 void test434() {
556 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).create();
557 final String src = "let foo = null; let value = foo?[bar]";
558 final JexlScript script = jexl.createScript(src);
559 assertNotNull(script);
560 final Object result = script.execute(null);
561 assertNull(result);
562 }
563
564 public static class Arithmetic435 extends JexlArithmetic {
565 public Arithmetic435(final boolean strict) {
566 super(strict);
567 }
568
569 public Object empty(final String type) {
570 if ("list".equals(type)) {
571 return Collections.emptyList();
572 }
573 return null;
574 }
575 }
576
577 @Test
578 void test435() {
579 final JexlArithmetic arithmetic = new Arithmetic435(true);
580 final JexlEngine jexl = new JexlBuilder().arithmetic(arithmetic).create();
581 final String src = "empty('list')";
582 final JexlScript script = jexl.createScript(src);
583 assertNotNull(script);
584 final Object result = script.execute(null);
585 assertInstanceOf(List.class, result);
586 }
587
588 @Test
589 void test436a() {
590 final String[] srcs = {"let i = null; ++i", "let i; ++i;", "let i; i--;", "let i; i++;"};
591 run436(null, srcs);
592 }
593
594 @Test
595 void test436b() {
596 final String[] srcs = {"var i = null; ++i", "var i; ++i;", "var i; i--;", "var i; i++;"};
597 run436(null, srcs);
598 }
599
600 @Test
601 void test436c() {
602 final JexlContext ctxt = new MapContext();
603 ctxt.set("i", null);
604 final String[] srcs = {"++i", "++i;", "i--;", "i++;"};
605 run436(null, srcs);
606 }
607
608 void run436(final JexlContext ctxt, final String[] srcs) {
609 final JexlEngine jexl = new JexlBuilder().create();
610 for (final String src : srcs) {
611 final JexlScript script = jexl.createScript(src);
612 assertThrows(JexlException.Operator.class, () -> script.execute(ctxt));
613 }
614 }
615
616 @Test
617 void test437a() {
618 final JexlEngine jexl = new JexlBuilder().create();
619 final String src = "let values = [...]\n"
620 + "function append(const value) {\n"
621 + " values.add(value)\n"
622 + "}\n"
623 + "\n"
624 + "append(1)\n"
625 + "append(2)\n"
626 + "return values ";
627 final JexlScript script = jexl.createScript(src);
628 assertNotNull(script);
629 final Object result = script.execute(null);
630 assertInstanceOf(List.class, result);
631 final List<?> values = (List<?>) result;
632 assertEquals(2, values.size());
633 }
634
635 @Test
636 void test437b() {
637 final JexlFeatures features = JexlFeatures.createDefault().ambiguousStatement(true);
638 assertTrue(features.supportsAmbiguousStatement());
639 final JexlEngine jexl = new JexlBuilder().features(features).create();
640 final String src = "let values = [...]"
641 + "function append(const value) {"
642 + " values.add(value)"
643 + "}"
644 + "append(1)"
645 + "append(2)"
646 + "return values ";
647 final JexlScript script = jexl.createScript(src);
648 assertNotNull(script);
649 final Object result = script.execute(null);
650 assertInstanceOf(List.class, result);
651 final List<?> values = (List<?>) result;
652 assertEquals(2, values.size());
653 }
654
655
656
657
658 static final char[] EQ_FRIEND;
659
660 static {
661 final char[] eq = {'!', ':', '<', '>', '^', '|', '&', '+', '-', '/', '*', '~', '='};
662 Arrays.sort(eq);
663 EQ_FRIEND = eq;
664 }
665
666
667
668
669
670
671
672 private static String transcodeSQLExpr(final CharSequence expr) {
673 final StringBuilder strb = new StringBuilder(expr.length());
674 final int end = expr.length();
675 char previous = 0;
676 for (int i = 0; i < end; ++i) {
677 final char c = expr.charAt(i);
678 if (previous == '<') {
679
680 if (c == '>') {
681
682 strb.append("!=");
683 previous = c;
684 continue;
685 }
686 strb.append('<');
687 }
688 if (c != '<') {
689 if (c == '=') {
690
691 if (Arrays.binarySearch(EQ_FRIEND, previous) >= 0) {
692 strb.append(c);
693 } else {
694 strb.append("==");
695 }
696 } else {
697 strb.append(c);
698 if (c == '"' || c == '\'') {
699
700 boolean escape = false;
701 for (i += 1; i < end; ++i) {
702 final char ec = expr.charAt(i);
703 strb.append(ec);
704 if (ec == '\\') {
705 escape = !escape;
706 } else if (escape) {
707 escape = false;
708 } else if (ec == c) {
709 break;
710 }
711 }
712 }
713 }
714 }
715 previous = c;
716 }
717 return strb.toString();
718 }
719
720 public static class SQLParser implements JexlScriptParser {
721 final Parser parser;
722
723 public SQLParser() {
724 parser = new Parser(new StringProvider(";"));
725 }
726
727 @Override
728 public ASTJexlScript parse(final JexlInfo info, final JexlFeatures features, final String src, final Scope scope) {
729 return parser.parse(info, features, transcodeSQLExpr(src), scope);
730 }
731
732 @Override
733 public ASTJexlScript jxltParse(final JexlInfo info, final JexlFeatures features, final String src, final Scope scope) {
734 return new Parser(parser).parse(info, features, transcodeSQLExpr(src), scope);
735 }
736 }
737
738
739 @Test
740 void testSQLTranspose() {
741 final String[] e = {"a<>b", "a = 2", "a.b.c <> '1<>0'"};
742 final String[] j = {"a!=b", "a == 2", "a.b.c != '1<>0'"};
743 for (int i = 0; i < e.length; ++i) {
744 final String je = transcodeSQLExpr(e[i]);
745 Assertions.assertEquals(j[i], je);
746 }
747 }
748
749 @Test
750 void testSQLNoChange() {
751 final String[] e = {"a <= 2", "a >= 2", "a := 2", "a + 3 << 4 > 5",};
752 for (final String element : e) {
753 final String je = transcodeSQLExpr(element);
754 Assertions.assertEquals(element, je);
755 }
756 }
757
758 @Test
759 void test438() {
760 final JexlFeatures f = new JexlFeatures().localVar(false).lambda(false).loops(false).sideEffect(false).sideEffectGlobal(false);
761 final JexlBuilder builder = new JexlBuilder().parserFactory(SQLParser::new).cache(32).features(f);
762 final JexlEngine sqle = builder.create();
763 Assertions.assertTrue((boolean) sqle.createScript("a <> 25", "a").execute(null, 24));
764 Assertions.assertFalse((boolean) sqle.createScript("a <> 25", "a").execute(null, 25));
765 Assertions.assertFalse((boolean) sqle.createScript("a = 25", "a").execute(null, 24));
766 Assertions.assertTrue((boolean) sqle.createScript("a != 25", "a").execute(null, 24));
767 Assertions.assertTrue((boolean) sqle.createScript("a = 25", "a").execute(null, 25));
768 Assertions.assertFalse((boolean) sqle.createScript("a != 25", "a").execute(null, 25));
769 }
770
771 @Test
772 void testIssue441() {
773 final JexlEngine jexl = new JexlBuilder().create();
774 String ctl = "\nab\nc`d\n";
775 final JexlExpression e = jexl.createExpression("`\nab\nc\\`d\n`");
776 Object o = e.evaluate(null);
777 Assertions.assertEquals(ctl, o);
778
779 final JexlContext context = new MapContext();
780 context.set("name", "Hello");
781 final String code = "return `${name + '\\n' + name}`;";
782 final JexlScript script = jexl.createScript(code);
783 o = script.execute(context);
784 ctl = "Hello\nHello";
785 Assertions.assertEquals(ctl, o);
786 }
787
788 @Test
789 void testIssue442() {
790 final JexlEngine jexl = new JexlBuilder().create();
791 final JexlContext context = new MapContext();
792 final String code = "var x = 'hello';\n" +
793 "function test(z) {\n" +
794
795 "`${x} ${z}`;\n" +
796 "}\n" +
797 "test('world');";
798 final JexlScript script = jexl.createScript(code);
799 final Object result = script.execute(context);
800 Assertions.assertEquals("hello world", result);
801 }
802
803
804 @Test
805 void testIssue447() {
806 final JexlEngine jexl = new JexlBuilder().create();
807 final String src = "const c = `${a}\n?= ${b}`; function foo(const left, const right) { `${left}\n?== ${right}` } c+foo(a, b)";
808 final JexlScript script = jexl.createScript(src, "a", "b");
809 final Object result = script.execute(null, "a", "b");
810 Assertions.assertEquals("a\n?= ba\n?== b", result);
811 String[] locals = script.getLocalVariables();
812 Assertions.assertArrayEquals(new String[]{"c", "foo"}, locals);
813 final String TEST447 = "src/test/scripts/test447.jexl";
814 final File src447 = new File(TEST447);
815 final JexlScript script447 = jexl.createScript(src447);
816 final Object result447 = script447.execute(null);
817 Assertions.assertInstanceOf(List.class, result447);
818 @SuppressWarnings("unchecked")
819 final List<Boolean> list = (List<Boolean>) result447;
820 for (final Boolean item : list) {
821 Assertions.assertTrue(item);
822 }
823 }
824
825 public static class BrkContext extends MapContext {
826 public BrkContext() {
827 super();
828 set("SYSTEM", System.class);
829 set("UNRESTRICTED", UNRESTRICTED);
830 }
831
832 public static Object brk(Object debug) {
833 return debug;
834 }
835
836 }
837
838 @Test
839 void test450a() {
840 JexlEngine jexl0 = new JexlBuilder().silent(false).permissions(JexlPermissions.RESTRICTED).create();
841 assertThrows(JexlException.Method.class, ()->jexl0.newInstance(
842 "org.apache.commons.jexl3.internal.introspection.Uberspect", null, null),
843 "should not be able to create Uberspect with RESTRICTED");
844 JexlPermissions perm = new JexlPermissions.ClassPermissions(org.apache.commons.jexl3.internal.introspection.Uberspect.class);
845 JexlEngine jexl1 = new JexlBuilder().silent(false).permissions(perm).create();
846 assertNotNull(jexl1.newInstance(
847 "org.apache.commons.jexl3.internal.introspection.Uberspect", null, null),
848 "should able to create Uberspect with Uberspect permission");
849
850 }
851
852 @Test
853 void test450b() {
854
855 assertThrows(JexlException.Method.class,
856 () -> run450b(JexlPermissions.RESTRICTED), "should not be able to load System with RESTRICTED");
857
858 assertEquals(java.lang.System.class, run450b(UNRESTRICTED));
859
860 JexlPermissions perm = new JexlPermissions.ClassPermissions(
861 getClass().getClassLoader().getClass(), org.apache.commons.jexl3.internal.introspection.Uberspect.class);
862 assertEquals(java.lang.System.class, run450b(perm));
863 }
864
865 private static Object run450b(JexlPermissions perm) {
866 JexlEngine jexl = new JexlBuilder().silent(false).permissions(perm).create();
867 String uscript = "new('org.apache.commons.jexl3.internal.introspection.Uberspect', null, null, perm).getClassLoader().loadClass('java.lang.System')";
868 JexlScript u0 = jexl.createScript(uscript, "perm");
869 return u0.execute(null, perm);
870 }
871
872 @Test
873 void test450c() {
874
875 assertNotNull(run450c(UNRESTRICTED));
876
877 JexlPermissions perm = new JexlPermissions.ClassPermissions(
878 JexlPermissions.ClassPermissions.class,
879 org.apache.commons.jexl3.internal.introspection.Uberspect.class);
880 assertNotNull(run450c(perm));
881
882 assertThrows(JxltEngine.Exception.class,
883 () -> run450c(JexlPermissions.RESTRICTED), "should not be able to load System with RESTRICTED");
884 }
885
886 private static Object run450c(JexlPermissions perm) {
887 JexlBuilder builder = new JexlBuilder().silent(false).permissions(perm);
888 Object result = new TemplateEngine(new Engine32(builder),false, 2, '$', '#').createExpression(
889 "${x = new ('org.apache.commons.jexl3.internal.introspection.Uberspect', null, null, UNRESTRICTED);" +
890 "sys = x?.getClassLoader()?.loadClass('java.lang.System') ?: SYSTEM;" +
891 "p = new('org.apache.commons.jexl3.introspection.JexlPermissions$ClassPermissions', [sys]);" +
892 "c = new('org.apache.commons.jexl3.internal.introspection.Uberspect', null, null, p);" +
893 "z = c.getMethod(sys,'currentTimeMillis').invoke(x,null);}"
894 ).evaluate(new BrkContext());
895 return result;
896 }
897
898 @Test
899 void test450() {
900 assertNotNull(run450(JexlPermissions.UNRESTRICTED),
901 "should be able to reach and invoke System::currentTimeMillis with UNRESTRICTED");
902 assertNotNull(run450(new JexlPermissions.ClassPermissions(org.apache.commons.jexl3.internal.TemplateEngine.class)),
903 "should be able to reach and invoke System::currentTimeMillis with TemplateEngine permission");
904 assertThrows(JexlException.Method.class,
905 () -> run450(RESTRICTED),
906 "should not be able to reach and invoke System::currentTimeMillis with RESTRICTED");
907 }
908
909 public static class Engine33 extends Engine32 {
910 public Engine33() {
911 this(createBuilder());
912 }
913 public Engine33(JexlBuilder builder) {
914 super(builder);
915 }
916 static JexlBuilder createBuilder() {
917 JexlPermissions perm = new JexlPermissions.ClassPermissions(
918 Issues400Test.class.getClassLoader().getClass(),
919 JexlPermissions.ClassPermissions.class,
920 org.apache.commons.jexl3.internal.TemplateEngine.class,
921 org.apache.commons.jexl3.internal.introspection.Uberspect.class);
922 return new JexlBuilder().safe(false).silent(false).permissions(perm);
923 }
924 }
925
926 private static Object run450(JexlPermissions perm) {
927 JexlEngine jexl = new JexlBuilder().silent(false).strict(true).safe(false).permissions(perm).create();
928 return jexl.createScript("new('org.apache.commons.jexl3.internal.TemplateEngine'," +
929 "new('org.apache.commons.jexl3.Issues400Test$Engine33'),false,256,'$'.charAt(0),'#'.charAt(0))" +
930 ".createExpression(" +
931 "\"#{x = new ('org.apache.commons.jexl3.internal.introspection.Uberspect', null, null);" +
932 "sys = x?.getClassLoader().loadClass('java.lang.System') ?: SYSTEM;" +
933 "p = new('org.apache.commons.jexl3.introspection.JexlPermissions$ClassPermissions', [sys]);" +
934 "c = new('org.apache.commons.jexl3.internal.introspection.Uberspect', null, null, p);" +
935 "z = c.getMethod(sys,'currentTimeMillis').invoke(x,null);}\")" +
936 ".evaluate(new('org.apache.commons.jexl3.Issues400Test$BrkContext'))").execute(null);
937 }
938
939 @Test
940 void test451() {
941 JexlEngine jexl = new JexlBuilder().create();
942 assertEquals("42",
943 jexl.createScript("o.toString()", "o").execute(null, "42"));
944 JexlPermissions perms = RESTRICTED.compose("java.lang { +Class { getSimpleName(); } }");
945 JexlSandbox sandbox = new JexlSandbox(false, true);
946 sandbox.permissions(Object.class.getName(), true, true, false, false);
947 sandbox.allow(String.class.getName()).execute("toString");
948 final JexlEngine jexl451 = new JexlBuilder().safe(false).silent(false).permissions(perms).sandbox(sandbox).create();
949
950 assertEquals("42",
951 jexl451.createScript("o.toString()", "o").execute(null, "42"));
952
953 assertThrows(JexlException.Method.class,
954 () -> jexl451.createScript("oo.getClass()", "oo").execute(null, "42"));
955
956 assertEquals(String.class,
957 jexl451.createScript("o.class", "o").execute(null, "42"));
958
959 assertEquals("Object",
960 jexl451.createScript("o.class.simpleName", "o").execute(null, new Object()));
961
962 assertThrows(JexlException.Property.class,
963 () -> jexl451.createScript("o.class.classLoader", "o").execute(null, new Object()));
964 }
965 }
966