diff --git a/xapian-core/queryparser/termgenerator_internal.cc b/xapian-core/queryparser/termgenerator_internal.cc
index 4a7251cfc3f2..021ebaed4fe2 100644
--- a/xapian-core/queryparser/termgenerator_internal.cc
+++ b/xapian-core/queryparser/termgenerator_internal.cc
@@ -707,8 +707,11 @@ MSet::Internal::snippet(const string & text,
 			const string & omit) const
 {
     if (hi_start.empty() && hi_end.empty() && text.size() <= length) {
-	// Too easy!
-	return text;
+	// The text is already short enough so we just need to perform
+	// escaping.
+	string output;
+	append_escaping_xml(text.data(), text.data() + text.size(), output);
+	return output;
     }
 
     bool cjk_ngram = (flags & MSet::SNIPPET_CJK_NGRAM);
diff --git a/xapian-core/tests/api_snippets.cc b/xapian-core/tests/api_snippets.cc
index 9c63a3778b9b..0c94118926d4 100644
--- a/xapian-core/tests/api_snippets.cc
+++ b/xapian-core/tests/api_snippets.cc
@@ -364,6 +364,13 @@ DEFINE_TESTCASE(snippet_start_nonspace, backend) {
     TEST_STRINGS_EQUAL(mset.snippet(input, 12, stem),
 		       "...&lt;<b>foo</b>.h&gt; to...");
 
+    // Check escaping still happens without highlighting when the text is
+    // already short enough.  Regression test for bug fixed in 1.4.32 and
+    // 2.0.1.
+    input = "<foo> &amp;";
+    TEST_STRINGS_EQUAL(mset.snippet(input, 12, stem, 0, "", ""),
+		       "&lt;foo&gt; &amp;amp;");
+
     input = "¡foo!";
     TEST_STRINGS_EQUAL(mset.snippet(input, strlen(input), stem),
 		       "¡<b>foo</b>!");
@@ -426,6 +433,13 @@ DEFINE_TESTCASE(snippet_start_nonspace, backend) {
     TEST_STRINGS_EQUAL(mset.snippet(input, 5, stem),
 		       "...<b>foo</b>!");
 
+    // Check escaping still happens without highlighting when the text is
+    // already short enough.  Regression test for bug fixed in 1.4.32 and
+    // 2.0.1.
+    input = "&foo takes the address of foo";
+    TEST_STRINGS_EQUAL(mset.snippet(input, strlen(input), stem, 0, "", ""),
+		       "&amp;foo takes the address of foo");
+
     return true;
 }
 
