Commit ea47fdf5 authored by Michael Smith's avatar Michael Smith

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
parent 235a2639
...@@ -24,7 +24,8 @@ typedef struct _format_plugin_tag ...@@ -24,7 +24,8 @@ typedef struct _format_plugin_tag
*/ */
int has_predata; 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); refbuf_queue_t *(*get_predata)(struct _format_plugin_tag *self);
void (*free_plugin)(struct _format_plugin_tag *self); void (*free_plugin)(struct _format_plugin_tag *self);
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include "stats.h" #include "stats.h"
#include "format.h" #include "format.h"
#define MAX_HEADER_PAGES 10
typedef struct _vstate_tag typedef struct _vstate_tag
{ {
ogg_sync_state oy; ogg_sync_state oy;
...@@ -26,12 +28,12 @@ typedef struct _vstate_tag ...@@ -26,12 +28,12 @@ typedef struct _vstate_tag
ogg_page og; ogg_page og;
unsigned long serialno; unsigned long serialno;
int header; int header;
refbuf_t *headbuf[10]; refbuf_t *headbuf[MAX_HEADER_PAGES];
int packets; int packets;
} vstate_t; } vstate_t;
void format_vorbis_free_plugin(format_plugin_t *self); 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); refbuf_queue_t *format_vorbis_get_predata(format_plugin_t *self);
format_plugin_t *format_vorbis_get_plugin(void) format_plugin_t *format_vorbis_get_plugin(void)
...@@ -68,7 +70,7 @@ void format_vorbis_free_plugin(format_plugin_t *self) ...@@ -68,7 +70,7 @@ void format_vorbis_free_plugin(format_plugin_t *self)
vorbis_comment_clear(&state->vc); vorbis_comment_clear(&state->vc);
vorbis_info_clear(&state->vi); vorbis_info_clear(&state->vi);
for (i = 0; i < 10; i++) { for (i = 0; i < MAX_HEADER_PAGES; i++) {
if (state->headbuf[i]) { if (state->headbuf[i]) {
refbuf_release(state->headbuf[i]); refbuf_release(state->headbuf[i]);
state->headbuf[i] = NULL; state->headbuf[i] = NULL;
...@@ -81,19 +83,19 @@ void format_vorbis_free_plugin(format_plugin_t *self) ...@@ -81,19 +83,19 @@ void format_vorbis_free_plugin(format_plugin_t *self)
free(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; char *buf;
refbuf_t *refbuf;
int i, result; int i, result;
ogg_packet op; ogg_packet op;
char *tag; char *tag;
refbuf_t *refbuf;
vstate_t *state = (vstate_t *)self->_state; vstate_t *state = (vstate_t *)self->_state;
if (data) { if (data) {
/* write the data to the buffer */ /* write the data to the buffer */
buffer = ogg_sync_buffer(&state->oy, len); buf = ogg_sync_buffer(&state->oy, len);
memcpy(buffer, data, len); memcpy(buf, data, len);
ogg_sync_wrote(&state->oy, 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 ...@@ -109,7 +111,7 @@ refbuf_t *format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned l
state->packets = 0; state->packets = 0;
/* release old headers, stream state, vorbis data */ /* 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]) { if (state->headbuf[i]) {
refbuf_release(state->headbuf[i]); refbuf_release(state->headbuf[i]);
state->headbuf[i] = NULL; state->headbuf[i] = NULL;
...@@ -150,6 +152,10 @@ refbuf_t *format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned l ...@@ -150,6 +152,10 @@ refbuf_t *format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned l
/* cache header pages */ /* cache header pages */
if (state->header > 0) { if (state->header > 0) {
if(state->header > MAX_HEADER_PAGES) {
refbuf_release(refbuf);
return -1;
}
refbuf_addref(refbuf); refbuf_addref(refbuf);
state->headbuf[state->header - 1] = 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 ...@@ -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) 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) ...@@ -184,7 +191,7 @@ refbuf_queue_t *format_vorbis_get_predata(format_plugin_t *self)
vstate_t *state = (vstate_t *)self->_state; vstate_t *state = (vstate_t *)self->_state;
queue = NULL; queue = NULL;
for (i = 0; i < 10; i++) { for (i = 0; i < MAX_HEADER_PAGES; i++) {
if (state->headbuf[i]) { if (state->headbuf[i]) {
refbuf_addref(state->headbuf[i]); refbuf_addref(state->headbuf[i]);
refbuf_queue_add(&queue, state->headbuf[i]); refbuf_queue_add(&queue, state->headbuf[i]);
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
** http parsing engine ** http parsing engine
*/ */
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
...@@ -15,6 +17,8 @@ ...@@ -15,6 +17,8 @@
#define strcasecmp stricmp #define strcasecmp stricmp
#endif #endif
#define MAX_HEADERS 32
/* internal functions */ /* internal functions */
/* misc */ /* misc */
...@@ -48,7 +52,7 @@ void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults) ...@@ -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) int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len)
{ {
char *data, *tmp; 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 i, l, retlen;
int lines; int lines;
char *req_type = NULL; char *req_type = NULL;
...@@ -73,7 +77,7 @@ int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len) ...@@ -73,7 +77,7 @@ int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len)
*/ */
lines = 0; lines = 0;
line[lines] = data; line[lines] = data;
for (i = 0; i < len; i++) { for (i = 0; i < len && lines < MAX_HEADERS; i++) {
if (data[i] == '\r') if (data[i] == '\r')
data[i] = '\0'; data[i] = '\0';
if (data[i] == '\n') { if (data[i] == '\n') {
......
...@@ -35,7 +35,7 @@ typedef struct log_tag ...@@ -35,7 +35,7 @@ typedef struct log_tag
char *filename; char *filename;
FILE *logfile; FILE *logfile;
char *buffer; char *buffer;
} log_t; } log_t;
log_t loglist[LOG_MAXLOGS]; log_t loglist[LOG_MAXLOGS];
...@@ -170,7 +170,9 @@ void log_write(int log_id, int priority, const char *cat, const char *fmt, ...) ...@@ -170,7 +170,9 @@ void log_write(int log_id, int priority, const char *cat, const char *fmt, ...)
va_list ap; va_list ap;
if (log_id < 0) return; if (log_id < 0) return;
if (log_id > LOG_MAXLOGS) return; /* Bad log number */
if (loglist[log_id].level < priority) return; if (loglist[log_id].level < priority) return;
if (priority > 4) return; /* Bad priority */
va_start(ap, fmt); va_start(ap, fmt);
......
...@@ -147,7 +147,11 @@ void *source_main(void *arg) ...@@ -147,7 +147,11 @@ void *source_main(void *arg)
stats_event(source->mount, "description", s); stats_event(source->mount, "description", s);
while (global.running == ICE_RUNNING) { 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) { while (refbuf == NULL) {
bytes = 0; bytes = 0;
while (bytes <= 0) { while (bytes <= 0) {
...@@ -167,7 +171,11 @@ void *source_main(void *arg) ...@@ -167,7 +171,11 @@ void *source_main(void *arg)
if (bytes == 0 || (bytes < 0 && !sock_recoverable(sock_error()))) break; if (bytes == 0 || (bytes < 0 && !sock_recoverable(sock_error()))) break;
} }
if (bytes <= 0) 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) { if (bytes <= 0) {
...@@ -333,6 +341,8 @@ void *source_main(void *arg) ...@@ -333,6 +341,8 @@ void *source_main(void *arg)
avl_tree_unlock(source->client_tree); avl_tree_unlock(source->client_tree);
} }
done:
printf("DEBUG: we're going down...\n"); printf("DEBUG: we're going down...\n");
/* we need to empty the client and pending trees */ /* we need to empty the client and pending trees */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment