fix(12-05): cast floats to strings with PHP's 14-digit precision in request validation

PHP 8's (string) cast of a float formats with the precision ini (14
significant digits, %.14G), not the shortest round-trip form: 1/3 is
0.33333333333333, 1e14 is 1.0E+14 and 5e-324 is 4.9406564584125E-324.
phpFloatString, used for the string form of JSON floats in size, in, regex
and integer checks, printed up to 17 digits and switched to the exponent
form only from 1e15. TestPHPFloatStringMatchesPHPCast pins 27 values to
php -r output.
This commit is contained in:
Jakub Zych
2026-10-02 15:46:24 +02:00
parent 36983bc87e
commit 3ac1d64ab4
2 changed files with 75 additions and 12 deletions

View File

@@ -2,6 +2,7 @@ package lagoon
import (
"encoding/json"
"math"
"reflect"
"strings"
"testing"
@@ -209,3 +210,45 @@ func TestValidateRulesMatchLaravel(t *testing.T) {
})
}
}
// TestPHPFloatStringMatchesPHPCast pins phpFloatString to PHP 8's (string)
// cast of a float, which formats with the precision ini (14 significant
// digits, %.14G): the wants are php -r '(string)$x' output.
func TestPHPFloatStringMatchesPHPCast(t *testing.T) {
for _, tc := range []struct {
in float64
want string
}{
{0.1 + 0.2, "0.3"},
{1e14, "1.0E+14"},
{1e15, "1.0E+15"},
{1e20, "1.0E+20"},
{123456789012345.0, "1.2345678901234E+14"},
{12345678901234.0, "12345678901234"},
{1.5e-5, "1.5E-5"},
{0.0001, "0.0001"},
{0.00012345678901234567, "0.00012345678901235"},
{-2.5, "-2.5"},
{3.0, "3"},
{1.0 / 3, "0.33333333333333"},
{2.0 / 3, "0.66666666666667"},
{-1e-10, "-1.0E-10"},
{99999999999999.9, "1.0E+14"},
{0.1, "0.1"},
{999999999999999.0, "1.0E+15"},
{5e-324, "4.9406564584125E-324"},
{1.7976931348623157e308, "1.7976931348623E+308"},
{100.0, "100"},
{1234.5678, "1234.5678"},
{-0.000099999, "-9.9999E-5"},
{0, "0"},
{math.Copysign(0, -1), "-0"},
{math.Inf(1), "INF"},
{math.Inf(-1), "-INF"},
{math.NaN(), "NAN"},
} {
if got := phpFloatString(tc.in); got != tc.want {
t.Errorf("phpFloatString(%v) = %q, want %q", tc.in, got, tc.want)
}
}
}