summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Holst <holstsn@users.sourceforge.net>2002-12-15 01:47:59 +0000
committerStefan Holst <holstsn@users.sourceforge.net>2002-12-15 01:47:59 +0000
commit7b2ce3fbf40e6c4916958a8161db38672469d684 (patch)
tree92b3e33d6f479aa80b302ea998515d104595f4ea
parentf08d47cb298edd6ba5079ef1f41c55b0ab82e5ea (diff)
downloadxine-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.am6
-rw-r--r--src/xine-utils/xine_buffer.c364
-rw-r--r--src/xine-utils/xine_buffer.h134
-rw-r--r--src/xine-utils/xineutils.h3
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