github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/staticcheck/sa5009/testdata/src/example.com/CheckPrintf/CheckPrintf.go (about) 1 // Package pkg is amazing. 2 package pkg 3 4 import ( 5 "fmt" 6 "math/big" 7 "os" 8 "unsafe" 9 ) 10 11 type Error int 12 13 func (Error) Error() string { return "" } 14 15 func fn() { 16 var b bool 17 var i int 18 var r rune 19 var s string 20 var x float64 21 var p *int 22 var imap map[int]int 23 var fslice []float64 24 var c complex64 25 // Some good format/argtypes 26 fmt.Printf("") 27 fmt.Printf("%b %b %b", 3, i, x) 28 fmt.Printf("%c %c %c %c", 3, i, 'x', r) 29 fmt.Printf("%d %d %d", 3, i, imap) 30 fmt.Printf("%e %e %e %e", 3e9, x, fslice, c) 31 fmt.Printf("%E %E %E %E", 3e9, x, fslice, c) 32 fmt.Printf("%f %f %f %f", 3e9, x, fslice, c) 33 fmt.Printf("%F %F %F %F", 3e9, x, fslice, c) 34 fmt.Printf("%g %g %g %g", 3e9, x, fslice, c) 35 fmt.Printf("%G %G %G %G", 3e9, x, fslice, c) 36 fmt.Printf("%b %b %b %b", 3e9, x, fslice, c) 37 fmt.Printf("%o %o", 3, i) 38 fmt.Printf("%p", p) 39 fmt.Printf("%q %q %q %q", 3, i, 'x', r) 40 fmt.Printf("%s %s %s", "hi", s, []byte{65}) 41 fmt.Printf("%t %t", true, b) 42 fmt.Printf("%T %T", 3, i) 43 fmt.Printf("%U %U", 3, i) 44 fmt.Printf("%v %v", 3, i) 45 fmt.Printf("%x %x %x %x", 3, i, "hi", s) 46 fmt.Printf("%X %X %X %X", 3, i, "hi", s) 47 fmt.Printf("%.*s %d %g", 3, "hi", 23, 2.3) 48 fmt.Printf("%s", &stringerv) 49 fmt.Printf("%v", &stringerv) 50 fmt.Printf("%T", &stringerv) 51 fmt.Printf("%s", &embeddedStringerv) 52 fmt.Printf("%v", &embeddedStringerv) 53 fmt.Printf("%T", &embeddedStringerv) 54 fmt.Printf("%v", notstringerv) 55 fmt.Printf("%T", notstringerv) 56 fmt.Printf("%q", stringerarrayv) 57 fmt.Printf("%v", stringerarrayv) 58 fmt.Printf("%s", stringerarrayv) 59 fmt.Printf("%v", notstringerarrayv) 60 fmt.Printf("%T", notstringerarrayv) 61 fmt.Printf("%d", new(fmt.Formatter)) 62 fmt.Printf("%f", new(big.Float)) 63 fmt.Printf("%*%", 2) // Ridiculous but allowed. 64 fmt.Printf("%s", interface{}(nil)) // Nothing useful we can say. 65 66 fmt.Printf("%g", 1+2i) 67 fmt.Printf("%#e %#E %#f %#F %#g %#G", 1.2, 1.2, 1.2, 1.2, 1.2, 1.2) // OK since Go 1.9 68 // Some bad format/argTypes 69 fmt.Printf("%b", "hi") //@ diag(`Printf format %b has arg #1 of wrong type string`) 70 _ = fmt.Sprintf("%b", "hi") //@ diag(`Printf format %b has arg #1 of wrong type string`) 71 fmt.Fprintf(os.Stdout, "%b", "hi") //@ diag(`Printf format %b has arg #1 of wrong type string`) 72 fmt.Printf("%t", c) //@ diag(`Printf format %t has arg #1 of wrong type complex64`) 73 fmt.Printf("%t", 1+2i) //@ diag(`Printf format %t has arg #1 of wrong type complex128`) 74 fmt.Printf("%c", 2.3) //@ diag(`Printf format %c has arg #1 of wrong type float64`) 75 fmt.Printf("%d", 2.3) //@ diag(`Printf format %d has arg #1 of wrong type float64`) 76 fmt.Printf("%e", "hi") //@ diag(`Printf format %e has arg #1 of wrong type string`) 77 fmt.Printf("%E", true) //@ diag(`Printf format %E has arg #1 of wrong type bool`) 78 fmt.Printf("%f", "hi") //@ diag(`Printf format %f has arg #1 of wrong type string`) 79 fmt.Printf("%F", 'x') //@ diag(`Printf format %F has arg #1 of wrong type rune`) 80 fmt.Printf("%g", "hi") //@ diag(`Printf format %g has arg #1 of wrong type string`) 81 fmt.Printf("%g", imap) //@ diag(`Printf format %g has arg #1 of wrong type map[int]int`) 82 fmt.Printf("%G", i) //@ diag(`Printf format %G has arg #1 of wrong type int`) 83 fmt.Printf("%o", x) //@ diag(`Printf format %o has arg #1 of wrong type float64`) 84 fmt.Printf("%p", 23) //@ diag(`Printf format %p has arg #1 of wrong type int`) 85 fmt.Printf("%q", x) //@ diag(`Printf format %q has arg #1 of wrong type float64`) 86 fmt.Printf("%s", b) //@ diag(`Printf format %s has arg #1 of wrong type bool`) 87 fmt.Printf("%s", byte(65)) //@ diag(`Printf format %s has arg #1 of wrong type byte`) 88 fmt.Printf("%t", 23) //@ diag(`Printf format %t has arg #1 of wrong type int`) 89 fmt.Printf("%U", x) //@ diag(`Printf format %U has arg #1 of wrong type float64`) 90 fmt.Printf("%X", 2.3) 91 fmt.Printf("%X", 2+3i) 92 fmt.Printf("%s", stringerv) //@ diag(`Printf format %s has arg #1 of wrong type example.com/CheckPrintf.ptrStringer`) 93 fmt.Printf("%t", stringerv) //@ diag(`Printf format %t has arg #1 of wrong type example.com/CheckPrintf.ptrStringer`) 94 fmt.Printf("%s", embeddedStringerv) //@ diag(`Printf format %s has arg #1 of wrong type example.com/CheckPrintf.embeddedStringer`) 95 fmt.Printf("%t", embeddedStringerv) //@ diag(`Printf format %t has arg #1 of wrong type example.com/CheckPrintf.embeddedStringer`) 96 fmt.Printf("%q", notstringerv) //@ diag(`Printf format %q has arg #1 of wrong type example.com/CheckPrintf.notstringer`) 97 fmt.Printf("%t", notstringerv) //@ diag(`Printf format %t has arg #1 of wrong type example.com/CheckPrintf.notstringer`) 98 fmt.Printf("%t", stringerarrayv) //@ diag(`Printf format %t has arg #1 of wrong type example.com/CheckPrintf.stringerarray`) 99 fmt.Printf("%t", notstringerarrayv) //@ diag(`Printf format %t has arg #1 of wrong type example.com/CheckPrintf.notstringerarray`) 100 fmt.Printf("%q", notstringerarrayv) //@ diag(`Printf format %q has arg #1 of wrong type example.com/CheckPrintf.notstringerarray`) 101 fmt.Printf("%d", BoolFormatter(true)) //@ diag(`Printf format %d has arg #1 of wrong type example.com/CheckPrintf.BoolFormatter`) 102 fmt.Printf("%z", FormatterVal(true)) // correct (the type is responsible for formatting) 103 fmt.Printf("%d", FormatterVal(true)) // correct (the type is responsible for formatting) 104 fmt.Printf("%s", nonemptyinterface) // correct (the type is responsible for formatting) 105 fmt.Printf("%.*s %d %6g", 3, "hi", 23, 'x') //@ diag(`Printf format %6g has arg #4 of wrong type rune`) 106 fmt.Printf("%s", "hi", 3) //@ diag(`Printf call needs 1 args but has 2 args`) 107 fmt.Printf("%"+("s"), "hi", 3) //@ diag(`Printf call needs 1 args but has 2 args`) 108 fmt.Printf("%s%%%d", "hi", 3) // correct 109 fmt.Printf("%08s", "woo") // correct 110 fmt.Printf("% 8s", "woo") // correct 111 fmt.Printf("%.*d", 3, 3) // correct 112 fmt.Printf("%.*d x", 3, 3, 3, 3) //@ diag(`Printf call needs 2 args but has 4 args`) 113 fmt.Printf("%.*d x", "hi", 3) //@ diag(`Printf format %.*d reads non-int arg #1 as argument of *`) 114 fmt.Printf("%.*d x", i, 3) // correct 115 fmt.Printf("%.*d x", s, 3) //@ diag(`Printf format %.*d reads non-int arg #1 as argument of *`) 116 fmt.Printf("%*% x", 0.22) //@ diag(`Printf format %*% reads non-int arg #1 as argument of *`) 117 fmt.Printf("%q %q", multi()...) // ok 118 fmt.Printf("%#q", `blah`) // ok 119 const format = "%s %s\n" 120 fmt.Printf(format, "hi", "there") 121 fmt.Printf(format, "hi") //@ diag(`Printf format %s reads arg #2, but call has only 1 args`) 122 fmt.Printf("%s %d %.3v %q", "str", 4) //@ diag(`Printf format %.3v reads arg #3, but call has only 2 args`) 123 124 fmt.Printf("%#s", FormatterVal(true)) // correct (the type is responsible for formatting) 125 fmt.Printf("d%", 2) //@ diag(`couldn't parse format string`) 126 fmt.Printf("%d", percentDV) 127 fmt.Printf("%d", &percentDV) 128 fmt.Printf("%d", notPercentDV) //@ diag(`Printf format %d has arg #1 of wrong type example.com/CheckPrintf.notPercentDStruct`) 129 fmt.Printf("%d", ¬PercentDV) //@ diag(`Printf format %d has arg #1 of wrong type *example.com/CheckPrintf.notPercentDStruct`) 130 fmt.Printf("%p", ¬PercentDV) // Works regardless: we print it as a pointer. 131 fmt.Printf("%q", &percentDV) //@ diag(`Printf format %q has arg #1 of wrong type *example.com/CheckPrintf.percentDStruct`) 132 fmt.Printf("%s", percentSV) 133 fmt.Printf("%s", &percentSV) 134 // Good argument reorderings. 135 fmt.Printf("%[1]d", 3) 136 fmt.Printf("%[1]*d", 3, 1) 137 fmt.Printf("%[2]*[1]d", 1, 3) 138 fmt.Printf("%[2]*.[1]*[3]d", 2, 3, 4) 139 fmt.Fprintf(os.Stderr, "%[2]*.[1]*[3]d", 2, 3, 4) // Use Fprintf to make sure we count arguments correctly. 140 // Bad argument reorderings. 141 fmt.Printf("%[xd", 3) //@ diag(`couldn't parse format string`) 142 fmt.Printf("%[x]d x", 3) //@ diag(`couldn't parse format string`) 143 fmt.Printf("%[3]*s x", "hi", 2) //@ diag(`Printf format %[3]*s reads arg #3, but call has only 2 args`) 144 fmt.Printf("%[3]d x", 2) //@ diag(`Printf format %[3]d reads arg #3, but call has only 1 args`) 145 fmt.Printf("%[2]*.[1]*[3]d x", 2, "hi", 4) //@ diag(`Printf format %[2]*.[1]*[3]d reads non-int arg #2 as argument of *`) 146 fmt.Printf("%[0]s x", "arg1") //@ diag(`Printf format %[0]s reads invalid arg 0; indices are 1-based`) 147 fmt.Printf("%[0]d x", 1) //@ diag(`Printf format %[0]d reads invalid arg 0; indices are 1-based`) 148 149 // Interfaces can be used with any verb. 150 var iface interface { 151 ToTheMadness() bool // Method ToTheMadness usually returns false 152 } 153 fmt.Printf("%f", iface) // ok: fmt treats interfaces as transparent and iface may well have a float concrete type 154 // Can print functions in many ways 155 fmt.Printf("%s", someFunction) //@ diag(`Printf format %s has arg #1 of wrong type func()`) 156 fmt.Printf("%d", someFunction) // ok: maybe someone wants to see the pointer 157 fmt.Printf("%v", someFunction) // ok: maybe someone wants to see the pointer in decimal 158 fmt.Printf("%p", someFunction) // ok: maybe someone wants to see the pointer 159 fmt.Printf("%T", someFunction) // ok: maybe someone wants to see the type 160 // Bug: used to recur forever. 161 fmt.Printf("%p %x", recursiveStructV, recursiveStructV.next) 162 fmt.Printf("%p %x", recursiveStruct1V, recursiveStruct1V.next) 163 fmt.Printf("%p %x", recursiveSliceV, recursiveSliceV) 164 //fmt.Printf("%p %x", recursiveMapV, recursiveMapV) 165 166 // indexed arguments 167 fmt.Printf("%d %[3]d %d %[2]d x", 1, 2, 3, 4) // OK 168 fmt.Printf("%d %[0]d %d %[2]d x", 1, 2, 3, 4) //@ diag(`Printf format %[0]d reads invalid arg 0; indices are 1-based`) 169 fmt.Printf("%d %[3]d %d %[-2]d x", 1, 2, 3, 4) //@ diag(`couldn't parse format string`) 170 fmt.Printf("%d %[3]d %d %[5]d x", 1, 2, 3, 4) //@ diag(`Printf format %[5]d reads arg #5, but call has only 4 args`) 171 fmt.Printf("%d %[3]d %-10d %[2]d x", 1, 2, 3) //@ diag(`Printf format %-10d reads arg #4, but call has only 3 args`) 172 fmt.Printf("%[1][3]d x", 1, 2) //@ diag(`couldn't parse format string`) 173 fmt.Printf("%[1]d x", 1, 2) // OK 174 fmt.Printf("%d %[3]d %d %[2]d x", 1, 2, 3, 4, 5) // OK 175 176 fmt.Printf(someString(), "hello") // OK 177 178 // d accepts pointers as long as they're not to structs. 179 // pointers to structs are dereferenced and walked. 180 fmt.Printf("%d", &s) 181 182 // staticcheck's own checks, based on bugs in go vet; see https://github.com/golang/go/issues/27672 183 { 184 185 type T2 struct { 186 X string 187 } 188 189 type T1 struct { 190 X *T2 191 } 192 x1 := []string{"hi"} 193 t1 := T1{&T2{"hi"}} 194 195 fmt.Printf("%s\n", &x1) 196 fmt.Printf("%s\n", t1) //@ diag(`Printf format %s has arg #1 of wrong type example.com/CheckPrintf.T1`) 197 var x2 struct{ A *int } 198 fmt.Printf("%p\n", x2) //@ diag(`Printf format %p has arg #1 of wrong type struct{A *int}`) 199 var x3 [2]int 200 fmt.Printf("%p", x3) //@ diag(`Printf format %p has arg #1 of wrong type [2]int`) 201 202 ue := unexportedError{nil} 203 fmt.Printf("%s", ue) 204 } 205 206 // staticcheck's own checks, based on our own bugs 207 fmt.Printf("%s", Error(0)) 208 fmt.Printf("%x", unsafe.Pointer(uintptr(0))) 209 } 210 211 func someString() string { return "X" } 212 213 // A function we use as a function value; it has no other purpose. 214 func someFunction() {} 215 216 // multi is used by the test. 217 func multi() []interface{} { 218 return nil 219 } 220 221 type stringer int 222 223 func (stringer) String() string { return "string" } 224 225 type ptrStringer float64 226 227 var stringerv ptrStringer 228 229 func (*ptrStringer) String() string { 230 return "string" 231 } 232 233 type embeddedStringer struct { 234 foo string 235 ptrStringer 236 bar int 237 } 238 239 var embeddedStringerv embeddedStringer 240 241 type notstringer struct { 242 f float64 243 } 244 245 var notstringerv notstringer 246 247 type stringerarray [4]float64 248 249 func (stringerarray) String() string { 250 return "string" 251 } 252 253 var stringerarrayv stringerarray 254 255 type notstringerarray [4]float64 256 257 var notstringerarrayv notstringerarray 258 259 var nonemptyinterface = interface { 260 f() 261 }(nil) 262 263 // A data type we can print with "%d". 264 type percentDStruct struct { 265 a int 266 b []byte 267 c *float64 268 } 269 270 var percentDV percentDStruct 271 272 // A data type we cannot print correctly with "%d". 273 type notPercentDStruct struct { 274 a int 275 b []byte 276 c bool 277 } 278 279 var notPercentDV notPercentDStruct 280 281 // A data type we can print with "%s". 282 type percentSStruct struct { 283 a string 284 b []byte 285 C stringerarray 286 } 287 288 var percentSV percentSStruct 289 290 type BoolFormatter bool 291 292 func (*BoolFormatter) Format(fmt.State, rune) { 293 } 294 295 // Formatter with value receiver 296 type FormatterVal bool 297 298 func (FormatterVal) Format(fmt.State, rune) { 299 } 300 301 type RecursiveSlice []RecursiveSlice 302 303 var recursiveSliceV = &RecursiveSlice{} 304 305 type RecursiveMap map[int]RecursiveMap 306 307 var recursiveMapV = make(RecursiveMap) 308 309 type RecursiveStruct struct { 310 next *RecursiveStruct 311 } 312 313 var recursiveStructV = &RecursiveStruct{} 314 315 type RecursiveStruct1 struct { 316 next *RecursiveStruct2 317 } 318 319 type RecursiveStruct2 struct { 320 next *RecursiveStruct1 321 } 322 323 var recursiveStruct1V = &RecursiveStruct1{} 324 325 type unexportedInterface struct { 326 f interface{} 327 } 328 329 // Issue 17798: unexported ptrStringer cannot be formatted. 330 type unexportedStringer struct { 331 t ptrStringer 332 } 333 type unexportedStringerOtherFields struct { 334 s string 335 t ptrStringer 336 S string 337 } 338 339 // Issue 17798: unexported error cannot be formatted. 340 type unexportedError struct { 341 e error 342 } 343 type unexportedErrorOtherFields struct { 344 s string 345 e error 346 S string 347 } 348 349 type errorer struct{} 350 351 func (e errorer) Error() string { return "errorer" } 352 353 type unexportedCustomError struct { 354 e errorer 355 } 356 357 type errorInterface interface { 358 error 359 ExtraMethod() 360 } 361 362 type unexportedErrorInterface struct { 363 e errorInterface 364 } 365 366 func UnexportedStringerOrError() { 367 fmt.Printf("%s", unexportedInterface{"foo"}) // ok; prints {foo} 368 fmt.Printf("%s", unexportedInterface{3}) // ok; we can't see the problem 369 370 us := unexportedStringer{} 371 fmt.Printf("%s", us) //@ diag(`Printf format %s has arg #1 of wrong type example.com/CheckPrintf.unexportedStringer`) 372 fmt.Printf("%s", &us) //@ diag(`Printf format %s has arg #1 of wrong type *example.com/CheckPrintf.unexportedStringer`) 373 374 usf := unexportedStringerOtherFields{ 375 s: "foo", 376 S: "bar", 377 } 378 fmt.Printf("%s", usf) //@ diag(`Printf format %s has arg #1 of wrong type example.com/CheckPrintf.unexportedStringerOtherFields`) 379 fmt.Printf("%s", &usf) //@ diag(`Printf format %s has arg #1 of wrong type *example.com/CheckPrintf.unexportedStringerOtherFields`) 380 381 intSlice := []int{3, 4} 382 fmt.Printf("%s", intSlice) //@ diag(`Printf format %s has arg #1 of wrong type []int`) 383 nonStringerArray := [1]unexportedStringer{{}} 384 fmt.Printf("%s", nonStringerArray) //@ diag(`Printf format %s has arg #1 of wrong type [1]example.com/CheckPrintf.unexportedStringer`) 385 fmt.Printf("%s", []stringer{3, 4}) // not an error 386 fmt.Printf("%s", [2]stringer{3, 4}) // not an error 387 } 388 389 // TODO: Disable complaint about '0' for Go 1.10. To be fixed properly in 1.11. 390 // See issues 23598 and 23605. 391 func DisableErrorForFlag0() { 392 fmt.Printf("%0t", true) 393 } 394 395 // Issue 26486. 396 func dbg(format string, args ...interface{}) { 397 if format == "" { 398 format = "%v" 399 } 400 fmt.Printf(format, args...) 401 } 402 403 // https://github.com/dominikh/go-tools/issues/714 404 func fn2() { 405 type String string 406 type Byte byte 407 408 var a string = "a" 409 var b []byte = []byte{'b'} 410 var c [1]byte = [1]byte{'c'} 411 var d String = "d" 412 var e []uint8 = []uint8{'e'} 413 var f []Byte = []Byte{'h'} 414 fmt.Printf("%s %s %s %s %s %s %s", a, b, c, &c, d, e, f) 415 } 416 417 func fn3() { 418 s := "%d" 419 if true { 420 fmt.Printf(s, "") //@ diag(`Printf format`) 421 } else { 422 _ = s 423 } 424 }