am 550c8d32: Fixed shift underflow bug in interElementWhitespace checking.

* commit '550c8d3230c152db7156b266d089512b72ac0024':
  Fixed shift underflow bug in interElementWhitespace checking.
diff --git a/src/main/org/owasp/html/TagBalancingHtmlStreamEventReceiver.java b/src/main/org/owasp/html/TagBalancingHtmlStreamEventReceiver.java
index ba83e9a..1f8f645 100644
--- a/src/main/org/owasp/html/TagBalancingHtmlStreamEventReceiver.java
+++ b/src/main/org/owasp/html/TagBalancingHtmlStreamEventReceiver.java
@@ -212,18 +212,28 @@
     }
   }
 
-  private static final int HTML_SPACE_CHAR_BITMASK =
-      (1 << ' ') | (1 << '\t') | (1 << '\n') | (1 << '\u000c') | (1 << '\r');
+  private static final long HTML_SPACE_CHAR_BITMASK =
+      (1L << ' ')
+    | (1L << '\t')
+    | (1L << '\n')
+    | (1L << '\u000c')
+    | (1L << '\r');
 
-  public void text(String text) {
+  public static boolean isInterElementWhitespace(String text) {
     int n = text.length();
     for (int i = 0; i < n; ++i) {
       int ch = text.charAt(i);
-      if (ch > 0x20 || (HTML_SPACE_CHAR_BITMASK & (1 << ch)) == 0) {
-        prepareForContent(ElementContainmentRelationships.CHARACTER_DATA_ONLY);
-        break;
+      if (ch > 0x20 || (HTML_SPACE_CHAR_BITMASK & (1L << ch)) == 0) {
+        return false;
       }
     }
+    return true;
+  }
+
+  public void text(String text) {
+    if (!isInterElementWhitespace(text)) {
+      prepareForContent(ElementContainmentRelationships.CHARACTER_DATA_ONLY);
+    }
 
     if (openElements.size() < nestingLimit) {
       underlying.text(text);
diff --git a/src/tests/org/owasp/html/TagBalancingHtmlStreamRendererTest.java b/src/tests/org/owasp/html/TagBalancingHtmlStreamRendererTest.java
index ab90ea4..941462d 100644
--- a/src/tests/org/owasp/html/TagBalancingHtmlStreamRendererTest.java
+++ b/src/tests/org/owasp/html/TagBalancingHtmlStreamRendererTest.java
@@ -32,12 +32,19 @@
 
 import junit.framework.TestCase;
 
+import org.junit.Test;
+import org.junit.Before;
+
+import static org.owasp.html.TagBalancingHtmlStreamEventReceiver
+              .isInterElementWhitespace;
+
+
 public class TagBalancingHtmlStreamRendererTest extends TestCase {
 
   StringBuilder htmlOutputBuffer;
   TagBalancingHtmlStreamEventReceiver balancer;
 
-  @Override protected void setUp() throws Exception {
+  @Before @Override protected void setUp() throws Exception {
     super.setUp();
     htmlOutputBuffer = new StringBuilder();
     balancer = new TagBalancingHtmlStreamEventReceiver(
@@ -48,6 +55,7 @@
         }));
   }
 
+  @Test
   public final void testTagBalancing() {
     balancer.openDocument();
     balancer.openTag("html", ImmutableList.<String>of());
@@ -72,6 +80,7 @@
         htmlOutputBuffer.toString());
   }
 
+  @Test
   public final void testTagSoupIronedOut() {
     balancer.openDocument();
     balancer.openTag("i", ImmutableList.<String>of());
@@ -87,6 +96,7 @@
         htmlOutputBuffer.toString());
   }
 
+  @Test
   public final void testListInListDirectly() {
     balancer.openDocument();
     balancer.openTag("ul", ImmutableList.<String>of());
@@ -106,6 +116,7 @@
         htmlOutputBuffer.toString());
   }
 
+  @Test
   public final void testTextContent() {
     balancer.openDocument();
     balancer.openTag("title", ImmutableList.<String>of());
@@ -152,6 +163,7 @@
         htmlOutputBuffer.toString());
   }
 
+  @Test
   public final void testMismatchedHeaders() {
     balancer.openDocument();
     balancer.openTag("H1", ImmutableList.<String>of());
@@ -181,6 +193,7 @@
         htmlOutputBuffer.toString());
   }
 
+  @Test
   public final void testListNesting() {
     balancer.openDocument();
     balancer.openTag("ul", ImmutableList.<String>of());
@@ -204,6 +217,7 @@
         htmlOutputBuffer.toString());
   }
 
+  @Test
   public final void testTableNesting() {
     balancer.openDocument();
     balancer.openTag("table", ImmutableList.<String>of());
@@ -229,6 +243,7 @@
         htmlOutputBuffer.toString());
   }
 
+  @Test
   public final void testNestingLimits() {
     // Some browsers can be DoSed by deeply nested structures.
     // See Issue 3, "Deeply nested elements crash FF 8, Chrome 11"
@@ -248,6 +263,7 @@
         htmlOutputBuffer.toString());
   }
 
+  @Test
   public final void testTablesGuarded() {
     // Derived from issue 12.
     balancer.openDocument();
@@ -304,4 +320,21 @@
         htmlOutputBuffer.toString());
   }
 
+  @Test
+  public final void testIsInterElementWhitespace() {
+    assertFalse(isInterElementWhitespace("foo"));
+    assertTrue(isInterElementWhitespace(""));
+    assertTrue(isInterElementWhitespace(" "));
+    assertTrue(isInterElementWhitespace("\t"));
+    assertTrue(isInterElementWhitespace("\n"));
+    assertTrue(isInterElementWhitespace(" \n"));
+    assertTrue(isInterElementWhitespace("\r\n"));
+    assertTrue(isInterElementWhitespace("\r"));
+    assertTrue(isInterElementWhitespace(" "));
+    assertTrue(isInterElementWhitespace(" \t "));
+    assertFalse(isInterElementWhitespace(" foo "));
+    assertFalse(isInterElementWhitespace("\u00A0"));
+    assertFalse(isInterElementWhitespace("\u0000"));
+  }
+
 }