]> git.ipfire.org Git - thirdparty/rrdtool-1.x.git/commitdiff
Fix SIGFPE in rrdtool dump on crafted RRDs (#783)
authorTobias Oetiker <tobi@oetiker.ch>
Tue, 26 May 2026 14:42:33 +0000 (16:42 +0200)
committerTobias Oetiker <tobi@oetiker.ch>
Tue, 26 May 2026 14:42:33 +0000 (16:42 +0200)
When a fuzz-crafted RRD file contains an RRA with pdp_cnt == 0 or
pdp_step == 0, rrd_dump_cb_r performed a modulo operation whose
divisor could be zero, triggering a SIGFPE.  Add a guard at the top
of the per-RRA loop that rejects such files with rrd_set_error()
and a clean return rather than crashing.

Reported by @rwhitworth.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CHANGES
src/rrd_dump.c

diff --git a/CHANGES b/CHANGES
index fe64e8880051d0023c4f0f621f7b7a5ef8eeff58..8e8db103d44fb48bae62b3508449ba90b29917d2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -22,6 +22,12 @@ Bugfixes
   text documentation works on systems with BSD-derived nroff (e.g.
   macOS /usr/bin/nroff). Issue #1323 reported by @gigaimage, fixed by
   @oetiker
+* Fix SIGFPE divide-by-zero crash in `rrdtool dump` when processing
+  fuzz-crafted RRD files that contain an RRA with `pdp_cnt` or
+  `pdp_step` equal to zero. The modulo operation at the heart of the
+  timestamp calculation is now guarded: such files are rejected with
+  a descriptive error message instead of crashing.
+  Issue #783 reported by @rwhitworth, fix by @oetiker.
 
 Features
 --------
index cdee9377210c9a73db187d5cb16de48a2bdc5aa2..0f00bcd1068181e0306e5aa5821e9a22a5953aae 100644 (file)
@@ -209,12 +209,19 @@ int rrd_dump_cb_r(
         rra_next += (rrd.stat_head->ds_cnt
                      * rrd.rra_def[i].row_cnt * sizeof(rrd_value_t));
 
+        if (rrd.rra_def[i].pdp_cnt == 0 || rrd.stat_head->pdp_step == 0) {
+            rrd_set_error("invalid RRA %u: pdp_cnt or pdp_step is zero", i);
+            rrd_free(&rrd);
+            rrd_close(rrd_file);
+            return (-1);
+        }
+
         CB_PUTS("\t<rra>\n");
 
         CB_FMTS("\t\t<cf>%s</cf>\n", rrd.rra_def[i].cf_nam);
 
         CB_FMTS("\t\t<pdp_per_row>%lu</pdp_per_row> <!-- %lu seconds -->\n\n",
-            rrd.rra_def[i].pdp_cnt, 
+            rrd.rra_def[i].pdp_cnt,
             rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step);
 
         /* support for RRA parameters */