diff --git a/lisp/xml.el b/lisp/xml.el
index 2c3b6a49f61..1802d04dfaf 100644
--- a/lisp/xml.el
+++ b/lisp/xml.el
@@ -579,7 +579,14 @@ Return one of:
(error "XML: (Well-Formed) Invalid character"))
;; However, if we're parsing incrementally, then we need to deal
;; with stray CDATA.
- (xml-parse-string)))))
+ (let ((s (xml-parse-string)))
+ (when (string-empty-p s)
+ ;; We haven't consumed any input! We must throw an error in
+ ;; order to prevent looping forever.
+ (error "XML: (Not Well-Formed) Could not parse: %s"
+ (buffer-substring-no-properties
+ (point) (min (+ (point) 10) (point-max)))))
+ s)))))
(defun xml-parse-string ()
"Parse character data at point, and return it as a string.
diff --git a/test/automated/xml-parse-tests.el b/test/automated/xml-parse-tests.el
index 763febb9b69..488d2c6f920 100644
--- a/test/automated/xml-parse-tests.el
+++ b/test/automated/xml-parse-tests.el
@@ -72,7 +72,12 @@
;; Invalid XML names
"<0foo>abc0foo>"
"<‿foo>abc‿foo>"
- "abc")
+ "abc"
+ ;; Two root tags
+ ""
+ ;; Bug#16344
+ "< /x>"
+ "< b/>")
"List of XML strings that should signal an error in the parser")
(defvar xml-parse-tests--qnames