nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: PebbleTemplates/pebble
Pull request #191 (2016-04-07 15:15:44)

Throw PebbleException when variable cannot be iterated in a For tag
Pebble returns a NullPointerException when passing a non-iterable variable (string, number, ..) to a for loop, making hard the task of finding what is that the developer has written wrong in the template.
This PR tries to address that issue, raising a PebbleException and providing information about the error and the line where it occurred.


Patch:
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/ForNode.java b/src/main/java/com/mitchellbosecke/pebble/node/ForNode.java
index db3809a4..f1a6459b 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/ForNode.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/ForNode.java
@@ -56,6 +56,11 @@ public class ForNode extends AbstractRenderableNode {
 
         iterable = toIterable(iterableEvaluation);
 
+        if (iterable == null) {
+            throw new PebbleException(null, "Not an iterable object. Value = [" + iterableEvaluation.toString() + "]",
+                getLineNumber(), self.getName());
+        }
+
         Iterator<?> iterator = iterable.iterator();
 
         boolean newScope = false;


Test patch:
diff --git a/src/test/java/com/mitchellbosecke/pebble/ArraySyntaxTest.java b/src/test/java/com/mitchellbosecke/pebble/ArraySyntaxTest.java
index df595c36..7b2118d4 100644
--- a/src/test/java/com/mitchellbosecke/pebble/ArraySyntaxTest.java
+++ b/src/test/java/com/mitchellbosecke/pebble/ArraySyntaxTest.java
@@ -21,6 +21,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 public class ArraySyntaxTest extends AbstractTest {
 
@@ -332,6 +333,22 @@ public class ArraySyntaxTest extends AbstractTest {
         assertEquals("BobMariaJohn", writer.toString());
     }
 
+    @Test
+    public void testForTagInvalidIterable() throws PebbleException, IOException {
+
+        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build();
+        String source = "{% set myVar = 'somevalue' %}{% for myVal in myVar %}{{ myVal }}{% endfor %}";
+        PebbleTemplate template = pebble.getTemplate(source);
+
+        Writer writer = new StringWriter();
+        try {
+            template.evaluate(writer, new HashMap<String, Object>());
+            fail("Expected PebbleException");
+        } catch (PebbleException e) {
+            assertEquals("Not an iterable object. Value = [somevalue] (" + source + ":1)", e.getMessage());
+        }
+    }
+
     @Test
     public void testForElseTag() throws PebbleException, IOException {
Repository: PebbleTemplates/pebble
Pull request #215 (2016-08-02 02:52:42)

Stop ScopeChain lookups when first scope is local
A local scope should stop the lookup from proceeding along the chain. This
was working in all cases except when the very first scope in the chain was
local.


Patch:
diff --git a/src/main/java/com/mitchellbosecke/pebble/template/ScopeChain.java b/src/main/java/com/mitchellbosecke/pebble/template/ScopeChain.java
index 109b685c..2de631df 100644
--- a/src/main/java/com/mitchellbosecke/pebble/template/ScopeChain.java
+++ b/src/main/java/com/mitchellbosecke/pebble/template/ScopeChain.java
@@ -130,13 +130,10 @@ public class ScopeChain {
             // account for the first lookup we did
             iterator.next();
 
-            while (result == null && iterator.hasNext()) {
+            while (!scope.isLocal() && result == null && iterator.hasNext()) {
                 scope = iterator.next();
 
                 result = scope.get(key);
-                if (scope.isLocal()) {
-                    break;
-                }
             }
         }
 
@@ -168,15 +165,12 @@ public class ScopeChain {
         // account for the first lookup we did
         iterator.next();
 
-        while (iterator.hasNext()) {
+        while (!scope.isLocal() && iterator.hasNext()) {
             scope = iterator.next();
 
             if (scope.containsKey(key)) {
                 return true;
             }
-            if (scope.isLocal()) {
-                break;
-            }
         }
 
         return false;


Test patch:
diff --git a/src/test/java/com/mitchellbosecke/pebble/ScopeChainTest.java b/src/test/java/com/mitchellbosecke/pebble/ScopeChainTest.java
new file mode 100644
index 00000000..19df11a8
--- /dev/null
+++ b/src/test/java/com/mitchellbosecke/pebble/ScopeChainTest.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * This file is part of Pebble.
+ * <p>
+ * Copyright (c) 2014 by Mitchell Bösecke
+ * <p>
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ ******************************************************************************/
+package com.mitchellbosecke.pebble;
+
+import com.mitchellbosecke.pebble.error.PebbleException;
+import com.mitchellbosecke.pebble.template.ScopeChain;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.junit.Assert.*;
+
+public class ScopeChainTest extends AbstractTest {
+
+    @Test
+    public void testLocalScopeAtTop() throws PebbleException, IOException {
+        ScopeChain scopeChain = new ScopeChain();
+        scopeChain.pushScope();
+        scopeChain.put("key", "value");
+        assertEquals("value", scopeChain.get("key"));
+        scopeChain.pushLocalScope();
+        assertEquals(false, scopeChain.containsKey("key"));
+        assertNull(scopeChain.get("key"));
+        scopeChain.put("key", "value2");
+        assertEquals(true, scopeChain.containsKey("key"));
+        assertEquals("value2", scopeChain.get("key"));
+    }
+}
Repository: PebbleTemplates/pebble
Pull request #299 (2017-10-26 22:02:57)

Fix NPE in GetAttributeExpression
The recent change to allow map access via primitives introduced an NPE situtation when null was being passed as the map key.  This PR fixes that issue by skipping `Number.class.isAssignableFrom` if the attributeNameValue is null


Patch:
diff --git a/src/main/java/com/mitchellbosecke/pebble/node/expression/GetAttributeExpression.java b/src/main/java/com/mitchellbosecke/pebble/node/expression/GetAttributeExpression.java
index 36bb77c9..22d4f5b1 100644
--- a/src/main/java/com/mitchellbosecke/pebble/node/expression/GetAttributeExpression.java
+++ b/src/main/java/com/mitchellbosecke/pebble/node/expression/GetAttributeExpression.java
@@ -208,7 +208,7 @@ public class GetAttributeExpression implements Expression<Object> {
         if (object.isEmpty()) {
             return null;
         }
-        if (Number.class.isAssignableFrom(attributeNameValue.getClass())) {
+        if (attributeNameValue != null && Number.class.isAssignableFrom(attributeNameValue.getClass())) {
             Number keyAsNumber = (Number) attributeNameValue;
 
             Class<?> keyClass = object.keySet().iterator().next().getClass();


Test patch:
diff --git a/src/test/java/com/mitchellbosecke/pebble/GetAttributeTest.java b/src/test/java/com/mitchellbosecke/pebble/GetAttributeTest.java
index bfe8864e..1c1deb99 100644
--- a/src/test/java/com/mitchellbosecke/pebble/GetAttributeTest.java
+++ b/src/test/java/com/mitchellbosecke/pebble/GetAttributeTest.java
@@ -84,6 +84,20 @@ public class GetAttributeTest extends AbstractTest {
         assertEquals("hello Steve", writer.toString());
     }
 
+    @Test
+    public void testHashmapAttributeWithArgumentOfNull() throws PebbleException, IOException {
+        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).build();
+        PebbleTemplate template = pebble.getTemplate("hello {{ object[missingContextProperty] }}");
+        Map<String, Object> context = new HashMap<>();
+        Map<String, String> map = new HashMap<>();
+        map.put("name", "Steve");
+        context.put("object", map);
+
+        Writer writer = new StringWriter();
+        template.evaluate(writer, context);
+        assertEquals("hello ", writer.toString());
+    }
+
     @Test
     public void testMethodAttribute() throws PebbleException, IOException {
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(true).build();
@@ -553,7 +567,7 @@ public class GetAttributeTest extends AbstractTest {
 
         assertEquals("1 1 2 true", writer.toString());
     }
-    
+
     @Test
     public void testBeanMethodWithNullArgument() throws PebbleException, IOException {
         PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(true).build();
Repository: PebbleTemplates/pebble
Pull request #492 (2019-12-18 18:56:57)

Empty map in strict mode does not throw exception (#491)


Patch:
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/attributes/MapResolver.java b/pebble/src/main/java/com/mitchellbosecke/pebble/attributes/MapResolver.java
index 84512df5..b1c33e87 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/attributes/MapResolver.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/attributes/MapResolver.java
@@ -4,6 +4,7 @@ import com.mitchellbosecke.pebble.error.AttributeNotFoundException;
 import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.node.ArgumentsNode;
 import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+
 import java.util.Map;
 
 class MapResolver implements AttributeResolver {
@@ -22,7 +23,7 @@ class MapResolver implements AttributeResolver {
       String filename,
       int lineNumber) {
     Map<?, ?> object = (Map<?, ?>) instance;
-    if (object.isEmpty()) {
+    if (object.isEmpty() && !context.isStrictVariables()) {
       return new ResolvedAttribute(null);
     }
 


Test patch:
diff --git a/pebble/src/test/java/com/mitchellbosecke/pebble/GetAttributeTest.java b/pebble/src/test/java/com/mitchellbosecke/pebble/GetAttributeTest.java
index e82525d4..ce2e338e 100644
--- a/pebble/src/test/java/com/mitchellbosecke/pebble/GetAttributeTest.java
+++ b/pebble/src/test/java/com/mitchellbosecke/pebble/GetAttributeTest.java
@@ -142,6 +142,23 @@ class GetAttributeTest {
     });
   }
 
+  @Test
+  void testNonExistingMapAttributeWithStrictVariablesAndEmptyMap() throws PebbleException, IOException {
+    assertThrows(AttributeNotFoundException.class, () -> {
+      PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
+          .strictVariables(true).build();
+
+      String source = "{{ object.nonExisting }}";
+      PebbleTemplate template = pebble.getTemplate(source);
+
+      Map<String, Object> context = new HashMap<>();
+      context.put("object", new HashMap<>());
+
+      Writer writer = new StringWriter();
+      template.evaluate(writer, context);
+    });
+  }
+
   @Test
   void testNullMapValueWithoutStrictVariables() throws PebbleException, IOException {
     PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
Repository: PebbleTemplates/pebble
Pull request #559 (2020-12-09 15:25:15)

Throw an error when an import alias references an invalid macro (#558)


Patch:
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/template/PebbleTemplateImpl.java b/pebble/src/main/java/com/mitchellbosecke/pebble/template/PebbleTemplateImpl.java
index d0255ab6..04bdd9b7 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/template/PebbleTemplateImpl.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/template/PebbleTemplateImpl.java
@@ -244,6 +244,12 @@ public class PebbleTemplateImpl implements PebbleTemplate {
         .getTemplate(this.resolveRelativePath(name));
     for (Pair<String, String> pair : namedMacros) {
       Macro m = templateImpl.macros.get(pair.getRight());
+
+      if (m == null) {
+        throw new PebbleException(null, "Function or Macro [" + pair.getRight() + "] referenced by alias ["
+                + pair.getLeft() + "] does not exist.");
+      }
+
       this.registerMacro(pair.getLeft(), m);
     }
   }


Test patch:
diff --git a/pebble/src/test/java/com/mitchellbosecke/pebble/macro/TestMacroCalls.java b/pebble/src/test/java/com/mitchellbosecke/pebble/macro/TestMacroCalls.java
index b9054334..074e518e 100644
--- a/pebble/src/test/java/com/mitchellbosecke/pebble/macro/TestMacroCalls.java
+++ b/pebble/src/test/java/com/mitchellbosecke/pebble/macro/TestMacroCalls.java
@@ -161,4 +161,22 @@ class TestMacroCalls {
           .startsWith("More than one named template can not share the same name"));
     }
   }
+
+  @Test
+  void testInvalidAliasReferencingUnknownMacro() throws IOException {
+    PebbleEngine pebble = new PebbleEngine.Builder().build();
+
+    try {
+      PebbleTemplate template = pebble
+          .getTemplate("templates/macros/invalid.from.unknownMacro.peb");
+      Writer writer = new StringWriter();
+      template.evaluate(writer);
+      fail("expected PebbleException");
+    } catch (PebbleException e) {
+      assertEquals(
+              "Function or Macro [iDontExist] referenced by alias [macro_test] does not exist.",
+              e.getPebbleMessage()
+      );
+    }
+  }
 }
diff --git a/pebble/src/test/resources/templates/macros/invalid.from.unknownMacro.peb b/pebble/src/test/resources/templates/macros/invalid.from.unknownMacro.peb
new file mode 100644
index 00000000..07b950c9
--- /dev/null
+++ b/pebble/src/test/resources/templates/macros/invalid.from.unknownMacro.peb
@@ -0,0 +1,4 @@
+Hello
+
+{% from "templates/macros/macro.peb" import iDontExist as macro_test %}
+Call 1: {{ macro_test() }}