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.internal.Util.debuggerCheck;
20 import static org.apache.commons.jexl3.introspection.JexlPermissions.RESTRICTED;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertFalse;
23 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
24 import static org.junit.jupiter.api.Assertions.assertNotEquals;
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.StringReader;
32 import java.io.StringWriter;
33 import java.lang.reflect.Proxy;
34 import java.math.MathContext;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.Collections;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.LinkedHashMap;
41 import java.util.LinkedHashSet;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.concurrent.atomic.AtomicInteger;
45 import java.util.stream.Collectors;
46 import java.util.stream.Stream;
47
48 import org.apache.commons.jexl3.internal.Engine32;
49 import org.apache.commons.jexl3.internal.OptionsContext;
50 import org.apache.commons.jexl3.introspection.JexlSandbox;
51 import org.junit.jupiter.api.Test;
52
53
54
55
56 class Issues300Test {
57 public static class Arithmetic383 extends JexlArithmetic {
58 public Arithmetic383(final boolean astrict) {
59 super(astrict);
60 }
61
62 @Override
63 public boolean isStrict(final JexlOperator op) {
64 switch (op) {
65 case NOT:
66 case CONDITION:
67 return false;
68 }
69 return super.isStrict(op);
70 }
71 }
72
73 public static class Arithmetic384 extends JexlArithmetic {
74 public Arithmetic384(final boolean astrict) {
75 super(astrict);
76 }
77
78 @Override
79 public boolean isStrict(final JexlOperator op) {
80 if (JexlOperator.ADD == op) {
81 return false;
82 }
83 return super.isStrict(op);
84 }
85 }
86
87 public static class Arithmetic384c extends JexlArithmetic {
88 AtomicInteger cmp = new AtomicInteger();
89
90 public Arithmetic384c(final boolean astrict) {
91 super(astrict);
92 }
93
94 public Arithmetic384c(final boolean astrict, final MathContext bigdContext, final int bigdScale) {
95 super(astrict, bigdContext, bigdScale);
96 }
97
98 @Override
99 protected int compare(final Object l, final Object r, final String op) {
100 cmp.incrementAndGet();
101 return super.compare(l, r, op);
102 }
103
104 int getCmpCalls() {
105 return cmp.get();
106 }
107 }
108
109 public static class Arithmetic384d extends Arithmetic384c {
110 public Arithmetic384d(final boolean astrict) {
111 super(astrict);
112 }
113
114 public Arithmetic384d(final boolean astrict, final MathContext bigdContext, final int bigdScale) {
115 super(astrict, bigdContext, bigdScale);
116 }
117 }
118
119 private static class Class397 implements Interface397i {
120 @Override
121 public String summary() {
122 return getClass().getName();
123 }
124 }
125
126 public static class Context0930 extends MapContext {
127
128
129
130
131
132
133
134 public Stream<?> filter(final Stream<?> stream, final JexlScript filter) {
135 return stream.filter(x -> Boolean.TRUE.equals(filter.execute(this, x)));
136 }
137 }
138
139
140
141
142 public static class Driver0930 {
143 private final String name;
144
145 Driver0930(final String n) {
146 name = n;
147 }
148
149 public String getAttributeName() {
150 return name;
151 }
152 }
153
154 public interface Interface397i {
155 String summary();
156 }
157
158 public static class Session322 {
159 public User322 getUser() {
160 return new User322();
161 }
162 }
163
164 public static class TestObject374 {
165 private String name;
166 private TestObject374 nested;
167
168 public String getName() {
169 return name;
170 }
171
172 public TestObject374 getNested() {
173 return nested;
174 }
175
176 public void setName(final String name) {
177 this.name = name;
178 }
179
180 public void setNested(final TestObject374 nested) {
181 this.nested = nested;
182 }
183 }
184
185 public enum Type375 {
186 DELIVERY_ADDRESS, DOMICILE
187 }
188
189 public static class User322 {
190 public String getName() {
191 return "user322";
192 }
193 }
194
195 public static class VaContext extends MapContext {
196 VaContext(final Map<String, Object> vars) {
197 super(vars);
198 }
199
200 public int cell(final List<?> l, final String... ms) {
201 return 42 + cell(ms);
202 }
203
204 public int cell(final String... ms) {
205 return ms.length;
206 }
207 }
208
209 public static class Var370 {
210 private String name;
211
212 public String getName() {
213 return name;
214 }
215
216 public void setName(final String s) {
217 name = s;
218 }
219 }
220
221 static JexlContext pragmaticContext() {
222 final JexlOptions opts = new JexlOptions();
223 opts.setFlags("-strict", "-cancellable", "-lexical", "-lexicalShade", "+safe", "+sharedInstance");
224 return new JexlTestCase.PragmaticContext(opts);
225 }
226
227 <T> T createProxy(final JexlEngine jexl, final Object o, final Class[] clazzz) {
228
229 return (T) Proxy.newProxyInstance(getClass().getClassLoader(), clazzz, (proxy, method, args) -> jexl.invokeMethod(o, method.getName(), args));
230 }
231
232 private Object run361a(final JexlEngine jexl) {
233 final String src = "()-> { ()-> { if (versionFile != null) { return 'foo'; } else { return 'bar'; }} }";
234 final JexlScript script = jexl.createScript(src);
235 final Object result = script.execute(null);
236 final JexlScript rs = (JexlScript) result;
237 return rs.execute(null);
238 }
239
240 private Object run361b(final JexlEngine jexl) {
241
242 final String src = "()-> { ()-> {" +
243 "var voa = vaf.value;\n" +
244 "if (voa != NaN && voa <= 0)" +
245 "{ return 'foo'; } else { return 'bar'; }" +
246 "} }";
247
248 final JexlContext context = new MapContext();
249 final Map<String, Object> vaf = Collections.singletonMap("value", null);
250 context.set("vaf", vaf);
251 final JexlScript script = jexl.createScript(src);
252 final Object result = script.execute(null);
253 final JexlScript rs = (JexlScript) result;
254 return rs.execute(context);
255 }
256
257 private String run361c(final JexlEngine jexl) {
258
259 final String src = "$$var t = null;\n" +
260 "$$if (t < 0) {\n" +
261 "'foo'\n" +
262 "$$} else {\n" +
263 "'bar'\n" +
264 "$$}";
265
266 final JxltEngine jxlt = jexl.createJxltEngine();
267 final JexlContext context = new MapContext();
268 final Map<String, Object> vaf = Collections.singletonMap("value", null);
269 context.set("vaf", vaf);
270 final JxltEngine.Template template = jxlt.createTemplate(src);
271 final StringWriter strw = new StringWriter();
272 template.evaluate(context, strw);
273 return strw.toString();
274 }
275
276 private Object run361d(final JexlEngine jexl) {
277 final String src = "var foo = 42; var foo = 43;";
278 final JexlScript script = jexl.createScript(src);
279 return script.execute(null);
280 }
281
282 @Test
283 void test301a() {
284 final JexlEngine jexl = new JexlBuilder().safe(false).arithmetic(new JexlArithmetic(false)).create();
285 final String[] srcs = { "var x = null; x.0", "var x = null; x[0]", "var x = [null,1]; x[0][0]" };
286 for (int i = 0; i < srcs.length; ++i) {
287 final String src = srcs[i];
288 final JexlScript s = jexl.createScript(src);
289 try {
290 final Object o = s.execute(null);
291 if (i > 0) {
292 fail(src + ": Should have failed");
293 }
294 } catch (final Exception ex) {
295 assertTrue(ex.getMessage().contains("x"));
296 }
297 }
298 }
299
300 @Test
301 void test302() {
302 final JexlContext jc = new MapContext();
303
304 final String[] strs = {
305 "{if (0) 1 else 2; var x = 4;}",
306 "if (0) 1; else 2; ",
307 "{ if (0) 1; else 2; }",
308 "{ if (0) { if (false) 1 else -3 } else 2; }"
309 };
310
311 final JexlEngine jexl = new JexlBuilder().create();
312 for (final String str : strs) {
313 final JexlScript e = jexl.createScript(str);
314 final Object o = e.execute(jc);
315 final int oo = ((Number) o).intValue() % 2;
316 assertEquals(0, oo, () -> "Block result is wrong " + str);
317 }
318 }
319
320 @Test
321 void test304() {
322 final JexlEngine jexlEngine = new JexlBuilder().strict(false).create();
323 JexlExpression e304 = jexlEngine.createExpression("overview.limit.var");
324
325 final Map<String, Object> map3 = new HashMap<>();
326 map3.put("var", "4711");
327 final Map<String, Object> map2 = new HashMap<>();
328 map2.put("limit", map3);
329 final Map<String, Object> map = new HashMap<>();
330 map.put("overview", map2);
331
332 final JexlContext context = new MapContext(map);
333 Object value = e304.evaluate(context);
334 assertEquals("4711", value);
335
336 map.clear();
337 map.put("overview.limit.var", 42);
338 value = e304.evaluate(context);
339 assertEquals(42, value);
340
341
342 final String[] keywords = {
343 "if", "else", "do", "while", "for", "break", "continue", "function", "return", "new", "size", "empty",
344 "var", "let", "const",
345 "null", "true", "false",
346 "not", "div", "mod", "and", "or",
347 "eq", "ne", "lt", "gt", "ge", "le",
348 };
349
350 for (final String keyword : keywords) {
351 final String pkw = "e304." + keyword;
352 map.put(pkw, 42);
353 e304 = jexlEngine.createExpression(pkw);
354 value = e304.evaluate(context);
355 assertEquals(42, value);
356 }
357 for (int i = 0; i < keywords.length; ++i) {
358 final String pkw = "e304." + keywords[i] + "." + keywords[keywords.length - 1 - i];
359 map.put(pkw, 42);
360 e304 = jexlEngine.createExpression(pkw);
361 value = e304.evaluate(context);
362 assertEquals(42, value);
363 }
364 final String allkw = "e304." + String.join(".", keywords);
365 map.put(allkw, 42);
366 e304 = jexlEngine.createExpression(allkw);
367 value = e304.evaluate(context);
368 assertEquals(42, value);
369 }
370
371 @Test
372 void test305() {
373 final JexlEngine jexl = new JexlBuilder().create();
374 JexlScript e;
375 e = jexl.createScript("{while(false) {}; var x = 1;}");
376 final String str0 = e.getParsedText();
377 e = jexl.createScript(str0);
378 assertNotNull(e);
379 final String str1 = e.getParsedText();
380 assertEquals(str0, str1);
381 }
382
383 @Test
384 void test306() {
385 final JexlContext ctxt = new MapContext();
386 final JexlEngine jexl = new JexlBuilder().create();
387 final JexlScript e = jexl.createScript("x.y ?: 2");
388 final Object o1 = e.execute(null);
389 assertEquals(2, o1);
390 ctxt.set("x.y", null);
391 final Object o2 = e.execute(ctxt);
392 assertEquals(2, o2);
393 }
394
395 @Test
396 void test306a() {
397 final JexlEngine jexl = new JexlBuilder().create();
398 final JexlScript e = jexl.createScript("x.y ?: 2", "x");
399 Object o = e.execute(null, new Object());
400 assertEquals(2, o);
401 o = e.execute(null);
402 assertEquals(2, o);
403 }
404
405 @Test
406 void test306b() {
407 final JexlEngine jexl = new JexlBuilder().create();
408 final JexlScript e = jexl.createScript("x?.y ?: 2", "x");
409 final Object o1 = e.execute(null, new Object());
410 assertEquals(2, o1);
411 final Object o2 = e.execute(null);
412 assertEquals(2, o2);
413 }
414
415 @Test
416 void test306c() {
417 final JexlEngine jexl = new JexlBuilder().safe(true).create();
418 final JexlScript e = jexl.createScript("x.y ?: 2", "x");
419 Object o = e.execute(null, new Object());
420 assertEquals(2, o);
421 o = e.execute(null);
422 assertEquals(2, o);
423 }
424
425 @Test
426 void test306d() {
427 final JexlEngine jexl = new JexlBuilder().safe(true).create();
428 final JexlScript e = jexl.createScript("x.y[z.t] ?: 2", "x");
429 Object o = e.execute(null, new Object());
430 assertEquals(2, o);
431 o = e.execute(null);
432 assertEquals(2, o);
433 }
434
435 @Test
436 void test309a() {
437
438 final String src = "<html lang=\"en\">\n"
439 + " <body>\n"
440 + " <h1>Hello World!</h1>\n"
441 + "$$ var i = 12++;\n"
442 + " </body>\n"
443 + "</html>";
444
445 final JexlEngine jexl = new JexlBuilder().safe(true).create();
446 final JxltEngine jxlt = jexl.createJxltEngine();
447 final JexlInfo info = new JexlInfo("template", 1, 1);
448 final JexlException.Parsing xerror = assertThrows(JexlException.Parsing.class, () -> jxlt.createTemplate(info, src));
449 assertEquals(4, xerror.getInfo().getLine());
450 }
451
452 @Test
453 void test309b() {
454
455 final String src = "<html lang=\"en\">\n"
456 + " <body>\n"
457 + " <h1>Hello World!</h1>\n"
458 + "$$ var i = a b c;\n"
459 + " </body>\n"
460 + "</html>";
461
462 final JexlEngine jexl = new JexlBuilder().safe(true).create();
463 final JxltEngine jxlt = jexl.createJxltEngine();
464 final JexlInfo info = new JexlInfo("template", 1, 1);
465 final JexlException.Parsing xerror = assertThrows(JexlException.Parsing.class, () -> jxlt.createTemplate(info, src));
466 assertEquals(4, xerror.getInfo().getLine());
467 }
468
469 @Test
470 void test309c() {
471
472 final String src = "<html lang=\"en\">\n"
473 + " <body>\n"
474 + " <h1>Hello World!</h1>\n"
475 + "$$ var i =12;\n"
476 + " </body>\n"
477 + "</html>";
478
479 final JexlEngine jexl = new JexlBuilder().safe(true).create();
480 final JxltEngine jxlt = jexl.createJxltEngine();
481 final JexlInfo info = new JexlInfo("template", 1, 1);
482 final JxltEngine.Template tmplt = jxlt.createTemplate(info, src);
483 final String src1 = tmplt.asString();
484 final String src2 = tmplt.toString();
485 assertEquals(src1, src2);
486 }
487
488 @Test
489 void test314() {
490 final JexlEngine jexl = new JexlBuilder().strict(true).safe(false).create();
491 final Map<String, Object> vars = new HashMap<>();
492 final JexlContext ctxt = new VaContext(vars);
493 JexlScript script;
494 Object result;
495 script = jexl.createScript("cell()");
496 result = script.execute(ctxt);
497 assertEquals(0, result);
498 script = jexl.createScript("x.cell()", "x");
499 result = script.execute(ctxt, Arrays.asList(10, 20));
500 assertEquals(42, result);
501 script = jexl.createScript("cell('1', '2')");
502 result = script.execute(ctxt);
503 assertEquals(2, result);
504 script = jexl.createScript("x.cell('1', '2')", "x");
505 result = script.execute(ctxt, Arrays.asList(10, 20));
506 assertEquals(44, result);
507
508 vars.put("TVALOGAR", null);
509 String jexlExp = "TVALOGAR==null ?'SIMON':'SIMONAZO'";
510 script = jexl.createScript(jexlExp);
511 result = script.execute(ctxt);
512 assertEquals("SIMON", result);
513
514 jexlExp = "TVALOGAR.PEPITO==null ?'SIMON':'SIMONAZO'";
515 script = jexl.createScript(jexlExp);
516
517 final Map<String, Object> tva = new LinkedHashMap<>();
518 tva.put("PEPITO", null);
519 vars.put("TVALOGAR", tva);
520 result = script.execute(ctxt);
521 assertEquals("SIMON", result);
522
523 vars.remove("TVALOGAR");
524 ctxt.set("TVALOGAR.PEPITO", null);
525 result = script.execute(ctxt);
526 assertEquals("SIMON", result);
527 }
528
529 @Test
530 void test315() {
531 final JexlEngine jexl = new JexlBuilder().strict(true).create();
532 final Map<String, Object> vars = new HashMap<>();
533 final JexlContext ctxt = new VaContext(vars);
534 JexlScript script;
535 Object result;
536 script = jexl.createScript("a?? 42 + 10", "a");
537 result = script.execute(ctxt, 32);
538 assertEquals(32, result);
539 result = script.execute(ctxt, (Object) null);
540 assertEquals(52, result);
541 script = jexl.createScript("- a??42 + +10", "a");
542 result = script.execute(ctxt, 32);
543 assertEquals(-32, result);
544 result = script.execute(ctxt, (Object) null);
545 assertEquals(52, result);
546
547 script = jexl.createScript("a? a : +42 + 10", "a");
548 result = script.execute(ctxt, 32);
549 assertEquals(32, result);
550 result = script.execute(ctxt, (Object) null);
551 assertEquals(52, result);
552
553 script = jexl.createScript("a ?: +42 + 10", "a");
554 result = script.execute(ctxt, 32);
555 assertEquals(32, result);
556 result = script.execute(ctxt, (Object) null);
557 assertEquals(52, result);
558 }
559
560 @Test
561 void test317() {
562 final JexlEngine jexl = new JexlBuilder().strict(true).create();
563 final JexlContext ctxt = new MapContext();
564 JexlScript script;
565 Object result;
566 JexlInfo info = new JexlInfo("test317", 1, 1);
567
568 script = jexl.createScript(info, "var f = "
569 + "()-> {x + x }; f",
570 "x");
571
572 result = script.execute(ctxt, 21);
573 assertInstanceOf(JexlScript.class, result);
574 script = (JexlScript) result;
575 info = JexlInfo.from(script);
576 assertNotNull(info);
577 assertEquals("test317", info.getName());
578 result = script.execute(ctxt, 21);
579 assertEquals(42, result);
580 }
581
582 @Test
583 void test322a() {
584 final JexlEngine jexl = new JexlBuilder().strict(true).create();
585 final JxltEngine jxlt = jexl.createJxltEngine();
586 final JexlContext context = new MapContext();
587
588 final String[] ins = { "${'{'}", "${\"{\"}", "${\"{}\"}", "${'{42}'}", "${\"{\\\"\\\"}\"}" };
589 final String[] ctls = { "{", "{", "{}", "{42}", "{\"\"}" };
590 StringWriter strw;
591 JxltEngine.Template template;
592 String output;
593
594 for (int i = 0; i < ins.length; ++i) {
595 final String src = ins[i];
596 template = jxlt.createTemplate("$$", new StringReader(src));
597 strw = new StringWriter();
598 template.evaluate(context, strw);
599 output = strw.toString();
600 assertEquals(ctls[i], output);
601 }
602 }
603
604 @Test
605 void test322b() {
606 final JexlContext ctxt = new MapContext();
607 final String src = "L'utilisateur ${session.user.name} s'est connecte";
608 final JexlEngine jexl = new JexlBuilder().strict(true).create();
609 final JxltEngine jxlt = jexl.createJxltEngine();
610 StringWriter strw;
611 JxltEngine.Template template;
612 String output;
613 template = jxlt.createTemplate("$$", new StringReader(src));
614
615 ctxt.set("session", new Session322());
616 strw = new StringWriter();
617 template.evaluate(ctxt, strw);
618 output = strw.toString();
619 assertEquals("L'utilisateur user322 s'est connecte", output);
620
621 ctxt.set("session.user", new User322());
622 strw = new StringWriter();
623 template.evaluate(ctxt, strw);
624 output = strw.toString();
625 assertEquals("L'utilisateur user322 s'est connecte", output);
626
627 ctxt.set("session.user.name", "user322");
628 strw = new StringWriter();
629 template.evaluate(ctxt, strw);
630 output = strw.toString();
631 assertEquals("L'utilisateur user322 s'est connecte", output);
632 }
633
634 @Test
635 void test323() {
636 final JexlEngine jexl = new JexlBuilder().safe(false).create();
637 final Map<String, Object> vars = new HashMap<>();
638 final JexlContext jc = new MapContext(vars);
639 Object result;
640
641
642 final JexlScript script0 = jexl.createScript("a.n.t.variable");
643 JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> script0.execute(jc), "a.n.t.variable is undefined!");
644 assertTrue(xvar.toString().contains("a.n.t"));
645
646
647 jc.set("a.n.t.variable", null);
648 final JexlScript script = jexl.createScript("a.n.t.variable");
649 result = script.execute(jc);
650 assertNull(result);
651
652
653 jc.set("a.n.t", null);
654 final JexlScript script1 = jexl.createScript("a.n.t[0].variable");
655 xvar = assertThrows(JexlException.Variable.class, () -> script1.execute(jc), "a.n.t is null!");
656 assertTrue(xvar.toString().contains("a.n.t"));
657
658
659 vars.remove("a.n.t");
660 final JexlScript script2 = jexl.createScript("a.n.t[0].variable");
661 xvar = assertThrows(JexlException.Variable.class, () -> script2.execute(jc), "a.n.t is undefined!");
662 assertTrue(xvar.toString().contains("a.n.t"));
663
664
665 final List<Object> inner = new ArrayList<>();
666 vars.put("a.n.t", inner);
667 final JexlScript script3 = jexl.createScript("a.n.t[0].variable");
668 JexlException.Property xprop = assertThrows(JexlException.Property.class, () -> script3.execute(jc), "a.n.t is null!");
669 assertTrue(xprop.toString().contains("0"));
670
671
672 inner.add(42);
673 final JexlScript script4 = jexl.createScript("a.n.t[0].variable");
674 xprop = assertThrows(JexlException.Property.class, () -> script4.execute(jc), "a.n.t is null!");
675 assertTrue(xprop.toString().contains("variable"));
676 }
677
678 @Test
679 void test324() {
680 final JexlEngine jexl = new JexlBuilder().create();
681 final String src42 = "new('java.lang.Integer', 42)";
682 final JexlExpression expr0 = jexl.createExpression(src42);
683 assertEquals(42, expr0.evaluate(null));
684 final String parsed = expr0.getParsedText();
685 assertEquals(src42, parsed);
686 final JexlException.Parsing xparse = assertThrows(JexlException.Parsing.class, () -> jexl.createExpression("new()"), "should not parse");
687 assertTrue(xparse.toString().contains(")"));
688 }
689
690 @Test
691 void test325() {
692 final JexlEngine jexl = new JexlBuilder().safe(false).create();
693 final Map<String, Object> map = new HashMap<String, Object>() {
694 private static final long serialVersionUID = 1L;
695
696 @Override
697 public Object get(final Object key) {
698 return super.get(key == null ? "" : key);
699 }
700
701 @Override
702 public Object put(final String key, final Object value) {
703 return super.put(key == null ? "" : key, value);
704 }
705 };
706 map.put("42", 42);
707 final JexlContext jc = new MapContext();
708 JexlScript script;
709 Object result;
710
711 script = jexl.createScript("map[null] = 42", "map");
712 result = script.execute(jc, map);
713 assertEquals(42, result);
714 script = jexl.createScript("map[key]", "map", "key");
715 result = script.execute(jc, map, null);
716 assertEquals(42, result);
717 result = script.execute(jc, map, "42");
718 assertEquals(42, result);
719 }
720
721 @Test
722 void test330() {
723 final JexlEngine jexl = new JexlBuilder().create();
724
725
726
727 final String longExpression = ""
728 +
729 "'THIS IS A VERY VERY VERY VERY VERY VERY VERY "
730 +
731 "VERY VERY LONG STRING CONCATENATION ' + VARIABLE ' <--- "
732 +
733 "error: missing + between VARIABLE and literal'";
734
735 final JexlException.Parsing xparse = assertThrows(JexlException.Parsing.class, () -> jexl.createExpression(longExpression),
736 "parsing malformed expression did not throw exception");
737 assertTrue(xparse.getMessage().contains("VARIABLE"));
738 }
739
740 @Test
741 void test331() {
742 final JexlEngine jexl = new JexlBuilder().create();
743 final JexlContext ctxt = new MapContext();
744 JexlScript script;
745 Object result;
746 script = jexl.createScript("a + '\\n' + b", "a", "b");
747 result = script.execute(ctxt, "hello", "world");
748 assertTrue(result.toString().contains("\n"));
749 }
750
751 @Test
752 void test347() {
753 final String src = "A.B == 5";
754 JexlEngine jexl = new JexlBuilder().safe(true).create();
755 final JexlScript script = jexl.createScript(src);
756 Object result = script.execute(null);
757
758 assertFalse((Boolean) result);
759
760 jexl = new JexlBuilder().strict(true).safe(false).create();
761 final JexlContext ctxt = new MapContext();
762 final JexlScript script1 = jexl.createScript(src);
763
764 assertThrows(JexlException.class, () -> script1.execute(ctxt));
765
766 ctxt.set("A", null);
767 assertThrows(JexlException.class, () -> script1.execute(ctxt), "should only succeed with safe navigation");
768
769 ctxt.set("A.B", null);
770 result = script1.execute(ctxt);
771 assertFalse((Boolean) result);
772 }
773
774 @Test
775 void test349() {
776 final String text = "(A ? C.D : E)";
777 final JexlEngine jexl = new JexlBuilder().safe(true).create();
778 final JexlExpression expr = jexl.createExpression(text);
779 final JexlScript script = jexl.createScript(text);
780 }
781
782 @Test
783 void test361_33() {
784 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).create();
785 assertThrows(JexlException.class, () -> run361c(jexl), "null arg should fail");
786 }
787
788 @Test
789 void test361a_32() {
790 final JexlEngine jexl = new Engine32(new JexlBuilder().safe(false));
791 final Object result = run361a(jexl);
792 assertNotNull(result);
793 }
794
795 @Test
796 void test361a_33() {
797 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).create();
798 assertThrows(JexlException.class, () -> run361a(jexl), "null arg should fail");
799 }
800
801 @Test
802 void test361b_32() {
803 final JexlEngine jexl = new Engine32(new JexlBuilder().safe(false).strict(false));
804 final Object result = run361b(jexl);
805 assertNotNull(result);
806 }
807
808 @Test
809 void test361b_33() {
810 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).create();
811 assertThrows(JexlException.class, () -> run361b(jexl), "null arg should fail");
812 }
813
814 @Test
815 void test361c_32() {
816 final JexlEngine jexl = new Engine32(new JexlBuilder().safe(false).strict(false));
817 final String result = run361c(jexl);
818 assertNotNull(result);
819 }
820
821 @Test
822 void test361d_32() {
823 final JexlEngine jexl = new Engine32(new JexlBuilder().lexical(false).lexicalShade(false).safe(false));
824 final Object result = run361d(jexl);
825 assertNotNull(result);
826 }
827
828 @Test
829 void test361d_33() {
830 final JexlEngine jexl = new JexlBuilder().lexical(true).lexicalShade(true).safe(false).strict(true).create();
831 assertThrows(JexlException.class, () -> run361d(jexl), "null arg should fail");
832 }
833
834 @Test
835 void test367() {
836 final String text = "var toto; function foo(x) { x }; var tata = 3; foo(3)";
837 final JexlEngine jexl = new JexlBuilder().safe(true).create();
838 final JexlScript script = jexl.createScript(text);
839 final Object result = script.execute(null);
840 assertEquals(3, result);
841 final String s0 = script.getParsedText();
842 final String s1 = script.getSourceText();
843 assertNotEquals(s0, s1);
844 }
845
846 @Test
847 void test370() {
848 final Var370 var370 = new Var370();
849 final JexlEngine jexl = new JexlBuilder().safe(true).create();
850 final ObjectContext<Var370> ctxt = new ObjectContext<>(jexl, var370);
851 final JexlExpression get = jexl.createExpression("name");
852
853 var370.setName("John");
854 assertEquals("John", get.evaluate(ctxt));
855 assertTrue(ctxt.has("name"));
856
857 var370.setName(null);
858 assertNull(get.evaluate(ctxt));
859 assertTrue(ctxt.has("name"));
860
861 final JexlExpression get1 = jexl.createExpression("phone");
862 assertFalse(ctxt.has("phone"));
863 final JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> get1.evaluate(ctxt), "phone should be undefined!");
864 assertEquals("phone", xvar.getVariable());
865 }
866
867 @Test
868 void test373b() {
869 final String src = "var i = ++1";
870 final JexlEngine jexl = new JexlBuilder().safe(true).create();
871 final JexlInfo info = new JexlInfo("badscript", 0, 0);
872 final JexlException.Parsing xparse = assertThrows(JexlException.Parsing.class, () -> jexl.createScript(info, src), "should not parse");
873 assertTrue(xparse.getMessage().contains("badscript"));
874 }
875
876 @Test
877 void test374() {
878 final JexlEngine engine = new JexlBuilder().cache(512).strict(true).silent(false).antish(false).safe(false).create();
879
880 final JexlExpression expr = engine.createExpression("nested.name");
881
882 final TestObject374 myObject = new TestObject374();
883 myObject.setName("John");
884 final JexlContext context = new ObjectContext<>(engine, myObject);
885
886 assertThrows(JexlException.class, () -> expr.evaluate(context));
887 }
888
889 @Test
890 void test375() {
891 final JexlSandbox jexlSandbox = new JexlSandbox(false);
892 jexlSandbox.allow(Type375.class.getName());
893 final JexlEngine engine = new JexlBuilder().sandbox(jexlSandbox).create();
894
895 final JexlContext context = new MapContext();
896 context.set("Type", Type375.class);
897
898 Object result = engine.createScript("Type.valueOf('DOMICILE')").execute(context);
899 assertEquals(Type375.DOMICILE, result);
900
901 result = engine.createScript("Type.DOMICILE").execute(context);
902 assertEquals(Type375.DOMICILE, result);
903 }
904
905 @Test
906 void test377() {
907 final String text = "function add(x, y) { x + y } add(a, b)";
908 final JexlEngine jexl = new JexlBuilder().safe(true).create();
909 final JexlScript script = jexl.createScript(text, "a", "b");
910 final Object result = script.execute(null, 20, 22);
911 assertEquals(42, result);
912 }
913
914 @Test
915 void test379a() {
916
917 final String src =
918 "#pragma jexl.import java.util\n"+
919 "const map = new LinkedHashMap({0 : 'zero'});";
920
921 final JexlEngine jexl = new JexlBuilder().safe(true).create();
922 final JexlScript script = jexl.createScript(src);
923 assertNotNull(script);
924 final Object result = script.execute(null);
925 assertNotNull(result);
926 assertInstanceOf(LinkedHashMap.class, result);
927 assertEquals(1, ((Map) result).size());
928 }
929
930 @Test
931 void test383() {
932 final JexlEngine jexl = new JexlBuilder().safe(false).arithmetic(new Arithmetic383(true)).create();
933 final String src0 = "if (a) 1; else 2;";
934 final String src1 = "if (!a) 1; else 2;";
935
936 final JexlScript s0 = jexl.createScript(src0, "a");
937 final JexlScript s1 = jexl.createScript(src1, "a");
938 assertEquals(2, s0.execute(null, (Object) null));
939 assertEquals(1, s1.execute(null, (Object) null));
940
941 final JexlScript s2 = jexl.createScript(src0);
942 final JexlScript s3 = jexl.createScript(src1);
943 JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> s2.execute(null, (Object) null));
944 assertEquals("a", xvar.getVariable());
945 xvar = assertThrows(JexlException.Variable.class, () -> s3.execute(null, (Object) null));
946 assertEquals("a", xvar.getVariable());
947
948
949 final MapContext ctxt = new MapContext();
950 ctxt.set("a", null);
951 assertEquals(2, s2.execute(ctxt, (Object) null));
952 assertEquals(1, s3.execute(ctxt, (Object) null));
953 }
954
955 @Test
956 void test384a() {
957 final JexlEngine jexl = new JexlBuilder().safe(false).strict(true).create();
958
959 for (final String src0 : Arrays.asList("'ABC' + null", "null + 'ABC'")) {
960 final JexlContext ctxt = new MapContext();
961 final JexlScript s0 = jexl.createScript(src0);
962 final JexlException xvar = assertThrows(JexlException.class, () -> s0.execute(ctxt, (Object) null), "null argument should throw");
963 assertTrue(xvar.toString().contains("+"));
964 }
965
966 for (final String src1 : Arrays.asList("'ABC' + a", "a + 'ABC'")) {
967 final JexlContext ctxt = new MapContext();
968 final JexlScript s1 = jexl.createScript(src1, "a");
969 JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> s1.execute(ctxt, (Object) null), "null argument should throw");
970 assertEquals("a", xvar.getVariable());
971
972 final JexlScript s2 = jexl.createScript(src1);
973 xvar = assertThrows(JexlException.Variable.class, () -> s2.execute(ctxt, (Object) null), "null argument should throw");
974 assertEquals("a", xvar.getVariable());
975 assertTrue(xvar.isUndefined());
976
977 ctxt.set("a", null);
978 xvar = assertThrows(JexlException.Variable.class, () -> s2.execute(ctxt, (Object) null), "null argument should throw");
979 assertEquals("a", xvar.getVariable());
980 assertFalse(xvar.isUndefined());
981 }
982 }
983
984 @Test
985 void test384b() {
986
987
988 final JexlEngine jexl = new JexlBuilder()
989 .arithmetic(new Arithmetic384(true))
990 .safe(false)
991 .strict(true)
992 .create();
993
994
995 for (final String src0 : Arrays.asList("'ABC' + null", "null + 'ABC'")) {
996 final JexlContext ctxt = new MapContext();
997 final JexlScript s0 = jexl.createScript(src0);
998 assertEquals("ABC", s0.execute(ctxt));
999 }
1000
1001 for (final String src1 : Arrays.asList("'ABC' + a", "a + 'ABC'")) {
1002 final JexlContext ctxt = new MapContext();
1003 final JexlScript s1 = jexl.createScript(src1, "a");
1004 assertEquals("ABC", s1.execute(ctxt, (Object) null));
1005
1006 final JexlScript s2 = jexl.createScript(src1);
1007 final JexlException.Variable xvar = assertThrows(JexlException.Variable.class, () -> s2.execute(ctxt, (Object) null), "null argument should throw");
1008 assertEquals("a", xvar.getVariable());
1009 assertTrue(xvar.isUndefined());
1010
1011
1012 ctxt.set("a", null);
1013 assertEquals("ABC", s1.execute(ctxt, (Object) null));
1014 }
1015 }
1016
1017 @Test
1018 void test384c() {
1019 final Arithmetic384c ja = new Arithmetic384c(true);
1020
1021 final JexlEngine jexl = new JexlBuilder()
1022 .safe(false)
1023 .strict(true)
1024 .arithmetic(ja)
1025 .create();
1026
1027 assertTrue(ja.toBoolean(jexl.createExpression("3 < 4").evaluate(null)));
1028 assertTrue(ja.toBoolean(jexl.createExpression("6 <= 8").evaluate(null)));
1029 assertFalse(ja.toBoolean(jexl.createExpression("6 == 7").evaluate(null)));
1030 assertTrue(ja.toBoolean(jexl.createExpression("4 > 2").evaluate(null)));
1031 assertTrue(ja.toBoolean(jexl.createExpression("8 > 6").evaluate(null)));
1032 assertTrue(ja.toBoolean(jexl.createExpression("7 != 6").evaluate(null)));
1033 assertEquals(6, ja.getCmpCalls());
1034 }
1035
1036 @Test
1037 void test384d() {
1038 final Arithmetic384c ja = new Arithmetic384d(true);
1039
1040 final JexlEngine jexl = new JexlBuilder()
1041 .safe(false)
1042 .strict(true)
1043 .arithmetic(ja)
1044 .create();
1045
1046 assertTrue(ja.toBoolean(jexl.createExpression("3 < 4").evaluate(null)));
1047 assertTrue(ja.toBoolean(jexl.createExpression("6 <= 8").evaluate(null)));
1048 assertFalse(ja.toBoolean(jexl.createExpression("6 == 7").evaluate(null)));
1049 assertTrue(ja.toBoolean(jexl.createExpression("4 > 2").evaluate(null)));
1050 assertTrue(ja.toBoolean(jexl.createExpression("8 > 6").evaluate(null)));
1051 assertTrue(ja.toBoolean(jexl.createExpression("7 != 6").evaluate(null)));
1052 assertEquals(6, ja.getCmpCalls());
1053 }
1054
1055 @Test
1056 void test390() throws Exception {
1057
1058 final JexlEngine jexl = new JexlBuilder()
1059 .safe(false)
1060 .strict(true)
1061 .create();
1062
1063 JexlScript script = null;
1064 final String src = "if (true) #pragma one 42";
1065 final JexlException.Parsing xparse = assertThrows(JexlException.Parsing.class, () -> jexl.createScript(src), "should have failed parsing");
1066 assertTrue(xparse.getDetail().contains("pragma"));
1067
1068 final String src1 = "if (true) { #pragma one 42 }";
1069 script = jexl.createScript(src1);
1070 final Object result = script.execute(null);
1071 debuggerCheck(jexl);
1072 }
1073
1074 @Test
1075 void test393() {
1076
1077 final String src = "const total = 0;\n" +
1078 "if (true) {\n" +
1079 " total = 1;\n" +
1080 "}\n" +
1081 "total; ";
1082 final JexlEngine jexl = new JexlBuilder()
1083 .safe(false)
1084 .strict(true)
1085 .create();
1086
1087 final JexlException.Parsing xparse = assertThrows(JexlException.Parsing.class, () -> jexl.createScript(src), "should fail on const total assignment");
1088 assertTrue(xparse.getMessage().contains("total"));
1089 }
1090
1091 @Test
1092 void testBackslashes() {
1093 final JexlEngine jexl = new JexlBuilder().safe(false).create();
1094 final String src = "\"\b\t\f\"";
1095 JexlScript s = jexl.createScript(src);
1096 assertNotNull(s);
1097 final String ctl = "\b\t\f";
1098 assertEquals(ctl, s.execute(null));
1099 String parsed = s.getParsedText();
1100 assertEquals("'\\b\\t\\f'", parsed);
1101 s = jexl.createScript(src);
1102 assertNotNull(s);
1103 assertEquals(ctl, s.execute(null));
1104 parsed = s.getParsedText();
1105 assertEquals("'\\b\\t\\f'", parsed);
1106 }
1107
1108 @Test
1109 void testDow() {
1110
1111 final String src = "(y, m, d)->{\n" +
1112 "// will return 0 for Sunday, 6 for Saturday\n" +
1113 "const t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4];\n"+
1114 "if (m < 3) { --y }\n" +
1115 "(y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;\n" +
1116 "}";
1117
1118 final JexlEngine jexl = new JexlBuilder().create();
1119 final JexlScript script = jexl.createScript(src);
1120 Object r = script.execute(null, 2023, 3, 1);
1121 assertInstanceOf(Number.class, r);
1122 Number dow = (Number) r;
1123 assertEquals(3, dow.intValue());
1124 r = script.execute(null, 1969, 7, 20);
1125 assertInstanceOf(Number.class, r);
1126 dow = (Number) r;
1127 assertEquals(0, dow.intValue());
1128 }
1129
1130 @Test
1131 void testIssue394() {
1132 final StringBuilder x = new StringBuilder("foobar");
1133 assertEquals("foobar", x.toString());
1134 final String src = "x -> x.setLength(3)";
1135 final JexlEngine jexl = new JexlBuilder().create();
1136 final JexlScript script = jexl.createScript(src);
1137 final Object result = script.execute(null, x);
1138 assertEquals("foo", x.toString());
1139 }
1140
1141 @Test
1142 void testIssue397() {
1143 String result;
1144 final String control = Class397.class.getName();
1145 final JexlEngine jexl = new JexlBuilder().permissions(RESTRICTED).create();
1146
1147 final Interface397i instance = new Class397();
1148 result = (String) jexl.invokeMethod(instance, "summary");
1149 assertEquals(control, result);
1150
1151 final Interface397i proxy = createProxy(jexl, instance, new Class[] { Interface397i.class });
1152 result = (String) jexl.invokeMethod(proxy, "summary");
1153 assertEquals(control, result);
1154
1155 final JexlScript script = jexl.createScript("dan.summary()", "dan");
1156 result = (String) script.execute(null, instance);
1157 assertEquals(control, result);
1158 result = (String) script.execute(null, proxy);
1159 assertEquals(control, result);
1160 }
1161
1162 @Test
1163 void testIssue398a() {
1164
1165 final String src = "let m = {\n" +
1166 " \"foo\": 1,\n" +
1167 " \"bar\": 2,\n" +
1168 "}";
1169
1170 final JexlEngine jexl = new JexlBuilder().create();
1171 final JexlScript script = jexl.createScript(src);
1172 final Object result = script.execute(null);
1173 assertInstanceOf(Map.class, result);
1174 final Map<?, ?> map = (Map<?, ?>) result;
1175 assertEquals(2, map.size());
1176 }
1177
1178 @Test
1179 void testIssue398b() {
1180 final Map<String, Object> foo = Collections.singletonMap("X", "x");
1181 final Map<String, Object> bar = Collections.singletonMap("Y", "y");
1182 final JexlContext ctxt = new MapContext();
1183 ctxt.set("foo", foo);
1184 ctxt.set("bar", bar);
1185
1186 final String src = "let m = {\n" +
1187 " foo.X: 1,\n" +
1188 " bar.Y: 2,\n" +
1189 "}";
1190
1191 final JexlEngine jexl = new JexlBuilder().create();
1192 JexlScript script = jexl.createScript(src);
1193 Object result = script.execute(ctxt);
1194 assertInstanceOf(Map.class, result);
1195 Map<?, ?> map = (Map<?, ?>) result;
1196 assertEquals(2, map.size());
1197 assertEquals(1, map.get("x"));
1198 assertEquals(2, map.get("y"));
1199
1200 script = jexl.createScript(src, "foo", "bar");
1201 result = script.execute(null, foo, bar);
1202 assertInstanceOf(Map.class, result);
1203 map = (Map<?, ?>) result;
1204 assertEquals(2, map.size());
1205 assertEquals(1, map.get("x"));
1206 assertEquals(2, map.get("y"));
1207 }
1208
1209 @Test
1210 void testIssue398c() {
1211 final JexlEngine jexl = new JexlBuilder().create();
1212 final Object empty = jexl.createScript("[,...]").execute(null);
1213 assertNotNull(empty);
1214 assertTrue(jexl.createScript("[1]").execute(null) instanceof int[]);
1215 assertTrue(jexl.createScript("[1,...]").execute(null) instanceof ArrayList<?>);
1216 assertTrue(jexl.createScript("{1}").execute(null) instanceof HashSet<?>);
1217 assertTrue(jexl.createScript("{1,...}").execute(null) instanceof LinkedHashSet<?>);
1218 assertTrue(jexl.createScript("{'one': 1}").execute(null) instanceof HashMap<?, ?>);
1219 assertTrue(jexl.createScript("{'one': 1,...}").execute(null) instanceof LinkedHashMap<?, ?>);
1220 }
1221
1222 @Test
1223 void testPropagateOptions() {
1224
1225 final String src0 = "`${$options.strict?'+':'-'}strict"
1226 + " ${$options.cancellable?'+':'-'}cancellable"
1227 + " ${$options.lexical?'+':'-'}lexical"
1228 + " ${$options.lexicalShade?'+':'-'}lexicalShade"
1229 + " ${$options.sharedInstance?'+':'-'}sharedInstance"
1230 + " ${$options.safe?'+':'-'}safe`";
1231
1232 final String text = "#pragma script.mode pro50\n" + "()->{ ()->{ " + src0 + "; } }";
1233 final JexlEngine jexl = new JexlBuilder().safe(true).create();
1234 final JexlScript script = jexl.createScript(text);
1235 JexlContext context = pragmaticContext();
1236 final JexlScript closure = (JexlScript) script.execute(context);
1237 final JexlContext opts = new OptionsContext();
1238 final Object result = closure.execute(opts);
1239 assertEquals("+strict +cancellable +lexical +lexicalShade -sharedInstance -safe", result);
1240
1241 final String text0 = "#pragma script.mode pro50\n" + "()->{ " + src0 + "; }";
1242 final JexlScript script0 = jexl.createScript(text0);
1243 context = pragmaticContext();
1244 final Object result0 = script0.execute(context);
1245 assertEquals("+strict +cancellable +lexical +lexicalShade -sharedInstance -safe", result0);
1246
1247 final String text1 = "#pragma script.mode pro50\n" + src0;
1248 final JexlScript script1 = jexl.createScript(text1);
1249 context = pragmaticContext();
1250 final Object result1 = script1.execute(context);
1251 assertEquals("+strict +cancellable +lexical +lexicalShade -sharedInstance -safe", result1);
1252
1253 final String text2 = src0;
1254 final JexlScript script2 = jexl.createScript(text2);
1255 context = pragmaticContext();
1256 final Object result2 = script2.execute(context);
1257 assertEquals("-strict -cancellable -lexical -lexicalShade +sharedInstance +safe", result2);
1258 }
1259
1260 @Test
1261 void tests301b() {
1262 final JexlEngine jexl = new JexlBuilder().safe(false).arithmetic(new JexlArithmetic(false)).create();
1263 final Object[] xs = { null, null, new Object[] { null, 1 } };
1264 final String[] srcs = { "x.0", "x[0]", "x[0][0]" };
1265 final JexlContext ctxt = new MapContext();
1266 for (int i = 0; i < xs.length; ++i) {
1267 ctxt.set("x", xs[i]);
1268 final String src = srcs[i];
1269 final JexlScript s = jexl.createScript(src);
1270 assertThrows(JexlException.class, () -> s.execute(null));
1271 }
1272 }
1273
1274 @Test
1275 void testSO20220930() {
1276
1277 final List<Driver0930> values = new ArrayList<>();
1278 for (int i = 0; i < 8; ++i) {
1279 values.add(new Driver0930("drvr" + Integer.toOctalString(i)));
1280 }
1281 for (int i = 0; i < 4; ++i) {
1282 values.add(new Driver0930("favorite" + Integer.toOctalString(i)));
1283 }
1284
1285 final JexlEngine jexl = new JexlBuilder().safe(false).create();
1286 final JexlContext context = new Context0930();
1287 context.set("values", values);
1288 context.set("Collectors", Collectors.class);
1289
1290 final String src32 = "values.stream().filter((driver) ->{ driver.attributeName =^ 'favorite' }).collect(Collectors.toList())";
1291 final String src33 = "values.stream().filter(driver -> driver.attributeName =^ 'favorite').collect(Collectors.toList())";
1292 for (final String src : Arrays.asList(src32, src33)) {
1293 final JexlExpression s = jexl.createExpression(src);
1294 assertNotNull(s);
1295
1296 final Object r = s.evaluate(context);
1297 assertNotNull(r);
1298
1299 final List<Driver0930> l = (List<Driver0930>) r;
1300 assertEquals(4, l.size());
1301 for (final Driver0930 d : l) {
1302 assertTrue(d.getAttributeName().startsWith("favorite"));
1303 }
1304 }
1305 }
1306
1307 @Test
1308 void testUnsolvableMethod() {
1309 final JexlEngine jexl = new JexlBuilder().create();
1310
1311 final JexlScript script = jexl.createScript(
1312 "var myFunction1 = function(object) {"
1313 + " myNonExistentFunction();"
1314 + "}"
1315 + "var myFunction2 = function(object) {"
1316 + " myFunction1();"
1317 + "}"
1318 + "myFunction2();");
1319
1320 final JexlException.Method unsolvable = assertThrows(JexlException.Method.class, () -> script.execute(new MapContext()));
1321 assertEquals("myNonExistentFunction", unsolvable.getMethod());
1322 }
1323 }