Skip to content

Commit 22c27cb

Browse files
committed
fixup! Fix counting *scanf() format string placeholders
add a isolated test-case with bug number, like we already have similar to e.g. public function testBug4717(): void
1 parent 9cf5b09 commit 22c27cb

2 files changed

Lines changed: 58 additions & 0 deletions

File tree

tests/PHPStan/Rules/Functions/PrintfParametersRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,9 @@ public function testBug10260(): void
155155
$this->analyse([__DIR__ . '/data/bug-10260.php'], []);
156156
}
157157

158+
public function testBug14567(): void
159+
{
160+
$this->analyse([__DIR__ . '/data/bug-14567.php'], []);
161+
}
162+
158163
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
namespace Bug14567;
4+
5+
// NUL byte terminates sscanf/fscanf format string scanning
6+
7+
// Placeholders after \0 should not be counted
8+
sscanf("12\0003 456 789", "%d %c %d\0 %d %*d", $num, $c, $num);
9+
10+
// Only 1 placeholder active before NUL
11+
sscanf('123 456', "%d\0%d", $a);
12+
13+
// Only 1 placeholder active before NUL (fscanf)
14+
fscanf(STDIN, "%d\0%d", $a2);
15+
16+
// No placeholders after NUL
17+
sscanf('123', "\0%d");
18+
19+
// Multiple placeholders, NUL in middle
20+
sscanf('123 456 789', "%d %d\0%d", $b, $c);
21+
22+
// %n specifier - counts characters consumed, 1 placeholder
23+
sscanf('hello', "%n", $n);
24+
25+
// %% - literal percent, 0 placeholders
26+
sscanf('100%', "100%%");
27+
28+
// %i specifier - integer with base detection, 1 placeholder
29+
sscanf('0xff', "%i", $hex);
30+
31+
// Mixed with %n
32+
sscanf('hello world', "%s%n", $word, $pos);
33+
34+
// %D specifier - uppercase alias for %d, 1 placeholder
35+
sscanf('42', "%D", $dval);
36+
37+
// %g specifier - general float, 1 placeholder
38+
sscanf('1.5', "%g", $gval);
39+
40+
// Size modifiers (l, L, h) - consumed before specifier, 1 placeholder each
41+
sscanf('42', "%ld", $long);
42+
sscanf('3.14', "%lf", $longf);
43+
sscanf('3.14', "%Lf", $longdouble);
44+
sscanf('42', "%hd", $short);
45+
46+
// Size modifier with width
47+
sscanf('42', "%10ld", $widelong);
48+
49+
// Size modifier with suppression - 0 capturing placeholders
50+
sscanf('42 hello', "%*ld %s", $afterskip);
51+
52+
// Mixed size modifiers
53+
sscanf('42 3.14 hello', "%ld %lf %s", $mix1, $mix2, $mix3);

0 commit comments

Comments
 (0)