Since perl can have multiple internal representations for the same
scalar variables, it calculates and caches them on demand.
So when doing a division with a variable, it calculates and caches the
floating point representation of it.

When using JSON::XS (which is the default and what we use), it has to
look at the internal representation and chooses a format, and if
both integer and floating point representations are there it chooses,
floating point.

This is usually not a problem, but for bigger numbers this representation
changes to the format `1.234e+15`.

Since our API designates the `total` and `used` fields as integers, our
Schema2Rust code wants to de-serialize this as an integer again and
fails with such values. (And with this the PDM de-serialization)

To avoid this internal conversion, extract the variables before doing
division with it, so the original object is not touched.

There might be more places where we do such calculations, but it's hard
to search for them, so let's fix it as we find them.
(And comment to avoid accidental refactoring to the broken code)

Example perl code to reproduce the problem:

```
use JSON;
my $foo = 12057594037927909;
print JSON::encode_json($foo);
```

returns `12057594037927909`, but

```
use JSON;
my $foo = 12057594037927909;
my $bar = 123.123 / $foo;
print JSON::encode_json($foo);
```
return `1.20575940379279e+16`.

This was reported in the PDM forum:
https://forum.proxmox.com/threads/177888/

Signed-off-by: Dominik Csapak <[email protected]>
---
 src/PVE/API2/Storage/Status.pm | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/PVE/API2/Storage/Status.pm b/src/PVE/API2/Storage/Status.pm
index 31bcc6d..8225c3a 100644
--- a/src/PVE/API2/Storage/Status.pm
+++ b/src/PVE/API2/Storage/Status.pm
@@ -257,7 +257,10 @@ __PACKAGE__->register_method({
             }
 
             if ($data->{total}) {
-                $data->{used_fraction} = ($data->{used} // 0) / $data->{total};
+                # extract variables, otherwise the division converts used and 
total to floating points
+                my $total = $data->{total};
+                my $used = $data->{used} // 0;
+                $data->{used_fraction} = $used / $total;
             }
 
             $res->{$storeid} = $data;
-- 
2.47.3



_______________________________________________
pve-devel mailing list
[email protected]
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to