edgexfoundry/device-rest-go

Value 0.0 out of float64/float32 range

Closed this issue ยท 0 comments

IkerDC commented

๐Ÿž Bug Report

Affected Services

The issue is located in: REST Device Service. On the handler of the driver: resthandler.go. (The issue causes that any deviceResource being read by the driver with valueType Float64 or Float32 will result in an error if the resource in that moment is equal to 0.0)

Is this a regression?

No, as far as I can see, this bug is present since version v1.0.0.

Description and Minimal Reproduction

When a float64 with value 0.0 is passed to the function checkFloatValueRange(valueType string, val interface{}), it will return an error because the value is out of range. There is a missing check to see if the value is 0.0.

func checkFloatValueRange(valueType string, val interface{}) error {
	switch valueType {
	case common.ValueTypeFloat32:
		valFloat := val.(float32)
		if math.Abs(float64(valFloat)) >= math.SmallestNonzeroFloat32 && math.Abs(float64(valFloat)) <= math.MaxFloat32 {
			return nil
		}
	case common.ValueTypeFloat64:
		valFloat := val.(float64)
		if math.Abs(valFloat) >= math.SmallestNonzeroFloat64 && math.Abs(valFloat) <= math.MaxFloat64 {
			return nil
		}
	}

	return fmt.Errorf("value %v for %s type is out of range", val, valueType)
}

In both cases (32 and 64) the value is checked on the intervarl SmallestNonzero <= value <= MaxFloat. Hence, 0.0 falls outside that interval. However, 0.0 is a valid float.
Result:

val := 0.0
checkFloatValueRange("Float64", val)
// Result: "value 0 for Float64 type is out of range"
// Expected: nil

Additionaly, it seems this check is unecessary if in the line above the val is being casted to the corresponding float type. A check to see if that casting has succeded should be enough to validate the value (as done for checkIntValueRange and checkUintValueRange):

// Example (proposed solution)
func checkFloatValueRange(valueType string, val interface{}) error {
	switch valueType {
	case common.ValueTypeFloat32:
		_, ok := val.(float32)
		if ok {
			return nil
		}
	case common.ValueTypeFloat64:
		_, ok := val.(float64)
		if ok {
			return nil
		}
	}

	return fmt.Errorf("value %v for %s type is out of range", val, valueType)
}

๐Ÿ”ฅ Exception or Error

Any float type with value 0.0, will return an error

val := 0.0
err := checkFloatValueRange("Float64", val)
// err = "value 0 for Float64 type is out of range"

๐ŸŒ Your Environment

Deployment Environment: Ubuntu 20.04

EdgeX Version: v3.0 MInnesota