more careful isfinite_() checks in skcms_TF_invert()

The fuzzer found a couple non-finite value edge cases:

In one, we end up with inv.a = inf, inv.d = finite, and tweak inv.b to
become -inf.  Then when we assert ad+b >= 0, we calculate inf-inf >= 0,
which is nan >=0, false.  To guard this, check tf_is_valid() after
b-tweak, which will catch any non-finite parameters.

In the other, gamma is large enough that we end up calculating
s = 0.983188629  + 0.951436281) ** 134.4673 == 3.45e38 == NaN
with powf_().  With s = NaN, so is as+b, and the check in powf_()
for x >= 0 fails.  To fix, check isfinite_(s) before using s.

Bug: oss-fuzz:16674, oss-fuzz:16675
Change-Id: I8e83526d7358a0c806720cd1e1458758f3474efc
Reviewed-on: https://skia-review.googlesource.com/c/skcms/+/236860
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
diff --git a/profiles/fuzz/inf_a.icc b/profiles/fuzz/inf_a.icc
new file mode 100644
index 0000000..976834d
--- /dev/null
+++ b/profiles/fuzz/inf_a.icc
Binary files differ
diff --git a/profiles/fuzz/inf_a.icc.txt b/profiles/fuzz/inf_a.icc.txt
new file mode 100644
index 0000000..c84e1c3
--- /dev/null
+++ b/profiles/fuzz/inf_a.icc.txt
@@ -0,0 +1,47 @@
+                Size : 0x000003B7 : 951
+    Data color space : 0x47524159 : 'GRAY'
+                 PCS : 0x58595A20 : 'XYZ '
+           Tag count : 0x00000005 : 5
+
+ Tag    : Type   : Size   : Offset
+ ------ : ------ : ------ : --------
+ '    ' : '    ' :     32 : 32
+ '   ÿ' : '    ' :     32 : 32
+ '    ' : '    ' :     32 : 288
+ '    ' : '    ' :     32 : 288
+ 'kTRC' : 'curv' :    544 : 388
+
+rTRC : 16-bit table with 257 entries
+  ~= : 0.03983583, 0.2187653, -0.0008457435, 0.1250019, 0.00390625, -0.6283875, 0 (Max error: 942760) (D-gap: 7.62865e-05)
+gTRC : 16-bit table with 257 entries
+  ~= : 0.03983583, 0.2187653, -0.0008457435, 0.1250019, 0.00390625, -0.6283875, 0 (Max error: 942760) (D-gap: 7.62865e-05)
+bTRC : 16-bit table with 257 entries
+  ~= : 0.03983583, 0.2187653, -0.0008457435, 0.1250019, 0.00390625, -0.6283875, 0 (Max error: 942760) (D-gap: 7.62865e-05)
+Best : 0.03983583, 0.2187653, -0.0008457435, 0.1250019, 0.00390625, -0.6283875, 0 (D-gap: 7.62865e-05)
+Inv  : 25.10303, 1.06237, 0.6675802, 7.999878, 0.0004882887, 0.005764008, -0 (D-gap: 0.00189783)
+ XYZ : | 0.9614258 0 0 |
+       | 0 1.0004883 0 |
+       | 0 0 0.82470703 |
+252 random bytes transformed to linear XYZD50 bytes:
+	1f2074 f5201a 81201a 1fe37b 97201a 3c201a 0020c3
+	1f20cd 1f20b1 1fec67 ebffbd ef771a 1f741a ef202f
+	272074 1f2085 e2201a 1f209f ef201a 27f91a 1f2072
+	1f205e 1f0085 1f201a 1f20b5 1f20c3 ec20d2 1fff1a
+	71f91a ef201b 1f205a f521cd 1f201a 1f20d2 1fff00
+	efffd2 1ff9ca db2031 1f2a1a 1f201b 1f8944 1f201a
+	cb209f ef201a 1fffa8 a2205e 1ff937 f5204f 1f811a
+	1fff1a 1ff91a 32205d 1fffc3 1f201a 88208e 1f201a
+	ecffca 1f7b1a 1f201a f5201a 37207f 1ffea8 1ff57e
+	1fa547 53f5cb 1f8b1a c501a1 a3001a 5b201a efaa1a
+	1ffd1a 1ff51a 1f341a 34201a ec8f00 00201a ec201a
+	ec201a 1f20cd 1f201a 1ff51a 1f201a f520c7 e34d39
+81 edge-case pixels transformed to sRGB 8888 (unpremul):
+	00fffffe 00f8ff00 00f8ff00  00ff00ff 00ff6c00 00ff6c00  00ff00ff 00ff6c00 00ff6c00
+	0000fcff 0000ff00 0000ff00  007700ff 00636363 00636363  007700ff 00636363 00636363
+	0000fcff 0000ff00 0000ff00  007700ff 00636363 00636363  007700ff 00636363 00636363
+	7ffffffe 7ff8ff00 7ff8ff00  7fff00ff 7fff6c00 7fff6c00  7fff00ff 7fff6c00 7fff6c00
+	7f00fcff 7f00ff00 7f00ff00  7f7700ff 7f636363 7f636363  7f7700ff 7f636363 7f636363
+	7f00fcff 7f00ff00 7f00ff00  7f7700ff 7f636363 7f636363  7f7700ff 7f636363 7f636363
+	fffffffe fff8ff00 fff8ff00  ffff00ff ffff6c00 ffff6c00  ffff00ff ffff6c00 ffff6c00
+	ff00fcff ff00ff00 ff00ff00  ff7700ff ff636363 ff636363  ff7700ff ff636363 ff636363
+	ff00fcff ff00ff00 ff00ff00  ff7700ff ff636363 ff636363  ff7700ff ff636363 ff636363
diff --git a/profiles/fuzz/nan_s.icc b/profiles/fuzz/nan_s.icc
new file mode 100644
index 0000000..25d4983
--- /dev/null
+++ b/profiles/fuzz/nan_s.icc
Binary files differ
diff --git a/profiles/fuzz/nan_s.icc.txt b/profiles/fuzz/nan_s.icc.txt
new file mode 100644
index 0000000..1c1fde1
--- /dev/null
+++ b/profiles/fuzz/nan_s.icc.txt
@@ -0,0 +1,38 @@
+                Size : 0x00000240 : 576
+    Data color space : 0x47524159 : 'GRAY'
+                 PCS : 0x58595A20 : 'XYZ '
+           Tag count : 0x00000001 : 1
+
+ Tag    : Type   : Size   : Offset
+ ------ : ------ : ------ : --------
+ 'kTRC' : 'curv' :    528 : 48
+
+rTRC : 16-bit table with 258 entries
+gTRC : 16-bit table with 258 entries
+bTRC : 16-bit table with 258 entries
+ XYZ : | 0.95739746 0 0 |
+       | 0 1.0083008 0 |
+       | 0 0 0.8161621 |
+252 random bytes transformed to linear XYZD50 bytes:
+	0d201a f42100 1fff1a 1f201a 1f001a 1f201a ee201a
+	33201a 1f201a 1f201a 1f781a 48202c 1f20c8 1f2044
+	1f201a d17f1a 1f201a f4201a 1f9e1a 1f201a 1f201a
+	1f621b dc001a 1f211a dd201a 74b81a 1f3b1a 1fff9d
+	e720cf 1f201a d5201a 1f201a 1fffd0 1f21d0 1f20bf
+	1f201a 1f201a c2c51a 1f201a 38701a 1f201a 75201a
+	1f201a 3d20c0 1f981a 00201a 1f201a f4201a 1f201a
+	ec201a 1f20bb 1f201a 1f9e1a 72201a 1f011a 0b271a
+	f420d0 1f401a 1f21d0 b8201a 1f201a 1f201a 54201a
+	f4c91a 1fff1a 1f20c1 1f02d0 1fcfd0 1fff1a 1f201a
+	5b511a 1fff1a 1f182d 1f2018 f42006 ebff1a 1f201a
+	1f351a f4651a 3c20b9 1fbb1a 60211a f4204a 1f201a
+81 edge-case pixels transformed to sRGB 8888 (unpremul):
+	00636462 007700ff 00636366  0000ff00 0000feff 0000ff00  00626760 007700ff 00626664
+	00ff6d00 00ff00ff 00ff6c00  00f6ff00 00fdfffb 00f6ff00  00ff6f00 00ff00ff 00ff6e00
+	00646461 007800ff 00646365  0000ff00 0000feff 0000ff00  0064675f 007800ff 00646663
+	7f636462 7f7700ff 7f636366  7f00ff00 7f00feff 7f00ff00  7f626760 7f7700ff 7f626664
+	7fff6d00 7fff00ff 7fff6c00  7ff6ff00 7ffdfffb 7ff6ff00  7fff6f00 7fff00ff 7fff6e00
+	7f646461 7f7800ff 7f646365  7f00ff00 7f00feff 7f00ff00  7f64675f 7f7800ff 7f646663
+	ff636462 ff7700ff ff636366  ff00ff00 ff00feff ff00ff00  ff626760 ff7700ff ff626664
+	ffff6d00 ffff00ff ffff6c00  fff6ff00 fffdfffb fff6ff00  ffff6f00 ffff00ff ffff6e00
+	ff646461 ff7800ff ff646365  ff00ff00 ff00feff ff00ff00  ff64675f ff7800ff ff646663
diff --git a/skcms.cc b/skcms.cc
index 3051b67..b26e4d5 100644
--- a/skcms.cc
+++ b/skcms.cc
@@ -1487,6 +1487,12 @@
         inv.b = -inv.a * inv.d;
     }
 
+    // That should usually make tf_is_valid(&inv) true, but there are a couple situations
+    // where we might still fail here, like non-finite parameter values.
+    if (!tf_is_valid(&inv)) {
+        return false;
+    }
+
     assert (inv.a >= 0);
     assert (inv.a * inv.d + inv.b >= 0);
 
@@ -1494,6 +1500,10 @@
     // But to preserve the valuable invariant inv(src(1.0f)) == 1.0f, we'll tweak
     // e or f of the inverse, depending on which segment contains src(1.0f).
     float s = skcms_TransferFunction_eval(src, 1.0f);
+    if (!isfinitef_(s)) {
+        return false;
+    }
+
     float sign = s < 0 ? -1.0f : 1.0f;
     s *= sign;
     if (s < inv.d) {
diff --git a/tests.c b/tests.c
index 03abb03..6911b0b 100644
--- a/tests.c
+++ b/tests.c
@@ -686,6 +686,9 @@
 
     // a + b is negative when inverting, because d>0
     "profiles/fuzz/negative_a_plus_b.icc",            // oss-fuzz:16584
+
+    "profiles/fuzz/nan_s.icc",                        // oss-fuzz:16674
+    "profiles/fuzz/inf_a.icc",                        // oss-fuzz:16675
 };
 
 static void test_Parse(bool regen) {