From cbfd73765a0a867caa984afcc6b8257879242d53 Mon Sep 17 00:00:00 2001 From: Athos Ribeiro Date: Thu, 3 Aug 2023 22:27:49 -0300 Subject: [PATCH] Fix off-by-one bug when truncating tempnam prefix The tempnam documentation currently states that "Only the first 63 characters of the prefix are used, the rest are ignored". However when the prefix is 64 characters-long, the current implementation fails to strip the last character, diverging from the documented behavior. This patch fixes the implementation so it matches the documented behavior for that specific case where the prefix is 64 characters long. Closes GH-11870 Signed-off-by: George Peter Banyard --- NEWS | 2 + ext/standard/file.c | 2 +- .../tests/file/tempnam_variation9.phpt | 73 +++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/file/tempnam_variation9.phpt diff --git a/NEWS b/NEWS index 122e709a9a9..8007ebceaea 100644 --- a/NEWS +++ b/NEWS @@ -49,6 +49,8 @@ PHP NEWS - Standard: . Prevent int overflow on $decimals in number_format. (Marc Bennewitz) + . Fixed bug GH-11870 (Fix off-by-one bug when truncating tempnam prefix) + (athos-ribeiro) 03 Aug 2023, PHP 8.1.22 diff --git a/ext/standard/file.c b/ext/standard/file.c index d51a584ed9c..8bab36096b1 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -834,7 +834,7 @@ PHP_FUNCTION(tempnam) ZEND_PARSE_PARAMETERS_END(); p = php_basename(prefix, prefix_len, NULL, 0); - if (ZSTR_LEN(p) > 64) { + if (ZSTR_LEN(p) >= 64) { ZSTR_VAL(p)[63] = '\0'; } diff --git a/ext/standard/tests/file/tempnam_variation9.phpt b/ext/standard/tests/file/tempnam_variation9.phpt new file mode 100644 index 00000000000..bea93646229 --- /dev/null +++ b/ext/standard/tests/file/tempnam_variation9.phpt @@ -0,0 +1,73 @@ +--TEST-- +Test tempnam() function: usage variations - test prefix maximum size +--SKIPIF-- + +--FILE-- +$prefix) { + echo "-- Iteration $i --\n"; + try { + $file_name = tempnam("$file_path", $prefix); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + continue; + } + + $base_name = basename($file_name); + echo "File name is => ", $base_name, "\n"; + echo "File name length is => ", strlen($base_name), "\n"; + + if (file_exists($file_name)) { + unlink($file_name); + } +} +rmdir($file_path); + +?> +--CLEAN-- + +--EXPECTF-- +*** Testing tempnam() maximum prefix size *** +-- Iteration 0 -- +File name is => begin_%rx{7}%r_end%r.{6}%r +File name length is => 23 +-- Iteration 1 -- +File name is => begin_%rx{53}%r_end%r.{6}%r +File name length is => 69 +-- Iteration 2 -- +File name is => begin_%rx{54}%r_en%r.{6}%r +File name length is => 69 +-- Iteration 3 -- +File name is => begin_%rx{55}%r_e%r.{6}%r +File name length is => 69 +-- Iteration 4 -- +File name is => begin_%rx{57}%r%r.{6}%r +File name length is => 69