Repository: PebbleTemplates/pebble
Pull request #267 (2017-05-05 14:14:57)

Fix for #266
[#266](https://github.com/PebbleTemplates/pebble/issues/266)


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c44d1606..f88bf72a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@
 - Fix potential null pointer exception in PebbleException (#243)
 - Fix for accessing map via primitive (#196)
 - Output filename and line number of non-existent macro
+- Fix for null pointer and index out of bounds exceptions when invalid or no endif/endfor tags are used in template (#266)
 
 ## v2.3.0 (2016-11-13)
 - Upgrade SLF4J from 1.6.1 to 1.7.21
diff --git a/src/main/java/com/mitchellbosecke/pebble/tokenParser/ForTokenParser.java b/src/main/java/com/mitchellbosecke/pebble/tokenParser/ForTokenParser.java
index ddcd8693..2ec140a1 100644
--- a/src/main/java/com/mitchellbosecke/pebble/tokenParser/ForTokenParser.java
+++ b/src/main/java/com/mitchellbosecke/pebble/tokenParser/ForTokenParser.java
@@ -49,10 +49,17 @@ public class ForTokenParser extends AbstractTokenParser {
             elseBody = parser.subparse(decideForEnd);
         }
 
-        // skip the 'endfor' token
-        stream.next();
-
-        stream.expect(Token.Type.EXECUTE_END);
+        if (stream.current().getValue() == null) {
+            throw new ParserException(
+                    null,
+                    String.format("Unexpected end of template. Pebble was looking for the \"endfor\" tag"),
+                    stream.current().getLineNumber(), stream.getFilename()
+            );
+        } else {
+            // skip the 'endfor' token
+            stream.next();
+            stream.expect(Token.Type.EXECUTE_END);
+        }
 
         return new ForNode(lineNumber, iterationVariable, iterable, body, elseBody);
     }
diff --git a/src/main/java/com/mitchellbosecke/pebble/tokenParser/IfTokenParser.java b/src/main/java/com/mitchellbosecke/pebble/tokenParser/IfTokenParser.java
index 0ceb52c9..97751f6a 100644
--- a/src/main/java/com/mitchellbosecke/pebble/tokenParser/IfTokenParser.java
+++ b/src/main/java/com/mitchellbosecke/pebble/tokenParser/IfTokenParser.java
@@ -45,6 +45,13 @@ public class IfTokenParser extends AbstractTokenParser {
         BodyNode elseBody = null;
         boolean end = false;
         while (!end) {
+            if (stream.current().getValue() == null) {
+                throw new ParserException(
+                        null,
+                        String.format("Unexpected end of template. Pebble was looking for the \"endif\" tag"),
+                        stream.current().getLineNumber(), stream.getFilename());
+            }
+
             switch (stream.current().getValue()) {
             case "else":
                 stream.next();


Test patch:
diff --git a/src/test/java/com/mitchellbosecke/pebble/CoreTagsTest.java b/src/test/java/com/mitchellbosecke/pebble/CoreTagsTest.java
index bef0c28b..2cc6e636 100755
--- a/src/test/java/com/mitchellbosecke/pebble/CoreTagsTest.java
+++ b/src/test/java/com/mitchellbosecke/pebble/CoreTagsTest.java
@@ -24,6 +24,7 @@ import java.util.*;
 import java.util.concurrent.Executors;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 public class CoreTagsTest extends AbstractTest {
 
@@ -169,6 +170,21 @@ public class CoreTagsTest extends AbstractTest {
         assertEquals("true", writer.toString());
     }
 
+    @Test
+    public void testIfWhenInvalidOrNoEndifTag() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
+        String source = "{% if variable %}smth{ endif %}";
+        try {
+            pebble.getTemplate(source);
+
+            fail("Should fail due to invalid endif tag");
+        } catch (PebbleException ex) {
+            assertEquals(ex.getPebbleMessage(), "Unexpected end of template. Pebble was looking for the \"endif\" tag");
+            assertEquals(ex.getLineNumber(), (Integer) 1);
+            assertEquals(ex.getFileName(), source);
+        }
+    }
+
     @Test
     public void testFlush() throws PebbleException, IOException {
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
@@ -246,6 +262,21 @@ public class CoreTagsTest extends AbstractTest {
         template.evaluate(writer, context);
     }
 
+    @Test
+    public void testForWhenInvalidOrNoEndforTag() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
+        String source = "{% for i in 'a'..5 %}{{i}}% endfor %}";
+        try {
+            pebble.getTemplate(source);
+
+            fail("Should fail due to invalid endfor tag");
+        } catch (PebbleException ex) {
+            assertEquals(ex.getPebbleMessage(), "Unexpected end of template. Pebble was looking for the \"endfor\" tag");
+            assertEquals(ex.getLineNumber(), (Integer) 1);
+            assertEquals(ex.getFileName(), source);
+        }
+    }
+
     @Test
     public void testFilterTag() throws PebbleException, IOException {
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();