Index: modules/analysis/common/src/java/org/apache/lucene/analysis/util/CharacterUtils.java
===================================================================
--- modules/analysis/common/src/java/org/apache/lucene/analysis/util/CharacterUtils.java	(revision 1303348)
+++ modules/analysis/common/src/java/org/apache/lucene/analysis/util/CharacterUtils.java	(working copy)
@@ -177,21 +177,46 @@
     public boolean fill(final CharacterBuffer buffer, final Reader reader) throws IOException {
       final char[] charBuffer = buffer.buffer;
       buffer.offset = 0;
-      charBuffer[0] = buffer.lastTrailingHighSurrogate;
-      final int offset = buffer.lastTrailingHighSurrogate == 0 ? 0 : 1;
+      final int offset;
+
+      // Install the previously saved ending high surrogate:
+      if (buffer.lastTrailingHighSurrogate != 0) {
+        charBuffer[0] = buffer.lastTrailingHighSurrogate;
+        offset = 1;
+      } else {
+        offset = 0;
+      }
       buffer.lastTrailingHighSurrogate = 0;
-      final int read = reader.read(charBuffer, offset, charBuffer.length
-          - offset);
+      final int read = reader.read(charBuffer,
+                                   offset,
+                                   charBuffer.length - offset);
       if (read == -1) {
         buffer.length = offset;
         return offset != 0;
       }
       buffer.length = read + offset;
-      // special case if the read returns 0 and the lastTrailingHighSurrogate was set
+
+      // If we read only a single char, and that char was a
+      // high surrogate, read again:
+      if (buffer.length == 1
+          && Character.isHighSurrogate(charBuffer[buffer.length - 1])) {
+        final int read2 = reader.read(charBuffer,
+                                      1,
+                                      charBuffer.length - 1);
+        if (read2 == -1) {
+          // NOTE: mal-formed input (ended on a high
+          // surrogate)!  Consumer must deal with it...
+          return true;
+        }
+
+        buffer.length += read2;
+      }
+
       if (buffer.length > 1
           && Character.isHighSurrogate(charBuffer[buffer.length - 1])) {
         buffer.lastTrailingHighSurrogate = charBuffer[--buffer.length];
       }
+
       return true;
     }
   }
Index: lucene/core/src/java/org/apache/lucene/util/fst/Util.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/fst/Util.java	(revision 1303348)
+++ lucene/core/src/java/org/apache/lucene/util/fst/Util.java	(working copy)
@@ -23,9 +23,7 @@
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.IntsRef;
 
-/** Static helper methods.
- *
- * @lucene.experimental */
+// nocommit
 public final class Util {
   private Util() {
   }
