Package: rrdtool
Version: 1.2.15-0.3
Severity: critical
Tags: patch,upstream,fixed-upstream
The non-threadsafe version of the rrdtool library has a wrong length for
the buffers of error strings, causing a segfaults in the python or perl
bindings.
This is a known upstream bug :
http://oss.oetiker.ch/rrdtool-trac/ticket/65
It has been fixed in version 1.2.16, with the following patch:
http://oss.oetiker.ch/rrdtool-trac/changeset?new=938&new_path=branches%
2F1.2%2Fprogram%2Fsrc%2Frrd_not_thread_safe.c&old=920&old_path=branches%
2F1.2%2Fprogram%2Fsrc%2Frrd_not_thread_safe.c
This patch is attached to this mail.
I'm also attaching a python script which reproduces this bug. It depends
on python-rrd. See the first lines for more explanations
Index: branches/1.2/program/src/rrd_not_thread_safe.c
===================================================================
--- branches/1.2/program/src/rrd_not_thread_safe.c (revision 860)
+++ branches/1.2/program/src/rrd_not_thread_safe.c (revision 935)
@@ -15,18 +15,24 @@
#define ERRBUFLEN 256
-static char rrd_error[MAXLEN] = "\0";
-static char rrd_liberror[ERRBUFLEN] = "\0";
+static char rrd_error[MAXLEN+10];
+static char rrd_liberror[ERRBUFLEN+10];
+static int rrd_context_init = 0;
/* The global context is very useful in the transition period to even
more thread-safe stuff, it can be used whereever we need a context
and do not need to worry about concurrency. */
static struct rrd_context global_ctx = {
- sizeof(rrd_error),
- sizeof(rrd_liberror),
+ MAXLEN,
+ ERRBUFLEN,
rrd_error,
rrd_liberror
};
-#include <stdarg.h>
+/* #include <stdarg.h> */
-struct rrd_context *rrd_get_context() {
+struct rrd_context *rrd_get_context(void) {
+ if (! rrd_context_init ){
+ rrd_context_init = 1;
+ global_ctx.rrd_error[0]='\0';
+ global_ctx.lib_errstr[0]='\0';
+ }
return &global_ctx;
}
#!/usr/bin/env python
# Depends: python-rrd
# Number of ds to use. 40 does not trigger the bug, 45 does
#ds_number = 40
ds_number = 45
import time, os, rrdtool
filename = "/tmp/test.rrd"
if os.path.exists(filename):
os.remove(filename)
rrd_cmd = [filename, "--step", "300", "--start", str( int(time.time()) - 10 ), 'RRA:AVERAGE:0.5:1:12']
for i in range(ds_number):
rrd_cmd.append("DS:ds%s:COUNTER:600:U:U" % i)
rrdtool.create(*rrd_cmd)
data = str(int(time.time()))
for i in range(ds_number + 1):
data += ":1000"
print "updating..."
rrdtool.update(filename, data)