]> gitweb.michael.orlitzky.com - libsvgtiny.git/commitdiff
src/svgtiny_gradient.c: be more careful with float -> int assignment
authorMichael Orlitzky <michael@orlitzky.com>
Sun, 8 Jun 2025 00:58:50 +0000 (20:58 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Sun, 8 Jun 2025 02:18:16 +0000 (22:18 -0400)
Assigning the value of a float to an unsigned int is undefined
behavior unless the value is guaranteed to fit. We run afoul of this
in compute_grad_points(), where the number of steps is computed using
a floating point calculation.

On a RISC-V / musl system, the end result is that we wind up with
steps = the maximum value of an unsigned int, when really this should
be an error case resulting in steps = 1. The test suite catches this.

src/svgtiny_gradient.c

index ca961ccf7c5535ffff5e99bb734f9d2b6e6ef232..8fd0f83a1e84a4b181c0850f4cb4f8c520bd0e54 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <assert.h>
+#include <limits.h>
 #include <math.h>
 #include <string.h>
 #include <stdio.h>
@@ -427,7 +428,18 @@ compute_grad_points(float *p,
                if(isnan(r0) || isnan(r1)) {
                        steps = 1;
                } else {
-                       steps = ceilf(fabsf(r1 - r0) / 0.05);
+                       /* float -> int assignment is undefined unless
+                        * the value is guaranteed to fit */
+                       float stepsf = ceilf(fabsf(r1 - r0) / 0.05);
+                       if (isnan(stepsf)) {
+                               steps = 1;
+                       }
+                       else if (stepsf > (float)UINT_MAX) {
+                               steps = 1;
+                       }
+                       else {
+                               steps = stepsf;
+                       }
                }
 
                if (steps == 0)