struct tm tm_buf;
+ errno = 0; /* gmtime_r may not set errno; zero it for best-effort reporting */
if (gmtime_r(&now, &tm_buf) == NULL) {
snprintf(buffer, sizeof(buffer), "(time error: %lld e%d)",
(long long) now, errno);
return pid_fd;
}
- if (read(pid_fd, pid_str, sizeof(pid_str)) <= 0) {
+ if (read(pid_fd, pid_str, sizeof(pid_str) - 1) <= 0) {
fprintf(stderr, "FATAL: Empty PID file exist\n");
close(pid_fd);
return -1;
long lval;
errno = 0;
lval = strtol(pid_str, &endptr, 10);
- if (errno != 0 || endptr == pid_str || lval <= 0 || lval > INT_MAX) {
+ /* skip trailing whitespace/newlines from PID file */
+ while (*endptr == ' ' || *endptr == '\n' || *endptr == '\r'
+ || *endptr == '\t')
+ endptr++;
+ if (errno != 0 || endptr == pid_str || *endptr != '\0'
+ || lval <= 0 || lval > INT_MAX) {
fprintf(stderr, "FATAL: PID file is corrupted\n");
close(pid_fd);
return -1;
errno = 0;
lval = strtol(i, &endptr, 10);
if (errno != 0 || endptr == i || *endptr != '\0'
- || lval <= 0 || lval > INT_MAX) {
- rc = send_response(sock, RESP_ERR, "Invalid argument count specified\n");
+ || lval <= 0 || lval > 65536) {
+ rc = send_response(sock, RESP_ERR, "Invalid argument count specified: %s\n", i);
goto done;
}
argc = (int) lval;
}
+ if (argc > (int)(SIZE_MAX / sizeof(char*))) {
+ rc = send_response(sock, RESP_ERR, "Argument count too large\n");
+ goto done;
+ }
if ((argv = malloc(argc * sizeof(char*))) == NULL) {
+ RRDD_LOG(LOG_ERR, "malloc failed for %d argv pointers", argc);
rc = send_response(sock, RESP_ERR, "%s\n", rrd_strerror(ENOMEM));
goto done;
}
lval = strtol(i, &endptr, 10);
if (errno != 0 || endptr == i || *endptr != '\0'
|| lval < 0 || lval > INT_MAX) {
- rc = send_response(sock, RESP_ERR, "Invalid index specified\n");
+ rc = send_response(sock, RESP_ERR, "Invalid index specified: %s\n", i);
goto done;
}
idx = (int) lval;
{
int threads;
+ if (options.optarg == NULL || *options.optarg == '\0') {
+ fprintf(stderr, "Missing argument for -t\n");
+ return 1;
+ }
{
char *endptr;
long lval;
{
char *endptr;
long lval;
+ if (options.optarg == NULL || *options.optarg == '\0') {
+ fprintf(stderr, "Missing argument for -a\n");
+ return 10;
+ }
errno = 0;
lval = strtol(options.optarg, &endptr, 10);
if (errno != 0 || endptr == options.optarg || *endptr != '\0'
dump-restore \
create-with-source-1 create-with-source-2 create-with-source-3 \
create-with-source-4 create-with-source-and-mapping-1 \
- create-from-template-1 dcounter1 vformatter1 xport1 list1 \
- pdp-calc1
+ create-from-template-1 dcounter1 vformatter1 xport1 xport2 list1 \
+ pdp-calc1 graph3
EXTRA_DIST = Makefile.am \
functions $(TESTS) \
tune1-testa-mod1.dump tune1-testa-mod2.dump tune1-testorg.dump \
tune2-testa-mod1.dump tune2-testorg.dump \
valgrind-supressions dcounter1 dcounter1.output graph1.output graph2.output vformatter1 rpn1.output rpn2.output \
- xport1.json.output xport1.xml.output \
+ xport1.json.output xport1.xml.output xport2 graph3 \
pdp-calc1 pdp-calc1-1-avg-60.output pdp-calc1-1-avg-300.output pdp-calc1-1-max-300.output
# NB: AM_TESTS_ENVIRONMENT not available until automake 1.12
--- /dev/null
+#!/bin/bash
+
+. $(dirname $0)/functions
+
+if [ -n "$MSYSTEM" ]; then
+ BUILD=graph3
+else
+ BUILD=$BUILDDIR/graph3
+fi
+
+# Shared RRD: step=300, GAUGE DS. We intentionally leave it with no data
+# updates for the empty-data VDEF_PERCENT test, then add data for the
+# realloc stress test.
+$RRDTOOL create ${BUILD}.rrd \
+ --start 920804400 --step 300 \
+ DS:val:GAUGE:600:U:U \
+ RRA:AVERAGE:0.5:1:600 \
+ RRA:AVERAGE:0.5:12:144
+report "create"
+
+is_cached && exit 0
+
+# --- PR #1312: VDEF PERCENT on all-NaN data must not crash (steps==0 guard) ---
+# No updates issued, so every slot is NaN. rrdtool graph should exit cleanly
+# (rc 0 or 1) without a segfault.
+$RRDTOOL graph /dev/null \
+ --start 920804400 --end 920808000 \
+ DEF:v=${BUILD}.rrd:val:AVERAGE \
+ VDEF:p95=v,95,PERCENTNAN \
+ PRINT:p95:'%lf' 2>/dev/null
+RC=$?
+if [ $RC -le 1 ] ; then
+ ok "VDEF PERCENT on empty data did not crash (rc=$RC)"
+else
+ fail $RC "VDEF PERCENT on empty data crashed or gave unexpected rc"
+fi
+
+# Add data for subsequent tests.
+$RRDTOOL update ${BUILD}.rrd \
+ 920804700:12345 920805000:12357 920805300:12363 \
+ 920805600:12363 920805900:12363 920806200:12373 \
+ 920806500:12383 920806800:12393 920807100:12399 \
+ 920807400:12405 920807700:12411 920808000:12415
+report "update"
+
+# --- PR #1312: graph with many DEF/CDEFs exercises the realloc path ---
+# Fifteen independent CDEFs derived from the same DEF; enough iterations to
+# trigger multiple realloc rounds in the graph element array.
+$RRDTOOL graph /dev/null \
+ --start 920804400 --end 920808000 \
+ DEF:v=${BUILD}.rrd:val:AVERAGE \
+ CDEF:c01=v,1,* \
+ CDEF:c02=v,2,* \
+ CDEF:c03=v,3,* \
+ CDEF:c04=v,4,* \
+ CDEF:c05=v,5,* \
+ CDEF:c06=v,6,* \
+ CDEF:c07=v,7,* \
+ CDEF:c08=v,8,* \
+ CDEF:c09=v,9,* \
+ CDEF:c10=v,10,* \
+ CDEF:c11=v,11,* \
+ CDEF:c12=v,12,* \
+ CDEF:c13=v,13,* \
+ CDEF:c14=v,14,* \
+ CDEF:c15=v,15,* \
+ VDEF:vmax=v,MAXIMUM \
+ PRINT:vmax:'max=%lf' 2>/dev/null
+report "graph realloc stress"
--- /dev/null
+#!/bin/bash
+
+. $(dirname $0)/functions
+
+if [ -n "$MSYSTEM" ]; then
+ BUILD=xport2
+else
+ BUILD=$BUILDDIR/xport2
+fi
+
+# Shared RRD: step=300, a single GAUGE DS, two RRAs.
+$RRDTOOL create ${BUILD}.rrd \
+ --start 1300000000 --step 300 \
+ DS:val:GAUGE:600:U:U \
+ RRA:AVERAGE:0.5:1:600 \
+ RRA:AVERAGE:0.5:12:144
+report "create"
+
+# Feed a handful of data points so the RRAs are not entirely NaN.
+$RRDTOOL update ${BUILD}.rrd \
+ 1300000300:10 1300000600:20 1300000900:30 \
+ 1300001200:40 1300001500:50 1300001800:60 \
+ 1300002100:70 1300002400:80 1300002700:90 \
+ 1300003000:100
+report "update"
+
+is_cached && exit 0
+
+# --- PR #1310: JSON output must be well-formed ---
+# Verify that --json produces output parseable by perl's JSON-like regex
+# heuristic: opening '{' and closing '}' with an "about" key present.
+OUT=$($RRDTOOL xport --json \
+ -s 1300000000 -e 1300003000 --step 300 \
+ DEF:v=${BUILD}.rrd:val:AVERAGE \
+ XPORT:v:val)
+RC=$?
+if [ $RC -ne 0 ] ; then
+ fail $RC "xport --json exited non-zero"
+else
+ # Minimal structural check: starts with '{' and contains the "about" key.
+ echo "$OUT" | grep -q '"about"'
+ report "xport json well-formed"
+fi
+
+# --- PR #1312: --step 0 must not crash (division by zero guard) ---
+$RRDTOOL xport --step 0 \
+ -s 1300000000 -e 1300003000 \
+ DEF:v=${BUILD}.rrd:val:AVERAGE \
+ XPORT:v:val >/dev/null 2>&1
+RC=$?
+if [ $RC -lt 128 ] ; then
+ ok "xport --step 0 did not crash (rc=$RC)"
+else
+ fail $RC "xport --step 0 crashed (signal exit)"
+fi
+
+# --- PR #1312: empty xport (no XPORT statements) must not crash ---
+$RRDTOOL xport \
+ -s 1300000000 -e 1300003000 --step 300 \
+ DEF:v=${BUILD}.rrd:val:AVERAGE 2>/dev/null
+RC=$?
+# rrdtool may return non-zero for no XPORT items; what matters is no crash
+# (segfault would give RC 139 or similar signal exit). Accept 0 or 1.
+if [ $RC -le 1 ] ; then
+ ok "xport with no XPORT statements did not crash (rc=$RC)"
+else
+ fail $RC "xport with no XPORT statements crashed or gave unexpected rc"
+fi