mirror of
https://github.com/rkd77/elinks.git
synced 2025-01-03 14:57:44 -05:00
Bug 517: read_encoded() == 0 might not mean EOF if non-blocking.
Without this patch, ELinks showed garbage at
<http://www.dwheeler.com/oss_fs_why.html> when bzip2 decompression was
enabled. safe_read() in bzip2_read() did not see all of the body
bytes that ELinks had received from the server. After bzip2_read()
received EAGAIN from safe_read() and returned 0, something skipped
1460 bytes.
decompress_data() apparently assumed that read_encoded() returning 0
meant the end of the file, and returned even though len still was
nonzero, i.e. it had not yet written to the pipe all the data that
the caller (read_chunked_http_data() or read_normal_http_data()) had
provided. The caller did not know this, and discarded the data.
(cherry picked from commit 7e5e05ca60
)
This commit is contained in:
parent
b03ddccf08
commit
bed84c483e
@ -215,8 +215,14 @@ try_encoding_extensions(struct string *filename, int *fd)
|
|||||||
return ENCODING_NONE;
|
return ENCODING_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reads the file from @stream in chunks of size @readsize. */
|
/** Reads the file from @a stream in chunks of size @a readsize.
|
||||||
/* Returns a connection state. S_OK if all is well. */
|
*
|
||||||
|
* @a stream should be in blocking mode. If it is in non-blocking
|
||||||
|
* mode, this function can return an empty string in @a page just
|
||||||
|
* because no more data is available yet, and the caller cannot know
|
||||||
|
* whether the true end of the stream has been reached.
|
||||||
|
*
|
||||||
|
* @return a connection state. S_OK if all is well. */
|
||||||
enum connection_state
|
enum connection_state
|
||||||
read_file(struct stream_encoded *stream, int readsize, struct string *page)
|
read_file(struct stream_encoded *stream, int readsize, struct string *page)
|
||||||
{
|
{
|
||||||
|
@ -989,7 +989,8 @@ http_send_header(struct socket *socket)
|
|||||||
/* This function decompresses the data block given in @data (if it was
|
/* This function decompresses the data block given in @data (if it was
|
||||||
* compressed), which is long @len bytes. The decompressed data block is given
|
* compressed), which is long @len bytes. The decompressed data block is given
|
||||||
* back to the world as the return value and its length is stored into
|
* back to the world as the return value and its length is stored into
|
||||||
* @new_len.
|
* @new_len. After this function returns, the caller will discard all the @len
|
||||||
|
* input bytes, so this function must use all of them unless an error occurs.
|
||||||
*
|
*
|
||||||
* In this function, value of either http->chunk_remaining or http->length is
|
* In this function, value of either http->chunk_remaining or http->length is
|
||||||
* being changed (it depends on if chunked mode is used or not).
|
* being changed (it depends on if chunked mode is used or not).
|
||||||
@ -1084,11 +1085,16 @@ decompress_data(struct connection *conn, unsigned char *data, int len,
|
|||||||
|
|
||||||
did_read = read_encoded(conn->stream, output + *new_len, BIG_READ);
|
did_read = read_encoded(conn->stream, output + *new_len, BIG_READ);
|
||||||
|
|
||||||
if (did_read > 0) *new_len += did_read;
|
/* Do not break from the loop if did_read == 0. It
|
||||||
else {
|
* means no decoded data is available yet, but some may
|
||||||
if (did_read < 0) state = FINISHING;
|
* become available later. This happens especially with
|
||||||
|
* the bzip2 decoder, which needs an entire compressed
|
||||||
|
* block as input before it generates any output. */
|
||||||
|
if (did_read < 0) {
|
||||||
|
state = FINISHING;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
*new_len += did_read;
|
||||||
} while (len || (did_read == BIG_READ));
|
} while (len || (did_read == BIG_READ));
|
||||||
|
|
||||||
if (state == FINISHING) shutdown_connection_stream(conn);
|
if (state == FINISHING) shutdown_connection_stream(conn);
|
||||||
|
Loading…
Reference in New Issue
Block a user