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