Merge branch 'stable-2.11'

* stable-2.11:
  Use the correct ValidatePolicy for commits created by Gerrit
  Fix invalid ref name being accepted by Gerrit

Change-Id: Idd999b650e2e58c8a2677fad807e61a7ba4bcc57
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
index cb99688..d12d30a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
@@ -547,7 +547,7 @@
       Config rc, Map<String, GroupReference> groupsByName) {
     accessSections = new HashMap<>();
     for (String refName : rc.getSubsections(ACCESS)) {
-      if (RefConfigSection.isValid(refName)) {
+      if (RefConfigSection.isValid(refName) & isValidRegex(refName)) {
         AccessSection as = getAccessSection(refName, true);
 
         for (String varName : rc.getStringList(ACCESS, refName, KEY_GROUP_PERMISSIONS)) {
@@ -580,6 +580,17 @@
     }
   }
 
+  private boolean isValidRegex(String refPattern) {
+    try {
+      Pattern.compile(refPattern.replace("${username}/", ""));
+    } catch (PatternSyntaxException e) {
+      error(new ValidationError(PROJECT_CONFIG, "Invalid ref name: "
+          + e.getMessage()));
+      return false;
+    }
+    return true;
+  }
+
   private void loadBranchOrderSection(Config rc) {
     if (rc.getSections().contains(BRANCH_ORDER)) {
       branchOrderSection = new BranchOrderSection(
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
index cfabf13..741efb4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
@@ -50,6 +50,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
 
 
 /** Manages access control for Git references (aka branches, tags). */
@@ -683,5 +685,10 @@
     } else if (!Repository.isValidRefName(refPattern)) {
       throw new InvalidNameException(refPattern);
     }
+    try {
+      Pattern.compile(refPattern.replace("${username}/", ""));
+    } catch (PatternSyntaxException e) {
+      throw new InvalidNameException(refPattern + " " + e.getMessage());
+    }
   }
 }
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java
index 85272d0..9706feb 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java
@@ -35,6 +35,7 @@
 import com.google.gerrit.common.data.Capable;
 import com.google.gerrit.common.data.PermissionRange;
 import com.google.gerrit.common.data.PermissionRule;
+import com.google.gerrit.common.errors.InvalidNameException;
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.git.ProjectConfig;
@@ -670,4 +671,29 @@
     assertCannotVote(-2, range);
     assertCannotVote(2, range);
   }
+
+  @Test
+  public void testValidateRefPatternsOK() throws Exception {
+    RefControl.validateRefPattern("refs/*");
+    RefControl.validateRefPattern("^refs/heads/*");
+    RefControl.validateRefPattern("^refs/tags/[0-9a-zA-Z-_.]+");
+    RefControl.validateRefPattern("refs/heads/review/${username}/*");
+  }
+
+  @Test(expected = InvalidNameException.class)
+  public void testValidateBadRefPatternDoubleCaret() throws Exception {
+    RefControl.validateRefPattern("^^refs/*");
+  }
+
+  @Test(expected = InvalidNameException.class)
+  public void testValidateBadRefPatternDanglingCharacter() throws Exception {
+    RefControl
+        .validateRefPattern("^refs/heads/tmp/sdk/[0-9]{3,3}_R[1-9][A-Z][0-9]{3,3}*");
+  }
+
+  @Test
+  public void testValidateRefPatternNoDanglingCharacter() throws Exception {
+    RefControl
+        .validateRefPattern("^refs/heads/tmp/sdk/[0-9]{3,3}_R[1-9][A-Z][0-9]{3,3}");
+  }
 }