mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-25 12:23:09 +00:00
Correctly handle multiple chunks from read_in_chunks
read_in_chunks does not clear the intermediate string 'str' between iterations, so every chunk has every other chunk prepended to it. A secondary issue is that it calls str2wcstring() on an intermediate chunk, which may split multi-byte sequences. This needs to be deferred to the end. Test added. Fixes #3756
This commit is contained in:
parent
f7c133da00
commit
5a5a6a6968
3 changed files with 23 additions and 11 deletions
|
@ -2024,20 +2024,19 @@ static int read_in_chunks(int fd, wcstring &buff, bool split_null) {
|
|||
break;
|
||||
}
|
||||
|
||||
long i;
|
||||
for (i = 0; i < bytes_read && !finished; i++) {
|
||||
if ((!split_null && inbuf[i] == L'\n') || (split_null && inbuf[i] == L'\0')) {
|
||||
finished = true;
|
||||
} else {
|
||||
str.push_back(inbuf[i]);
|
||||
}
|
||||
}
|
||||
buff += str2wcstring(str);
|
||||
if (i < bytes_read) {
|
||||
CHECK(lseek(fd, i - bytes_read, SEEK_CUR) != -1, STATUS_BUILTIN_ERROR)
|
||||
const char *end = std::find(inbuf, inbuf + bytes_read, split_null ? L'\0' : L'\n');
|
||||
long bytes_consumed = end - inbuf; // note: must be signed for use in lseek
|
||||
assert(bytes_consumed <= bytes_read);
|
||||
str.append(inbuf, bytes_consumed);
|
||||
if (bytes_consumed < bytes_read) {
|
||||
// We found a splitter
|
||||
// +1 because we need to treat the splitter as consumed, but not append it to the string
|
||||
CHECK(lseek(fd, bytes_consumed - bytes_read + 1, SEEK_CUR) != -1, STATUS_BUILTIN_ERROR)
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
buff = str2wcstring(str);
|
||||
if (buff.empty() && eof) {
|
||||
exit_res = STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
|
|
|
@ -117,4 +117,14 @@ echo -ne 'foo\nbar\0baz\nquux' | while read -lza foo
|
|||
print_vars foo
|
||||
end
|
||||
|
||||
echo
|
||||
echo '# chunked read tests'
|
||||
set -l path /tmp/fish_chunked_read_test.txt
|
||||
set -l longstr (seq 1024 | string join ',')
|
||||
echo -n $longstr > $path
|
||||
read -l longstr2 < $path
|
||||
test "$longstr" = "$longstr2"
|
||||
and echo "Chunked reads test pass"
|
||||
or echo "Chunked reads test failure: long strings don't match!"
|
||||
|
||||
true
|
||||
|
|
|
@ -55,3 +55,6 @@ newline
|
|||
1 'foo' 1 'bar'
|
||||
2 'foo' 'bar'
|
||||
2 'baz' 'quux'
|
||||
|
||||
# chunked read tests
|
||||
Chunked reads test pass
|
||||
|
|
Loading…
Reference in a new issue