Skip to content

Commit e9f21c3

Browse files
athos-ribeirobon
authored and
bon
committed
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 phpGH-11870 Signed-off-by: George Peter Banyard <girgias@php.net>
1 parent ef6d904 commit e9f21c3

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

ext/standard/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ PHP_FUNCTION(tempnam)
704704
ZEND_PARSE_PARAMETERS_END();
705705

706706
p = php_basename(prefix, prefix_len, NULL, 0);
707-
if (ZSTR_LEN(p) > 64) {
707+
if (ZSTR_LEN(p) >= 64) {
708708
ZSTR_VAL(p)[63] = '\0';
709709
}
710710

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
--TEST--
2+
Test tempnam() function: usage variations - test prefix maximum size
3+
--SKIPIF--
4+
<?php
5+
if (PHP_OS_FAMILY !== 'Windows') {
6+
die("skip Do not run on Windows");
7+
}
8+
?>
9+
--FILE--
10+
<?php
11+
/* Testing the maximum prefix size */
12+
13+
echo "*** Testing tempnam() maximum prefix size ***\n";
14+
$file_path = __DIR__."/tempnamVar9";
15+
mkdir($file_path);
16+
17+
$pre_prefix = "begin_";
18+
$post_prefix = "_end";
19+
$fixed_length = strlen($pre_prefix) + strlen($post_prefix);
20+
/* An array of prefixes */
21+
$names_arr = [
22+
$pre_prefix . str_repeat("x", 7) . $post_prefix,
23+
$pre_prefix . str_repeat("x", 63 - $fixed_length) . $post_prefix,
24+
$pre_prefix . str_repeat("x", 64 - $fixed_length) . $post_prefix,
25+
$pre_prefix . str_repeat("x", 65 - $fixed_length) . $post_prefix,
26+
$pre_prefix . str_repeat("x", 300) . $post_prefix,
27+
];
28+
29+
foreach($names_arr as $i=>$prefix) {
30+
echo "-- Iteration $i --\n";
31+
try {
32+
$file_name = tempnam("$file_path", $prefix);
33+
} catch (Error $e) {
34+
echo $e->getMessage(), "\n";
35+
continue;
36+
}
37+
38+
$base_name = basename($file_name);
39+
echo "File name is => ", $base_name, "\n";
40+
echo "File name length is => ", strlen($base_name), "\n";
41+
42+
if (file_exists($file_name)) {
43+
unlink($file_name);
44+
}
45+
}
46+
rmdir($file_path);
47+
48+
?>
49+
--CLEAN--
50+
<?php
51+
$file_path = __DIR__."/tempnamVar9";
52+
if (file_exists($file_path)) {
53+
array_map('unlink', glob($file_path . "/*"));
54+
rmdir($file_path);
55+
}
56+
?>
57+
--EXPECTF--
58+
*** Testing tempnam() maximum prefix size ***
59+
-- Iteration 0 --
60+
File name is => begin_%rx{7}%r_end%r.{6}%r
61+
File name length is => 23
62+
-- Iteration 1 --
63+
File name is => begin_%rx{53}%r_end%r.{6}%r
64+
File name length is => 69
65+
-- Iteration 2 --
66+
File name is => begin_%rx{54}%r_en%r.{6}%r
67+
File name length is => 69
68+
-- Iteration 3 --
69+
File name is => begin_%rx{55}%r_e%r.{6}%r
70+
File name length is => 69
71+
-- Iteration 4 --
72+
File name is => begin_%rx{57}%r%r.{6}%r
73+
File name length is => 69

0 commit comments

Comments
 (0)