🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.emacs.gnus
Article #765

Infinite loop bug in nntp-retrieve-headers

#765
From: Steve Popovich
Date: Sun, 12 Mar 1989 21:56
158 lines
6092 bytes
This message applies to GNUS version 3.11.

There is a bug in nntp-retrieve-headers that can cause an infinite
loop when selecting a newsgroup.  The bug appears when the NNTP server
sends GNUS a header that doesn't start with any of the keywords it is
expecting.  In my case, the culprit was an article with both a "From: "
header and, later, a "from:" header (all lower case, with no whitespace
after the colon).  The bogus "from:" header caused the endless loop,
because nntp-retrieve-headers will advance to the next line only after
each line is recognized.  The answer is of course to make sure that
non-matching lines will eventually get skipped over.  The following
is one way of doing this; replace your version of nntp-retrieve-headers
with this or a similarly redefined version to avoid the bug.
	-Steve

(defun nntp-retrieve-headers (sequence)
  "Return list of article headers specified by SEQUENCE of article id.
The format of list is `([NUMBER SUBJECT FROM XREF LINES DATE MESSAGE-ID] ...)'.
Reader macros for the vector are defined as `nntp-header-FIELD'.
Writer macros for the vector are defined as `nntp-set-header-FIELD'.
News group must be selected before calling me."
  (save-excursion
    (set-buffer nntp-server-buffer)
    (erase-buffer)
    (let ((number (length sequence))
	  (last-point (point-min))
	  (received 0)
	  (count 0)
	  (headers nil)			;Result list.
	  (article 0)
	  (subject nil)
	  (message-id)
	  (from nil)
	  (xref nil)
	  (lines 0)
	  (date nil))
      ;; Send HEAD command.
      (while sequence
	(nntp-send-strings-to-server "HEAD" (car sequence))
	(setq sequence (cdr sequence))
	(setq count (1+ count))
	;; Every 400 header requests we have to read stream in order
	;;  to avoid deadlock.
	(if (or (null sequence)		;All requests have been sent.
		(zerop (% count nntp-maximum-request)))
	    (progn
	      (accept-process-output)
	      (while (progn
		       (goto-char last-point)
		       ;; Count replies.
		       (while (re-search-forward "^[0-9]" nil t)
			 (setq received (1+ received)))
		       (setq last-point (point))
		       (< received count))
		;; If number of headers is greater than 100, give
		;;  informative messages.
		(and (> number nntp-large-newsgroup)
		     (zerop (% received 20))
		     (message "NNTP: %d%% of headers received."
			      (/ (* received 100) number)))
		(nntp-accept-response))
	      ))
	)
      ;; Wait for text of last command.
      (goto-char (point-max))
      (re-search-backward "^[0-9]" nil t)
      (if (looking-at "^[23]")
	  (while (progn
		   (goto-char (- (point-max) 3))
		   (not (looking-at "^\\.\r$")))
	    (nntp-accept-response)
	    ))
      (if (> number nntp-large-newsgroup)
	  (message "NNTP: 100%% of headers received."))
      ;; Now all of replies are received.
      ;; First, delete unnecessary lines.
      (goto-char (point-min))
      (delete-non-matching-lines
       "^Subject:\\|^Xref:\\|^From:\\|^Lines:\\|^Date:\\|^[23]")
      (if (> number nntp-large-newsgroup)
	  (message "NNTP: Parsing headers..."))
      (setq received number)
      ;; Then examines replies.
      (while (not (eobp))
	(cond ((looking-at "^[23].*[ \t]+\\([0-9]+\\)[ \t]+\\(<.+>\\)")
	       (setq article
		     (string-to-int
		      (buffer-substring (match-beginning 1) (match-end 1))))
	       (setq message-id
		     (buffer-substring (match-beginning 2) (match-end 2)))
	       (forward-line 1)
	       ;; Set default value.
	       (setq subject nil)
	       (setq xref nil)
	       (setq from nil)
	       (setq lines 0)
	       (setq date nil)
	       ;; It is better to extract From:, Subject:, Date:,
	       ;;  Lines: and Xref: field values in *THIS* order.
	       ;; Forward-line each time after getting expected value
	       ;;  in order to reduce count of string matching.
	       (while (looking-at "^[^23]")
		 (let ((no-match t))
		   (if (looking-at "^From:[ \t]\\(.*\\)\r$")
		       (progn
			 (setq from (buffer-substring (match-beginning 1)
						      (match-end 1)))
			 (forward-line 1)
			 (setq no-match nil)))
		   (if (looking-at "^Subject:[ \t]\\(.*\\)\r$")
		       (progn
			 (setq subject (buffer-substring (match-beginning 1)
							 (match-end 1)))
			 (forward-line 1)
			 (setq no-match nil)))
		   (if (looking-at "^Date:[ \t]\\(.*\\)\r$")
		       (progn
			 (setq date (buffer-substring (match-beginning 1)
						      (match-end 1)))
			 (forward-line 1)
			 (setq no-match nil)))
		   (if (looking-at "^Lines:[ \t]\\(.*\\)\r$")
		       (progn
			 (setq lines (string-to-int
				      (buffer-substring (match-beginning 1)
							(match-end 1))))
			 (forward-line 1)
			 (setq no-match nil)))
		   (if (looking-at "^Xref:[ \t]\\(.*\\)\r$")
		       (progn
			 (setq xref (buffer-substring (match-beginning 1)
						      (match-end 1)))
			 (forward-line 1)
			 (setq no-match nil)))
		   (if no-match
		       (forward-line 1))
		   ))
	       (if (null subject)
		   (setq subject "(None)"))
	       (if (null from)
		   (setq from "Unknown User"))
	       (setq headers
		     (cons (vector article subject from
				   xref lines date message-id)
			   headers))
	       )
	      (t (forward-line 1))	;Skip invalid field (ex. Subject:abc)
	      )
	(setq received (1- received))
	(and (> number nntp-large-newsgroup)
	     (zerop (% received 20))
	     (message "NNTP: Parsing headers... %d%%"
		      (/ (* received 100) number)))
	)
      (if (> number nntp-large-newsgroup)
	  (message "NNTP: Parsing headers... done"))
      (nreverse headers)
      )))
Technical Details
Message-ID: <POPOVICH.89Mar12165650@park.cs.columbia.edu>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!watmath!uunet!tut.cis.ohio-state.edu!ucbvax!ucsd!rutgers!columbia!cs!popovich

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!watmath!uunet!tut.cis.ohio-state.edu!ucbvax!ucsd!rutgers!columbia!cs!popovich
From: popovich@park.cs.columbia.edu (Steve Popovich)
Newsgroups: gnu.emacs.gnus
Subject: Infinite loop bug in nntp-retrieve-headers
Message-ID: <POPOVICH.89Mar12165650@park.cs.columbia.edu>
Date: 12 Mar 89 21:56:50 GMT
Sender: news@cs.columbia.edu
Distribution: gnu
Organization: Columbia University
Lines: 158