From f1fe7a0733570e84343f152e2409b22782feb2d3 Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Mon, 14 Oct 2024 11:02:51 +0200 Subject: [PATCH] file set contents: fix error handling with or-operator precedence In perl the `or` and the `||` operator do mostly the same thing but with a different precedence level [0]. A statement like: `$foo += bar() or die "error"` is basically equivalent to: `($foo += bar()) or die "error"` That means as long as bar only returns zero or positive integers the `or die` can only happen the first time, as otherwise $foo is bigger than zero and thus will never evaluate to false. This can be reproduced by perl -we 'my $foo = 1; $foo += 0 or die "wont happen";' While one could switch to the `||` operator, this is a bit to subtle, so to fix this, separate tracking the total bytes written from getting the bytes written by the current call, this avoids the error potential completely. [0]: https://perldoc.perl.org/perlop#Logical-or-and-Exclusive-Or Reported-by: Wolfgang Bumiller Signed-off-by: Thomas Lamprecht --- src/PVE/Tools.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm index e4ff7f9..55aac9f 100644 --- a/src/PVE/Tools.pm +++ b/src/PVE/Tools.pm @@ -299,8 +299,9 @@ sub file_set_contents { my $len = length($data); while ($offset < $len) { - $offset += syswrite($fh, $data, $len - $offset, $offset) + my $written_bytes = syswrite($fh, $data, $len - $offset, $offset) or die "unable to write '$tmpname' - $!\n"; + $offset += $written_bytes; } close $fh or die "closing file '$tmpname' failed - $!\n";