The return value of file-position of string-input-stream is wrong.

Bug #1884220 reported by ryosuke sasaki on 2020-06-19
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
Undecided
Unassigned

Bug Description

$ uname -a
Darwin usernoMacBook-puro.local 19.5.0 Darwin Kernel Version 19.5.0: Tue May 26 20:41:44 PDT 2020; root:xnu-6153.121.2~2/RELEASE_X86_64 x86_64

$ sbcl --version
SBCL 2.0.5

(let ((start 1))
  (with-input-from-string (in "abc" :start start)
    (assert (eql start (file-position in)))))

Expect the return value of file-positioin to be start, but the actual value will be 0.

Changing this line to the following gave the correct result.

https://github.com/sbcl/sbcl/blob/790a82f7b6989100b74c7b9346f9b5adb6647655/src/code/stream.lisp#L1282

< (- (string-input-stream-index stream)
< (string-input-stream-start stream))))
---
> (string-input-stream-index stream)))

ryosuke sasaki (cxxxr) on 2020-06-19
description: updated
information type: Private Security → Public
Douglas Katzman (dougk) wrote :

It's unclear that that's the right expected behavior.
Firstly, the subtraction is necessary because of displaced strings, but secondly, it's totally unclear what it would mean if you tried to assign the position to less than 5.
Consider that logically the :start and :end bound the arguments to SUBSEQ, and a valid implementation might be to actually call SUBSEQ and produce a string stream from that. So stream position 0 is string position 0, I can't any other thing that it should be.

Douglas Katzman (dougk) wrote :

(i didn't mean "less than 5", I meant "less than whatever :START was")

Douglas Katzman (dougk) wrote :

Clozure:
? (let ((s (make-string-input-stream "ABCDEFG" 3))) (values (read-char s) (file-position s)))
#\D
1

CLISP:
[1]> (let ((s (make-string-input-stream "ABCDEFG" 3))) (values (read-char s) (file-position s)))
#\D ;
1

Moreover, I would claim that a implementation is buggy if it does it this way (as some do):

(with-input-from-string (s "ABCDEFG" :start 3) (file-position s :start) (read-char s))
=> #\A

By what rationale should positioning to the :START of that stream return #\A as the next character to read, when I've explicitly asked for a stream that returns the characters in the subsequence bounded below by index 3?

Changed in sbcl:
status: New → Invalid
Richard M Kreuter (kreuter) wrote :

While I happen to like SBCL's FILE-POSITION behavior on STRING-STREAMs (because it allows one to count how many characters got parsed by functions analogous to READ-FROM-STRING without requiring your parsers to count characters explicitly), something always struck me as dodgy about depending on it.

Two peculiar notes stand out about FILE-POSITION in ANSI:

(a) the dictionary entry says the first argument can be a stream, but the Description section make numerous references to positions within a file. But there's no file associated with a STRING-STREAM.

(b) It doesn't appear that much effort was made to define FILE-POSITION for other standard kinds of stream; only BROADCAST-STREAM has a defined semantic for FILE-POSITION. Nothing for TWO-WAY-STREAM, CONCATENATED-STREAM, for example.

I think item (a) is sufficient reason to observe that there's some degree of implicit implementor discretion in defining FILE-POSITION for string streams. Item (b) is just extra cause to be suspicious that the standard is comprehensive in its requirements for FILE-POSITION.

(For people who enjoy ANSI hermeneutics:

(c) CLtL describes FILE-POSITION with the sentence "file-position returns or sets the current position within a random-access file".

(d) If you can find the dpANS3 sources for the standard, you'll find this comment in the source for FILE-POSITION's dictionary entry:

%%KMP: I could find no reference which supported this claim. It looks well-defined to me.
%
% The consequences are undefined if \param{file-stream}
% is not a \term{stream} that is open to a random-access file.

So it's as reasonable as not to suppose that it might have been an X3J13 editing error that FILE-POSITION is documented to take STREAMs instead of (say) FILE-STREAMs.)

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers