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 | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/svgtiny_gradient.c b/src/svgtiny_gradient.c
index ca961cc..8fd0f83 100644
--- a/src/svgtiny_gradient.c
+++ b/src/svgtiny_gradient.c
@@ -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)
-- 
2.49.0
 
No comments:
Post a Comment