mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2025-02-02 15:07:36 -05:00
Buffer overflows.
Requires a change to the format plugin interface - jack: if you want this done differently, feel free to change it (or ask me to). svn path=/trunk/httpp/; revision=3219
This commit is contained in:
parent
235a2639cc
commit
ea47fdf504
@ -24,7 +24,8 @@ typedef struct _format_plugin_tag
|
||||
*/
|
||||
int has_predata;
|
||||
|
||||
refbuf_t *(*get_buffer)(struct _format_plugin_tag *self, char *data, unsigned long len);
|
||||
int (*get_buffer)(struct _format_plugin_tag *self, char *data, unsigned long
|
||||
len, refbuf_t **buffer);
|
||||
refbuf_queue_t *(*get_predata)(struct _format_plugin_tag *self);
|
||||
void (*free_plugin)(struct _format_plugin_tag *self);
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "stats.h"
|
||||
#include "format.h"
|
||||
|
||||
#define MAX_HEADER_PAGES 10
|
||||
|
||||
typedef struct _vstate_tag
|
||||
{
|
||||
ogg_sync_state oy;
|
||||
@ -26,12 +28,12 @@ typedef struct _vstate_tag
|
||||
ogg_page og;
|
||||
unsigned long serialno;
|
||||
int header;
|
||||
refbuf_t *headbuf[10];
|
||||
refbuf_t *headbuf[MAX_HEADER_PAGES];
|
||||
int packets;
|
||||
} vstate_t;
|
||||
|
||||
void format_vorbis_free_plugin(format_plugin_t *self);
|
||||
refbuf_t *format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned long len);
|
||||
int format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned long len, refbuf_t **buffer);
|
||||
refbuf_queue_t *format_vorbis_get_predata(format_plugin_t *self);
|
||||
|
||||
format_plugin_t *format_vorbis_get_plugin(void)
|
||||
@ -68,7 +70,7 @@ void format_vorbis_free_plugin(format_plugin_t *self)
|
||||
vorbis_comment_clear(&state->vc);
|
||||
vorbis_info_clear(&state->vi);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < MAX_HEADER_PAGES; i++) {
|
||||
if (state->headbuf[i]) {
|
||||
refbuf_release(state->headbuf[i]);
|
||||
state->headbuf[i] = NULL;
|
||||
@ -81,19 +83,19 @@ void format_vorbis_free_plugin(format_plugin_t *self)
|
||||
free(self);
|
||||
}
|
||||
|
||||
refbuf_t *format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned long len)
|
||||
int format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned long len, refbuf_t **buffer)
|
||||
{
|
||||
char *buffer;
|
||||
refbuf_t *refbuf;
|
||||
char *buf;
|
||||
int i, result;
|
||||
ogg_packet op;
|
||||
char *tag;
|
||||
refbuf_t *refbuf;
|
||||
vstate_t *state = (vstate_t *)self->_state;
|
||||
|
||||
if (data) {
|
||||
/* write the data to the buffer */
|
||||
buffer = ogg_sync_buffer(&state->oy, len);
|
||||
memcpy(buffer, data, len);
|
||||
buf = ogg_sync_buffer(&state->oy, len);
|
||||
memcpy(buf, data, len);
|
||||
ogg_sync_wrote(&state->oy, len);
|
||||
}
|
||||
|
||||
@ -109,7 +111,7 @@ refbuf_t *format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned l
|
||||
state->packets = 0;
|
||||
|
||||
/* release old headers, stream state, vorbis data */
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < MAX_HEADER_PAGES; i++) {
|
||||
if (state->headbuf[i]) {
|
||||
refbuf_release(state->headbuf[i]);
|
||||
state->headbuf[i] = NULL;
|
||||
@ -150,6 +152,10 @@ refbuf_t *format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned l
|
||||
|
||||
/* cache header pages */
|
||||
if (state->header > 0) {
|
||||
if(state->header > MAX_HEADER_PAGES) {
|
||||
refbuf_release(refbuf);
|
||||
return -1;
|
||||
}
|
||||
refbuf_addref(refbuf);
|
||||
state->headbuf[state->header - 1] = refbuf;
|
||||
|
||||
@ -174,7 +180,8 @@ refbuf_t *format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned l
|
||||
}
|
||||
}
|
||||
|
||||
return refbuf;
|
||||
*buffer = refbuf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
refbuf_queue_t *format_vorbis_get_predata(format_plugin_t *self)
|
||||
@ -184,7 +191,7 @@ refbuf_queue_t *format_vorbis_get_predata(format_plugin_t *self)
|
||||
vstate_t *state = (vstate_t *)self->_state;
|
||||
|
||||
queue = NULL;
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < MAX_HEADER_PAGES; i++) {
|
||||
if (state->headbuf[i]) {
|
||||
refbuf_addref(state->headbuf[i]);
|
||||
refbuf_queue_add(&queue, state->headbuf[i]);
|
||||
|
@ -3,6 +3,8 @@
|
||||
** http parsing engine
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
@ -15,6 +17,8 @@
|
||||
#define strcasecmp stricmp
|
||||
#endif
|
||||
|
||||
#define MAX_HEADERS 32
|
||||
|
||||
/* internal functions */
|
||||
|
||||
/* misc */
|
||||
@ -48,7 +52,7 @@ void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults)
|
||||
int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len)
|
||||
{
|
||||
char *data, *tmp;
|
||||
char *line[32]; /* limited to 32 lines, should be more than enough */
|
||||
char *line[MAX_HEADERS]; /* limited to 32 lines, should be more than enough */
|
||||
int i, l, retlen;
|
||||
int lines;
|
||||
char *req_type = NULL;
|
||||
@ -73,7 +77,7 @@ int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len)
|
||||
*/
|
||||
lines = 0;
|
||||
line[lines] = data;
|
||||
for (i = 0; i < len; i++) {
|
||||
for (i = 0; i < len && lines < MAX_HEADERS; i++) {
|
||||
if (data[i] == '\r')
|
||||
data[i] = '\0';
|
||||
if (data[i] == '\n') {
|
||||
|
@ -170,7 +170,9 @@ void log_write(int log_id, int priority, const char *cat, const char *fmt, ...)
|
||||
va_list ap;
|
||||
|
||||
if (log_id < 0) return;
|
||||
if (log_id > LOG_MAXLOGS) return; /* Bad log number */
|
||||
if (loglist[log_id].level < priority) return;
|
||||
if (priority > 4) return; /* Bad priority */
|
||||
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
14
src/source.c
14
src/source.c
@ -147,7 +147,11 @@ void *source_main(void *arg)
|
||||
stats_event(source->mount, "description", s);
|
||||
|
||||
while (global.running == ICE_RUNNING) {
|
||||
refbuf = source->format->get_buffer(source->format, NULL, 0);
|
||||
int ret = source->format->get_buffer(source->format, NULL, 0, &refbuf);
|
||||
if(ret < 0) {
|
||||
WARN0("Bad data from source");
|
||||
break;
|
||||
}
|
||||
while (refbuf == NULL) {
|
||||
bytes = 0;
|
||||
while (bytes <= 0) {
|
||||
@ -167,7 +171,11 @@ void *source_main(void *arg)
|
||||
if (bytes == 0 || (bytes < 0 && !sock_recoverable(sock_error()))) break;
|
||||
}
|
||||
if (bytes <= 0) break;
|
||||
refbuf = source->format->get_buffer(source->format, buffer, bytes);
|
||||
ret = source->format->get_buffer(source->format, buffer, bytes, &refbuf);
|
||||
if(ret < 0) {
|
||||
WARN0("Bad data from source");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes <= 0) {
|
||||
@ -333,6 +341,8 @@ void *source_main(void *arg)
|
||||
avl_tree_unlock(source->client_tree);
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
printf("DEBUG: we're going down...\n");
|
||||
|
||||
/* we need to empty the client and pending trees */
|
||||
|
Loading…
Reference in New Issue
Block a user