From d445a7e9cc31b94ab1eceb228a7634c79d37496e Mon Sep 17 00:00:00 2001 From: Philip Gladstone Date: Wed, 19 Nov 2003 02:23:17 +0000 Subject: [PATCH] Changed a bunch of calls to sprintf to snprintf to protect against buffer overflows. Fix streaming from non-streaming ffm files. It turned out that you always got 'index & id do not match' errors. Add some more error detection on getting FFM feeds Originally committed as revision 2523 to svn://svn.ffmpeg.org/ffmpeg/trunk --- ffserver.c | 123 ++++++++++++++++++++++++++++------------------------- 1 file changed, 66 insertions(+), 57 deletions(-) diff --git a/ffserver.c b/ffserver.c index 498795f801..eb8b37d0ae 100644 --- a/ffserver.c +++ b/ffserver.c @@ -1253,7 +1253,7 @@ static int http_parse_request(HTTPContext *c) stream = stream->next; } if (stream == NULL) { - sprintf(msg, "File '%s' not found", url); + snprintf(msg, sizeof(msg), "File '%s' not found", url); goto send_error; } @@ -1264,13 +1264,13 @@ static int http_parse_request(HTTPContext *c) if (stream->stream_type == STREAM_TYPE_REDIRECT) { c->http_error = 301; q = c->buffer; - q += sprintf(q, "HTTP/1.0 301 Moved\r\n"); - q += sprintf(q, "Location: %s\r\n", stream->feed_filename); - q += sprintf(q, "Content-type: text/html\r\n"); - q += sprintf(q, "\r\n"); - q += sprintf(q, "Moved\r\n"); - q += sprintf(q, "You should be redirected.\r\n", stream->feed_filename); - q += sprintf(q, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 301 Moved\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Location: %s\r\n", stream->feed_filename); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: text/html\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Moved\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "You should be redirected.\r\n", stream->feed_filename); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); /* prepare output buffer */ c->buffer_ptr = c->buffer; @@ -1296,14 +1296,14 @@ static int http_parse_request(HTTPContext *c) if (post == 0 && max_bandwidth < current_bandwidth) { c->http_error = 200; q = c->buffer; - q += sprintf(q, "HTTP/1.0 200 Server too busy\r\n"); - q += sprintf(q, "Content-type: text/html\r\n"); - q += sprintf(q, "\r\n"); - q += sprintf(q, "Too busy\r\n"); - q += sprintf(q, "The server is too busy to serve your request at this time.

\r\n"); - q += sprintf(q, "The bandwidth being served (including your stream) is %dkbit/sec, and this exceeds the limit of %dkbit/sec\r\n", + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 Server too busy\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: text/html\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Too busy\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "The server is too busy to serve your request at this time.

\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "The bandwidth being served (including your stream) is %dkbit/sec, and this exceeds the limit of %dkbit/sec\r\n", current_bandwidth, max_bandwidth); - q += sprintf(q, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); /* prepare output buffer */ c->buffer_ptr = c->buffer; @@ -1347,29 +1347,29 @@ static int http_parse_request(HTTPContext *c) q = c->buffer; switch(redir_type) { case REDIR_ASX: - q += sprintf(q, "HTTP/1.0 200 ASX Follows\r\n"); - q += sprintf(q, "Content-type: video/x-ms-asf\r\n"); - q += sprintf(q, "\r\n"); - q += sprintf(q, "\r\n"); - q += sprintf(q, "\r\n"); - q += sprintf(q, "\r\n", + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 ASX Follows\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n", hostbuf, filename, info); - q += sprintf(q, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); break; case REDIR_RAM: - q += sprintf(q, "HTTP/1.0 200 RAM Follows\r\n"); - q += sprintf(q, "Content-type: audio/x-pn-realaudio\r\n"); - q += sprintf(q, "\r\n"); - q += sprintf(q, "# Autogenerated by ffserver\r\n"); - q += sprintf(q, "http://%s/%s%s\r\n", + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 RAM Follows\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: audio/x-pn-realaudio\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "# Autogenerated by ffserver\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "http://%s/%s%s\r\n", hostbuf, filename, info); break; case REDIR_ASF: - q += sprintf(q, "HTTP/1.0 200 ASF Redirect follows\r\n"); - q += sprintf(q, "Content-type: video/x-ms-asf\r\n"); - q += sprintf(q, "\r\n"); - q += sprintf(q, "[Reference]\r\n"); - q += sprintf(q, "Ref1=http://%s/%s%s\r\n", + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 ASF Redirect follows\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "[Reference]\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info); break; case REDIR_RTSP: @@ -1380,11 +1380,11 @@ static int http_parse_request(HTTPContext *c) p = strrchr(hostname, ':'); if (p) *p = '\0'; - q += sprintf(q, "HTTP/1.0 200 RTSP Redirect follows\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 RTSP Redirect follows\r\n"); /* XXX: incorrect mime type ? */ - q += sprintf(q, "Content-type: application/x-rtsp\r\n"); - q += sprintf(q, "\r\n"); - q += sprintf(q, "rtsp://%s:%d/%s\r\n", + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/x-rtsp\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename); } @@ -1395,9 +1395,9 @@ static int http_parse_request(HTTPContext *c) int sdp_data_size, len; struct sockaddr_in my_addr; - q += sprintf(q, "HTTP/1.0 200 OK\r\n"); - q += sprintf(q, "Content-type: application/sdp\r\n"); - q += sprintf(q, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/sdp\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); len = sizeof(my_addr); getsockname(c->fd, (struct sockaddr *)&my_addr, &len); @@ -1428,7 +1428,7 @@ static int http_parse_request(HTTPContext *c) } } - sprintf(msg, "ASX/RAM file not handled"); + snprintf(msg, sizeof(msg), "ASX/RAM file not handled"); goto send_error; } @@ -1493,12 +1493,12 @@ static int http_parse_request(HTTPContext *c) } } - sprintf(msg, "POST command not handled"); + snprintf(msg, sizeof(msg), "POST command not handled"); c->stream = 0; goto send_error; } if (http_start_receive_data(c) < 0) { - sprintf(msg, "could not open feed"); + snprintf(msg, sizeof(msg), "could not open feed"); goto send_error; } c->http_error = 0; @@ -1517,17 +1517,17 @@ static int http_parse_request(HTTPContext *c) /* open input stream */ if (open_input_stream(c, info) < 0) { - sprintf(msg, "Input stream corresponding to '%s' not found", url); + snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url); goto send_error; } /* prepare http header */ q = c->buffer; - q += sprintf(q, "HTTP/1.0 200 OK\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n"); mime_type = c->stream->fmt->mime_type; if (!mime_type) mime_type = "application/x-octet_stream"; - q += sprintf(q, "Pragma: no-cache\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n"); /* for asf, we need extra headers */ if (!strcmp(c->stream->fmt->name,"asf_stream")) { @@ -1535,10 +1535,10 @@ static int http_parse_request(HTTPContext *c) c->wmp_client_id = random() & 0x7fffffff; - q += sprintf(q, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=%d\r\nPragma: features=\"broadcast\"\r\n", c->wmp_client_id); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=%d\r\nPragma: features=\"broadcast\"\r\n", c->wmp_client_id); } - q += sprintf(q, "Content-Type: %s\r\n", mime_type); - q += sprintf(q, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); /* prepare output buffer */ c->http_error = 0; @@ -1549,13 +1549,13 @@ static int http_parse_request(HTTPContext *c) send_error: c->http_error = 404; q = c->buffer; - q += sprintf(q, "HTTP/1.0 404 Not Found\r\n"); - q += sprintf(q, "Content-type: %s\r\n", "text/html"); - q += sprintf(q, "\r\n"); - q += sprintf(q, "\n"); - q += sprintf(q, "404 Not Found\n"); - q += sprintf(q, "%s\n", msg); - q += sprintf(q, "\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 404 Not Found\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: %s\r\n", "text/html"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "404 Not Found\n"); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "%s\n", msg); + q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\n"); /* prepare output buffer */ c->buffer_ptr = c->buffer; @@ -1753,7 +1753,7 @@ static void compute_stats(HTTPContext *c) break; case CODEC_TYPE_VIDEO: type = "video"; - sprintf(parameters, "%dx%d, q=%d-%d, fps=%d", st->codec.width, st->codec.height, + snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec.width, st->codec.height, st->codec.qmin, st->codec.qmax, st->codec.frame_rate / st->codec.frame_rate_base); break; default: @@ -2382,6 +2382,14 @@ static int http_receive_data(HTTPContext *c) } } + if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) { + if (c->buffer[0] != 'f' || + c->buffer[1] != 'm') { + http_log("Feed stream has become desynchronized -- disconnecting\n"); + goto fail; + } + } + if (c->buffer_ptr >= c->buffer_end) { FFStream *feed = c->stream; /* a packet has been received : write it in the store, except @@ -3210,6 +3218,7 @@ static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec) fst->priv_data = av_mallocz(sizeof(FeedData)); memcpy(&fst->codec, codec, sizeof(AVCodecContext)); fst->codec.coded_frame = &dummy_frame; + fst->index = stream->nb_streams; stream->streams[stream->nb_streams++] = fst; return fst; } @@ -3289,7 +3298,7 @@ static void extract_mpeg4_header(AVFormatContext *infile) if (!mpeg4_count) return; - printf("MPEG4 without extra data: trying to find header\n"); + printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename); while (mpeg4_count > 0) { if (av_read_packet(infile, &pkt) < 0) break;