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