Skip to content

Float fields and sanitizer do not handle scientific notation #1502

@MetaTunes

Description

@MetaTunes

Short description of the issue

$sanitizer->float() does not handle scientific notation even though scientific notation is rendered in InputfieldFloat.

Expected behavior

For example, $sanitzer->float('-1.253E-5') should just return the value unchanged (but as a float , not a string).

Actual behavior

$sanitizer->float('-1.253E-5') returns -1.2535. Entering scientific notation in a float field can therefore result in a grossly inaccurate result. This is particularly an issue since $sanitizer->float(-0.00001253) returns -1.253E-5 so if you enter a number like -0.00001253 into a float field and save it twice, you get -1.2535.

Screenshots/Links that demonstrate the issue

float2

Suggestion for a possible fix

Various regex matches in Sanitizer.php remove any non-numeric characters (lines 3950, 3955, 3957).
For example, the regex in line 3957 - preg_replace('/[^0-9]/', '', substr($str, $pos + 1)); removes any non-numeric character and thus the exponent term 'E-'.
These regexes should leave any terms 'E-', 'E+', 'e-' or 'e+' in place and then line 3960 if(!$options['getString']) $value = floatval($value); should do the required conversion.
However, the string needs to be checked that the exponentiation is at the end (and only once), so the fix is not entirely straighforward.

In any case, there is a short-cut that can be used to check for any internally-produced scientific notation, such as in the
InputfieldFloat rendering. Add, after line 3909, if((string)floatval($value) === $value) $value = floatval($value); or if((string)(float)$value === $value) $value = (float)$value; (or maybe both, to be certain; I'm not quite sure how locales are handled and can't easily test that). That will bypass all the unnecessary regex for simple cases like the example given above. It will not deal with all manually-entered scientific notation, e.g. -1.253E-2, as (float) will convert that to -0.001253 which is not the same string.

Steps to reproduce the issue

  1. Create a new field of type 'float', add it to a template
  2. Create/open a page with that template and enter a number such as -0.00001253 in it
  3. Save the page - the field displays -1.253E-5
  4. Save the page again; the field displays -1.2535.

Setup/Environment

SERVER DETAILS
ProcessWire: 3.0.190
PHP: 8.0.13
Webserver: Apache/2.4.35 (Win64) OpenSSL/1.1.1l
MySQL Server: 5.7.24
MySQL Client: mysqlnd 8.0.13

MODULE DETAILS
AdminPageFieldEditLinks: 3.1.4
ConnectPageFields: 0.3.3
CronjobDatabaseBackup: 1.2.4
FieldtypeCombo: 0.0.7
FieldtypeMeasurement: 0.0.8
FieldtypeRepeaterMatrix: 0.0.8
FieldtypeRuntimeOnly: 0.1.8
FieldtypeTable: 0.2.2
InputfieldCombo: 0.0.7
InputfieldMeasurement: 0.0.7
InputfieldRepeaterMatrix: 0.0.8
InputfieldTable: 0.2.2
PageAutosave: 0.0.6
ProcessDatabaseBackups: 0.0.6
ProcessTracyAdminer: 1.1.3
ProcessWireUpgrade: 0.1.1
ProcessWireUpgradeCheck: 0.0.9
SelectOncePerTable: 0.2.0
TracyDebugger: 4.22.19

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions