diff options
author | Stefan Holst <holstsn@users.sourceforge.net> | 2002-12-15 01:47:59 +0000 |
---|---|---|
committer | Stefan Holst <holstsn@users.sourceforge.net> | 2002-12-15 01:47:59 +0000 |
commit | 7b2ce3fbf40e6c4916958a8161db38672469d684 (patch) | |
tree | 92b3e33d6f479aa80b302ea998515d104595f4ea | |
parent | f08d47cb298edd6ba5079ef1f41c55b0ab82e5ea (diff) | |
download | xine-lib-7b2ce3fbf40e6c4916958a8161db38672469d684.tar.gz xine-lib-7b2ce3fbf40e6c4916958a8161db38672469d684.tar.bz2 |
Introducing an implementation of dynamic buffer especially useful
for network input plugins to prevent buffer overflows. All the new
functions were prefixed by "xine_buffer".
CVS patchset: 3532
CVS date: 2002/12/15 01:47:59
-rw-r--r-- | src/xine-utils/Makefile.am | 6 | ||||
-rw-r--r-- | src/xine-utils/xine_buffer.c | 364 | ||||
-rw-r--r-- | src/xine-utils/xine_buffer.h | 134 | ||||
-rw-r--r-- | src/xine-utils/xineutils.h | 3 |
4 files changed, 504 insertions, 3 deletions
diff --git a/src/xine-utils/Makefile.am b/src/xine-utils/Makefile.am index 376958b9d..ce090662a 100644 --- a/src/xine-utils/Makefile.am +++ b/src/xine-utils/Makefile.am @@ -22,7 +22,8 @@ libxineutils_la_SOURCES = $(pppc_files) \ xine_check.c \ xine_mutex.c \ xmllexer.c \ - xmlparser.c + xmlparser.c \ + xine_buffer.c libxineutils_la_LIBADD = $(THREAD_LIBS) $(XV_LIB) $(X_LIBS) @@ -32,7 +33,8 @@ include_HEADERS = attributes.h \ xineutils.h \ xine_check.h \ xmllexer.h \ - xmlparser.h + xmlparser.h \ + xine_buffer.h debug: @$(MAKE) CFLAGS="$(DEBUG_CFLAGS) $(THREAD_CFLAGS)" diff --git a/src/xine-utils/xine_buffer.c b/src/xine-utils/xine_buffer.c new file mode 100644 index 000000000..d179b1f66 --- /dev/null +++ b/src/xine-utils/xine_buffer.c @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2000-2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: xine_buffer.c,v 1.1 2002/12/15 01:47:59 holstsn Exp $ + * + * + * generic dynamic buffer functions. The goals + * of these functions are (in fact many of these points + * are todos): + * - dynamic allocation and reallocation depending + * on the size of data written to it. + * - fast and transparent access to the data. + * The user sees only the raw data chunk as it is + * returned by the well-known malloc function. + * This is necessary since not all data-accessing + * functions can be wrapped here. + * - some additional health checks are made during + * development (eg boundary checks after direct + * access to a buffer). This can be turned off in + * production state for higher performance. + * - A lot of convenient string and memory manipulation + * functions are implemented here, where the user + * do not have to care about memory chunk sizes. + * - Some garbage collention could be implemented as well; + * i think of a global structure containing infos + * about all allocated chunks. This must be implemented + * in a thread-save way... + * + * Here are some drawbacks (aka policies): + * - The user must not pass indexed buffers to xine_buffer_* + * functions. + * - The pointers passed to xine_buffer_* functions may change + * (eg during reallocation). The user must respect that. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include "xineutils.h" +#include "xine_buffer.h" + +#define LOG + +#define CHECKS + +/* FIXME */ +#define xine_xmalloc(x) calloc(1,x) + +/* + * private data structs + */ + +typedef struct { + + uint32_t size; + uint32_t chunk_size; + + uint8_t magic; + +} xine_buffer_header_t; + +#define XINE_BUFFER_HEADER_SIZE 9 +#define XINE_BUFFER_MAGIC 42 + +/* + * xine_buffer stores its additional info just in front of + * the public data pointer: + * + * <header 8 bytes> <magic 1 byte> <data> + * ^public pointer + * + * hopefully the magic value will prevent some segfaults, + * if xine_buffer_* functions are called with user-malloced + * data chunks... + */ + + +/* + * some macros + */ + +#define CHECK_MAGIC(x) if (*(((uint8_t *)x)-1)!=XINE_BUFFER_MAGIC) \ + {printf("xine_buffer: FATAL: xine_buffer_header not recognized!\n");exit(1);} + +#define GET_HEADER(x) ((xine_buffer_header_t *)(x-XINE_BUFFER_HEADER_SIZE)) + +/* reallocs buf, if smaller than size. */ +#define GROW_TO(buf, to_size) \ + if (GET_HEADER(buf)->size < (to_size)) { \ + int new_size = (to_size) + GET_HEADER(buf)->chunk_size - \ + ((to_size) % GET_HEADER(buf)->chunk_size);\ + \ + buf = realloc(buf-XINE_BUFFER_HEADER_SIZE, new_size+XINE_BUFFER_HEADER_SIZE);\ + buf += XINE_BUFFER_HEADER_SIZE;\ + GET_HEADER(buf)->size=new_size; } + +/* + * returns an initialized pointer to a buffer. + * The buffer will be allocated in blocks of + * chunk_size bytes. This will prevent permanent + * reallocation on slow growing buffers. + */ +void *xine_buffer_init(int chunk_size) { + + void *data=xine_xmalloc(chunk_size+XINE_BUFFER_HEADER_SIZE); + xine_buffer_header_t *header=(xine_buffer_header_t*)data; + + header->size=chunk_size; + header->chunk_size=chunk_size; + header->magic=XINE_BUFFER_MAGIC; + + return data+XINE_BUFFER_HEADER_SIZE; +} + +/* + * frees a buffer, the macro ensures, that a freed + * buffer pointer is set to NULL + */ +#define xine_buffer_free(buf) buf=_xine_buffer_free(buf) +void *_xine_buffer_free(void *buf) { + +#ifdef CHECKS + if (!buf) { +#ifdef LOG + printf("xine_buffer_free: warning: got NULL pointer\n"); +#endif + return NULL; + } + CHECK_MAGIC(buf); +#endif + + free(buf-XINE_BUFFER_HEADER_SIZE); + + return NULL; +} + +/* + * duplicates a buffer + */ +void *xine_buffer_dup(void *buf) { + + void *new; + +#ifdef CHECKS + if (!buf) { +#ifdef LOG + printf("xine_buffer_dup: warning: got NULL pointer\n"); +#endif + return NULL; + } + CHECK_MAGIC(buf); +#endif + + new=xine_xmalloc(GET_HEADER(buf)->size+XINE_BUFFER_HEADER_SIZE); + + xine_fast_memcpy(new, buf-XINE_BUFFER_HEADER_SIZE, + GET_HEADER(buf)->size+XINE_BUFFER_HEADER_SIZE); + + return new+XINE_BUFFER_HEADER_SIZE; +} + +/* + * will copy len bytes of data into buf at position index. + */ +#define xine_buffer_copyin(buf,i,data,len) \ + buf=_xine_buffer_copyin(buf,i,data,len) +void *_xine_buffer_copyin(void *buf, int index, void *data, int len) { + +#ifdef CHECKS + if (!buf || !data) { +#ifdef LOG + printf("xine_buffer_copyin: warning: got NULL pointer\n"); +#endif + return NULL; + } + CHECK_MAGIC(buf); +#endif + + GROW_TO(buf, index+len); + + xine_fast_memcpy(buf+index, data, len); + + return buf; +} + +/* + * will copy len bytes out of buf+index into data. + * no checks are made in data. It is treated as an ordinary + * user-malloced data chunk. + */ +void xine_buffer_copyout(void *buf, int index, void *data, int len) { + +#ifdef CHECKS + if (!buf || !data) { +#ifdef LOG + printf("xine_buffer_copyout: warning: got NULL pointer\n"); +#endif + return; + } + CHECK_MAGIC(buf); +#endif + + if (GET_HEADER(buf)->size < index+len) + { + printf("xine_buffer_copyout: warning: attempt to read over boundary!\n"); + if (GET_HEADER(buf)->size < index) + return; + len = GET_HEADER(buf)->size - index; + } + xine_fast_memcpy(data, buf+index, len); +} + +/* + * set len bytes in buf+index to b. + */ +#define xine_buffer_set(buf,i,b,len) \ + buf=_xine_buffer_set(buf,i,b,len) +void *_xine_buffer_set(void *buf, int index, uint8_t b, int len) { + +#ifdef CHECKS + if (!buf) { +#ifdef LOG + printf("xine_buffer_set: warning: got NULL pointer\n"); +#endif + return NULL; + } + CHECK_MAGIC(buf); +#endif + + GROW_TO(buf, index+len); + + memset(buf+index, b, len); + + return buf; +} + +/* + * concatnates given buf (which schould contain a null terminated string) + * with another string. + */ +#define xine_buffer_strcat(buf,data) \ + buf=_xine_buffer_strcat(buf,data) +void *_xine_buffer_strcat(void *buf, char *data) { + +#ifdef CHECKS + if (!buf || !data) { +#ifdef LOG + printf("xine_buffer_strcat: warning: got NULL pointer\n"); +#endif + return NULL; + } + CHECK_MAGIC(buf); +#endif + + GROW_TO(buf, strlen(buf)+strlen(data)+1); + + strcat(buf, data); + + return buf; +} + +/* + * copies given string to buf+index + */ +#define xine_buffer_strcpy(buf,index,data) \ + buf=_xine_buffer_strcpy(buf,index,data) +void *_xine_buffer_strcpy(void *buf, int index, char *data) { + +#ifdef CHECKS + if (!buf || !data) { +#ifdef LOG + printf("xine_buffer_strcpy: warning: got NULL pointer\n"); +#endif + return NULL; + } + CHECK_MAGIC(buf); +#endif + + GROW_TO(buf, index+strlen(data)+1); + + strcpy(buf+index, data); + + return buf; +} + +/* + * returns a pointer to the first occurence of needle. + * note, that the returned pointer cannot be used + * in any other xine_buffer_* functions. + */ +char *xine_buffer_strchr(void *buf, int ch) { +#ifdef CHECKS + if (!buf) { +#ifdef LOG + printf("xine_buffer_get_size: warning: got NULL pointer\n"); +#endif + return 0; + } + CHECK_MAGIC(buf); +#endif + + return strchr((const char *)buf, ch); +} + +/* + * get allocated memory size + */ +int xine_buffer_get_size(void *buf) { + +#ifdef CHECKS + if (!buf) { +#ifdef LOG + printf("xine_buffer_get_size: warning: got NULL pointer\n"); +#endif + return 0; + } + CHECK_MAGIC(buf); +#endif + + return GET_HEADER(buf)->size; +} + +/* + * ensures a specified buffer size if the user want to + * write directly to the buffer. Normally the special + * access functions defined here should be used. + */ +#define xine_buffer_ensure_size(buf,data) \ + buf=_xine_buffer_ensure_size(buf,data) +void *_xine_buffer_ensure_size(void *buf, int size) { + +#ifdef CHECKS + if (!buf) { +#ifdef LOG + printf("xine_buffer_ensure_size: warning: got NULL pointer\n"); +#endif + return 0; + } + CHECK_MAGIC(buf); +#endif + + GROW_TO(buf, size); + + return buf; +} + + diff --git a/src/xine-utils/xine_buffer.h b/src/xine-utils/xine_buffer.h new file mode 100644 index 000000000..6ef0e019a --- /dev/null +++ b/src/xine-utils/xine_buffer.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2000-2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: xine_buffer.h,v 1.1 2002/12/15 01:47:59 holstsn Exp $ + * + * + * generic dynamic buffer functions. The goals + * of these functions are (in fact many of these points + * are todos): + * - dynamic allocation and reallocation depending + * on the size of data written to it. + * - fast and transparent access to the data. + * The user sees only the raw data chunk as it is + * returned by the well-known malloc function. + * This is necessary since not all data-accessing + * functions can be wrapped here. + * - some additional health checks are made during + * development (eg boundary checks after direct + * access to a buffer). This can be turned off in + * production state for higher performance. + * - A lot of convenient string and memory manipulation + * functions are implemented here, where the user + * do not have to care about memory chunk sizes. + * - Some garbage collention could be implemented as well; + * i think of a global structure containing infos + * about all allocated chunks. This must be implemented + * in a thread-save way... + * + * Here are some drawbacks (aka policies): + * - The user must not pass indexed buffers to xine_buffer_* + * functions. + * - The pointers passed to xine_buffer_* functions may change + * (eg during reallocation). The user must respect that. + */ + +#ifndef HAVE_XINE_BUFFER_H +#define HAVE_XINE_BUFFER_H + +#include <inttypes.h> + +/* + * returns an initialized pointer to a buffer. + * The buffer will be allocated in blocks of + * chunk_size bytes. This will prevent permanent + * reallocation on slow growing buffers. + */ +void *xine_buffer_init(int chunk_size); + +/* + * frees a buffer, the macro ensures, that a freed + * buffer pointer is set to NULL + */ +#define xine_buffer_free(buf) buf=_xine_buffer_free(buf) +void *_xine_buffer_free(void *buf); + +/* + * duplicates a buffer + */ +void *xine_buffer_dup(void *buf); + +/* + * will copy len bytes of data into buf at position index. + */ +#define xine_buffer_copyin(buf,i,data,len) \ + buf=_xine_buffer_copyin(buf,i,data,len) +void *_xine_buffer_copyin(void *buf, int index, void *data, int len); + +/* + * will copy len bytes out of buf+index into data. + * no checks are made in data. It is treated as an ordinary + * user-malloced data chunk. + */ +void xine_buffer_copyout(void *buf, int index, void *data, int len); + +/* + * set len bytes in buf+index to b. + */ +#define xine_buffer_set(buf,i,b,len) \ + buf=_xine_buffer_set(buf,i,b,len) +void *_xine_buffer_set(void *buf, int index, uint8_t b, int len); + +/* + * concatnates given buf (which schould contain a null terminated string) + * with another string. + */ +#define xine_buffer_strcat(buf,data) \ + buf=_xine_buffer_strcat(buf,data) +void *_xine_buffer_strcat(void *buf, char *data); + +/* + * copies given string to buf+index + */ +#define xine_buffer_strcpy(buf,index,data) \ + buf=_xine_buffer_strcpy(buf,index,data) +void *_xine_buffer_strcpy(void *buf, int index, char *data); + +/* + * returns a pointer to the first occurence of ch. + * note, that the returned pointer cannot be used + * in any other xine_buffer_* functions. + */ +char *xine_buffer_strchr(void *buf, int ch); + +/* + * get allocated memory size + */ +int xine_buffer_get_size(void *buf); + +/* + * ensures a specified buffer size if the user want to + * write directly to the buffer. Normally the special + * access functions defined here should be used. + */ +#define xine_buffer_ensure_size(buf,data) \ + buf=_xine_buffer_ensure_size(buf,data) +void *_xine_buffer_ensure_size(void *buf, int size); + +#endif diff --git a/src/xine-utils/xineutils.h b/src/xine-utils/xineutils.h index 1d6561b8c..0c3fb722f 100644 --- a/src/xine-utils/xineutils.h +++ b/src/xine-utils/xineutils.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xineutils.h,v 1.28 2002/12/04 05:33:40 tmmm Exp $ + * $Id: xineutils.h,v 1.29 2002/12/15 01:47:59 holstsn Exp $ * */ #ifndef XINEUTILS_H @@ -35,6 +35,7 @@ extern "C" { #include "attributes.h" #include "compat.h" #include "xmlparser.h" +#include "xine_buffer.h" /* * debugable mutexes |