1
0
mirror of https://gitlab.xiph.org/xiph/icecast-common.git synced 2024-07-21 03:04:15 -04:00

Fix: fixed a lot smaller and bigger bugs in chunked transfer encoding

This fixes a lot bugs.
debug fprintf()s are included intentionally and will be removed
by the next commit.
This commit is contained in:
Philipp Schafft 2015-02-10 21:13:15 +00:00
parent 58cccf307e
commit ea8dde3202

View File

@ -66,7 +66,7 @@ static ssize_t __enc_chunked_read(httpp_encoding_t *self, void *buf, size_t len,
static ssize_t __enc_chunked_write(httpp_encoding_t *self, const void *buf, size_t len, ssize_t (*cb)(void*, const void*, size_t), void *userdata);
/* function to move some data out of our buffers */
static inline ssize_t __copy_buffer(void *dst, void **src, size_t *boffset, size_t *blen, size_t len)
ssize_t __copy_buffer(void *dst, void **src, size_t *boffset, size_t *blen, size_t len)
{
void *p;
size_t have_len;
@ -83,6 +83,8 @@ static inline ssize_t __copy_buffer(void *dst, void **src, size_t *boffset, size
todo = len < have_len ? len : have_len;
fprintf(stderr, "len=%zu, *blen=%zu, *boffset=%zu, todo=%zu\n", len, *blen, *boffset, todo);
memcpy(dst, p, todo);
*boffset += todo;
@ -483,6 +485,7 @@ static ssize_t __enc_chunked_read(httpp_encoding_t *self, void *buf, size_t len,
if (self->read_bytes_till_header > 2) {
size_t todo = len > (self->read_bytes_till_header - 2) ? (self->read_bytes_till_header - 2) : len;
ret = cb(userdata, buf, todo);
fprintf(stderr, "%zu bytes to go, %zu bytes todo, %zi bytes got from backend\n", self->read_bytes_till_header, todo, ret);
if (ret < 1)
return ret;
self->read_bytes_till_header -= ret;
@ -516,12 +519,13 @@ static ssize_t __enc_chunked_read(httpp_encoding_t *self, void *buf, size_t len,
}
self->buf_read_raw_len += ret;
fprintf(stderr, "got %zi bytes\n", ret);
/* now we should have some bytes in our buffer.
* Now skip the "\r\n" that may be left to do from self->read_bytes_till_header.
*/
if (self->buf_read_raw_len == self->read_bytes_till_header) {
if ((self->buf_read_raw_len - self->buf_read_raw_offset) == self->read_bytes_till_header) {
/* ok, that wasn't super big step forward. At least we got rid of self->read_bytes_till_header.
* now freeing buffers again...
*/
@ -531,7 +535,7 @@ static ssize_t __enc_chunked_read(httpp_encoding_t *self, void *buf, size_t len,
self->buf_read_raw_len = 0;
self->read_bytes_till_header = 0;
return 0;
} else if (self->buf_read_raw_len > self->read_bytes_till_header) {
} else if ((self->buf_read_raw_len - self->buf_read_raw_offset) > self->read_bytes_till_header) {
/* ship the tailing "\r\n".
* We should check we really got that and not some other stuff, eh? Yes, I'm sure we should...
*/
@ -549,6 +553,8 @@ static ssize_t __enc_chunked_read(httpp_encoding_t *self, void *buf, size_t len,
* that is part of the header as well!
*/
fprintf(stderr, "current buffer layout: raw{offset=%zu, len=%zu}, decoded{offset=%zu, len=%zu}, read_bytes_till_header=%zu\n", self->buf_read_raw_offset, self->buf_read_raw_len, self->buf_read_decoded_offset, self->buf_read_decoded_len, self->read_bytes_till_header);
in_quote = 0;
offset_extentions = -1;
offset_CR = -1;
@ -556,6 +562,8 @@ static ssize_t __enc_chunked_read(httpp_encoding_t *self, void *buf, size_t len,
for (i = self->buf_read_raw_offset, c = self->buf_read_raw + self->buf_read_raw_offset;
i < self->buf_read_raw_len;
i++, c++) {
if (i < (self->buf_read_raw_offset + 80))
fprintf(stderr, "*c=0x%.2x'%c' in_quote=%i\n", (unsigned int)(unsigned char)*c, *c, in_quote);
if (in_quote) {
if (*c == '\\') in_quote = 2;
else if (*c == '"') in_quote--;
@ -572,6 +580,7 @@ static ssize_t __enc_chunked_read(httpp_encoding_t *self, void *buf, size_t len,
break;
}
}
fprintf(stderr, "current buffer layout: raw{offset=%zu, len=%zu}, decoded{offset=%zu, len=%zu}, read_bytes_till_header=%zu\n", self->buf_read_raw_offset, self->buf_read_raw_len, self->buf_read_decoded_offset, self->buf_read_decoded_len, self->read_bytes_till_header);
/* ok, now we know a lot more!:
* offset_extentions is the offset to the extentions if any.
@ -583,6 +592,13 @@ static ssize_t __enc_chunked_read(httpp_encoding_t *self, void *buf, size_t len,
if (offset_LF == -1)
return 0;
fprintf(stderr, "We got a header, body is at +%zi bytes\n", offset_LF + 1);
fflush(stderr);
if (offset_LF > 1024)
abort();
/* ok. Now we have a complet header.
* First pass the extentions to extention parser if any.
*/
@ -604,9 +620,13 @@ static ssize_t __enc_chunked_read(httpp_encoding_t *self, void *buf, size_t len,
if (sscanf(self->buf_read_raw + self->buf_read_raw_offset, "%llx", &bodylen) != 1)
return -1;
fprintf(stderr, "bodylen=%llu\n", bodylen);
/* ok, Now we move the offset forward to the body. */
self->buf_read_raw_offset = offset_LF + 1;
printf("ok, buffer without header looks like this now: offset=%zu, len=%zu\n", self->buf_read_raw_offset, self->buf_read_raw_len);
/* Do we still have some data in buffer?
* If not free the buffer and set the counters
* to point to the next header.
@ -623,13 +643,15 @@ static ssize_t __enc_chunked_read(httpp_encoding_t *self, void *buf, size_t len,
/* ok, now we check if what we have in the buffer is less or equal than our bodylen. */
if ((self->buf_read_raw_len - self->buf_read_raw_offset) <= bodylen) {
/* ok, this is fantastic. The framework can do the rest for us! */
fprintf(stderr, "nice case: we have a data only buffer!\n");
self->buf_read_decoded = self->buf_read_raw;
self->buf_read_decoded_offset = self->buf_read_raw_offset;
self->buf_read_decoded_len = self->buf_read_decoded_len;
self->buf_read_decoded_len = self->buf_read_raw_len;
self->buf_read_raw = NULL;
self->buf_read_raw_offset = 0;
self->buf_read_raw_len = 0;
self->read_bytes_till_header = bodylen + 2 - (self->buf_read_raw_len - self->buf_read_raw_offset);
self->read_bytes_till_header = bodylen + 2 - (self->buf_read_decoded_len - self->buf_read_decoded_offset);
fprintf(stderr, "final buffer layout: raw{offset=%zu, len=%zu}, decoded{offset=%zu, len=%zu}, read_bytes_till_header=%zu\n", self->buf_read_raw_offset, self->buf_read_raw_len, self->buf_read_decoded_offset, self->buf_read_decoded_len, self->read_bytes_till_header);
return 0;
}
@ -639,6 +661,8 @@ static ssize_t __enc_chunked_read(httpp_encoding_t *self, void *buf, size_t len,
* and let our internal structures point to the next header.
*/
fprintf(stderr, "bad case: we need to allocate a new buffer!\n");
self->buf_read_decoded = malloc(bodylen);
if (!self->buf_read_decoded) /* just retry later if we can not allocate a buffer */
return -1;
@ -648,6 +672,8 @@ static ssize_t __enc_chunked_read(httpp_encoding_t *self, void *buf, size_t len,
self->buf_read_raw_offset += bodylen;
self->read_bytes_till_header = 2; /* tailing "\r\n" */
fprintf(stderr, "final buffer layout: raw{offset=%zu, len=%zu}, decoded{offset=%zu, len=%zu}, read_bytes_till_header=%zu\n", self->buf_read_raw_offset, self->buf_read_raw_len, self->buf_read_decoded_offset, self->buf_read_decoded_len, self->read_bytes_till_header);
return 0;
}