Repository: VKCOM/noverify
Pull request #760 (2020-09-03 09:13:19)

linter: move bitwiseOps to dynamic rules
As a bonus, & and | that are used instead of && and || now
can be auto-fixed.

We also start to check for &, | and ^ applied to non-numeric
types. In our test corpus it only triggers in math library
that does that on purpose (bitwise work on strings).
Since sometimes this is a desired behavior, these extra
patterns have MAYBE severity level.

Signed-off-by: Iskander Sharipov <quasilyte@gmail.com>


Patch:
diff --git a/src/cmd/embeddedrules/rules.go b/src/cmd/embeddedrules/rules.go
index 1e25e3a..c35d749 100644
--- a/src/cmd/embeddedrules/rules.go
+++ b/src/cmd/embeddedrules/rules.go
@@ -77,7 +77,7 @@ func (fi bindataFileInfo) Sys() interface{} {
 	return nil
 }
 
-var _embeddedrulesRulesPhp = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x98\xd1\x6f\xe2\xb8\x13\xc7\xdf\x91\xf8\x1f\x06\x94\x52\x60\x81\xfc\xaa\xdf\x5b\x5b\xda\xbd\x7b\x3b\x69\x75\x95\xee\x1e\x4f\x2d\x38\xc9\x84\x78\x1b\xec\x9c\xed\x2c\x70\x85\xff\xfd\xe4\x38\x84\x40\x0c\x24\x5b\x5d\xa5\x52\x18\xdb\xf3\x99\x99\xef\x24\x19\xfa\xf8\x9c\x44\x49\xbb\xd5\x6e\xb9\xc3\x61\xbb\x05\x43\xf8\xca\x38\x65\x32\x41\x5f\x51\xce\xe0\x97\x6f\xdf\x8c\x35\xa6\x4c\xa1\x00\xf3\x13\x50\x49\xbc\x18\xf5\x8a\x7b\x74\xd6\xe7\xcb\x25\x32\x05\x7f\x60\xc2\x85\x02\x85\x82\x11\xb1\x01\x5c\x27\x02\xa5\xa4\x9c\x49\x50\x11\x51\xe0\x13\x06\x1e\x82\xa4\xcb\x24\xa6\x21\xc5\x60\x62\xce\x7b\x18\x72\x81\x00\xce\x1a\x9e\xf5\xcb\x3d\x38\x1b\xb3\x42\x42\x83\xd7\x2b\x07\x6b\x48\xd7\x59\x40\x65\xab\xdb\x6e\x85\x29\x33\xe1\xe7\x01\xfc\x69\x38\x9b\xfe\x00\x3e\xda\x2d\x00\x13\x2f\x68\x0f\x4b\xb2\xf1\x10\x7c\x9e\xc6\x01\x08\x4c\x62\xe2\x23\xa8\x08\x8b\xd0\x57\x54\x45\xf0\x3d\x95\x0a\x1c\x9f\xb3\x60\x7f\x4c\x6d\x12\x04\x8f\xf3\xb8\x6c\x76\xf5\x9f\xec\x33\x3c\x83\x12\x29\xc2\x3d\x84\x24\x96\xf8\xa0\x8b\x74\x01\xbb\x12\x54\x21\x10\x09\xf3\xbe\xf6\x39\xc8\x7c\xcc\x8f\x58\xd0\xf9\x0f\x68\xfb\xb2\x15\x28\x5d\xcf\x52\x2d\x33\x5b\x92\x0a\x04\x67\x5d\x86\x96\xd4\x69\x06\x7b\xb6\xc1\x9e\x0b\x58\xe6\x9d\x4a\x89\xaa\xef\xac\x07\x47\x90\xdd\xa5\x3e\x4b\xb8\x42\xa6\x28\x89\x81\x27\x28\x48\x26\x7d\x22\xd0\xc7\x00\x99\x8f\xda\x63\x8a\xb2\xda\x62\x3d\x70\x96\x44\xbe\xc3\x74\x0a\xff\x7b\x00\xd7\xd5\x6f\x22\x22\x21\xa2\x8b\x08\x45\xd9\x83\x8a\x08\x83\xde\x71\x27\xf6\x0f\x1e\x06\x99\x8b\xd3\xe6\x3b\x9c\x2f\xfa\xce\x85\xdf\xb9\xc2\x7b\x58\xa1\x6e\x36\x1d\xfa\xbc\x14\x47\x67\xaa\xcb\xa3\x8b\x45\x2a\xe1\x03\xfe\x40\x96\xfb\xa0\x21\xd0\xe2\x1a\xf2\x49\xba\x88\x94\xe9\xd3\xb9\x6e\x15\x3f\x42\xff\xfd\x25\x99\xe7\x57\x9a\xfe\x24\xc1\xe3\x2a\x32\xc5\x31\xed\xe3\xba\xa0\xf7\x4a\xc8\x1a\x0e\xa8\x04\xc6\x15\x10\x58\x70\x1e\xec\xf7\x41\xc8\x05\x78\x54\xad\xa8\xc4\x43\x61\x07\x13\x73\x3e\xf7\x62\x14\xa0\x6c\x01\x73\xca\x7e\x90\x98\x06\xc6\xf1\x48\x5f\xf4\xe8\x2b\x0c\x80\xa5\x4b\x0f\x05\x84\x3c\x65\x41\x76\xcd\xcc\x81\xca\xfc\xb8\xa6\x66\x71\x46\x18\x27\x61\x1a\x8f\xc0\x43\x9f\xa4\xd2\x5c\x84\x82\x73\x05\x3c\xcc\xde\x27\x82\x7b\x31\x2e\x75\xa8\x87\xda\xe4\xb1\xc0\x6f\x65\x34\x10\x81\x40\x40\xa0\x4c\xe3\xfc\x38\x51\x93\xa2\x4f\xe1\xeb\x8a\x08\xa6\x23\xbe\x22\x77\xde\x8f\x84\x6d\x66\xf8\xf7\xcc\xa3\x8a\xb0\xe0\xde\x08\x09\xe0\xcc\xf4\x71\x67\xa6\xc5\x9b\x3d\x14\xb6\x5e\xb1\x90\xd9\x76\x15\x66\xa7\x36\x93\x59\xa1\x9d\x73\xd0\xce\x05\xe8\xb4\x49\xa6\xff\xb7\xa6\x7a\x3e\xd7\x8b\xc9\x36\xc9\xd6\x06\xee\x9c\x05\x77\x8e\xc0\x0d\xb5\xdd\x56\xb4\xe5\xa2\x2a\xed\xf6\x88\xba\xfd\x9c\xb4\xdb\xaa\xb4\xc7\xcc\xce\x39\xe6\x27\x94\xdd\x56\x95\x3d\x4d\xf4\x7c\xa6\x3f\x2f\xec\xd6\x22\xec\x69\xb2\xe7\xb3\x2d\x73\x2f\xde\xf6\x89\x94\x74\xc1\xb4\xa5\xfe\x58\x31\xd5\x2f\x5f\xcc\x33\xe5\x64\xae\xf8\x32\x3d\x98\x4b\x83\xc5\xc1\x5c\xbe\xb9\x1b\xf6\x4b\x72\x75\xa4\x38\x7a\x00\x66\xbe\x4e\x1f\x80\x99\xf1\xe2\xd3\xb6\x1c\x74\x7d\xd8\xd8\x06\x1b\xd7\x83\x8d\x9b\xc2\x86\x36\xd8\xb0\x1e\x6c\xd8\x14\xe6\xda\x60\x6e\x3d\x98\xdb\x14\x76\x63\x83\xdd\xd4\x83\xdd\x34\x85\xf5\x6c\xb0\x5e\x3d\x58\xaf\x29\x6c\x6b\x83\x6d\xeb\xc1\xb6\x4d\x61\x6f\x36\xd8\x5b\x3d\xd8\x5b\x53\xd8\xe3\xa3\x8d\x66\xac\xd7\x71\x8f\x8f\x4d\x79\x4f\x4f\x36\x9e\xb1\x5e\xe7\x3d\x3d\x35\xe5\x4d\x6c\xb8\x49\x3d\xda\xa4\xf9\xd4\x6e\xa3\x19\xeb\x75\x5c\x36\xde\x37\x18\xe0\xc3\x70\xec\x6d\xc6\x9c\x21\x2c\xa9\x54\xe4\xbd\x3a\xb8\x93\xbf\x7c\x9e\x32\xd5\x77\xc8\xe0\xf5\xe4\x26\x5e\x5a\x1a\xdf\xbd\x9e\xde\xb3\x79\x18\xfe\xba\xb9\xb3\xdc\xb1\xf7\x8f\x35\x3d\x63\x12\x2f\xde\x80\xfe\xb2\xcb\x02\x0c\x40\x71\xd0\xc3\x68\xe6\x75\x7c\x97\x8d\xe6\x0c\x28\x0b\x70\x5d\x2e\x07\x9c\xb0\x61\x0c\x19\xbd\xa8\x45\x39\xe4\x6a\xed\xaf\xe2\x25\xfd\x07\x79\x78\x95\x6f\xb6\x9d\x09\xe0\xb0\xf8\x7a\x4d\x0d\x99\xca\x84\xfa\x94\xa7\x7a\x94\x5e\xa4\xe6\x01\xcb\x45\x80\xe2\x44\x0a\xa9\x44\xc2\x65\xff\xd6\xbd\x1d\x81\x23\x07\xc7\x62\xe4\x8b\x8e\x1c\xc1\xad\x7b\x3b\xa8\x3c\x40\xc5\x42\xbe\x68\x9f\x97\xf4\xd8\xb7\x45\x56\x13\x9f\x0b\x81\xbe\x82\x88\x6c\xa4\x22\xfe\x3b\xe8\xef\x28\x0c\x31\x88\xf1\x34\xce\x52\xea\x7a\x06\xd9\x9f\x98\x99\xdd\xc5\x20\xb2\x0f\xf1\xa3\xeb\x47\x44\x74\x77\x23\x70\x3e\xba\xc3\xee\x6e\xf0\x50\xac\xd3\x6b\x1b\xae\x78\x48\x3d\xa9\xc4\x2c\x57\xff\xa3\x2b\x55\x65\xd3\xee\x7c\x3f\x58\xd3\xcf\xff\x4b\x91\x09\xa6\x2b\x20\x53\xef\xbb\xb6\x9f\x2f\x41\x22\x70\x31\xcb\x8f\xf5\x9d\xd9\x08\xb2\x5f\x4b\x30\x3f\x13\x87\x89\x41\x09\xbd\xf1\xb2\x0a\xba\x10\xf9\xa1\xb2\x02\xb6\xc8\xce\x56\xbb\xb2\xb9\xdb\xfd\x5c\x35\x03\x8c\xe9\x92\xea\x8e\xad\x95\x07\xae\x93\x98\x07\x39\xde\x16\xe7\xae\xdd\xfa\x37\x00\x00\xff\xff\x01\xc2\xb1\x40\x53\x13\x00\x00")
+var _embeddedrulesRulesPhp = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x98\xdb\x6e\xe3\x36\x13\xc7\xef\xfd\x14\x63\x43\xeb\xd8\x5e\xdb\xfa\x16\xdf\x5d\x8e\xdb\xde\x15\x58\x34\xc0\x16\x7b\x55\x24\x36\x25\x8d\x2c\x6e\x24\x52\x25\xa9\xc4\x6a\x94\x77\x2f\x48\x49\xb1\xac\x83\x2d\xa5\x0d\x10\xc3\x1a\x91\xf3\xfb\xcf\x0c\x8f\xbe\xbe\x8b\x83\x78\x34\xb2\x17\x8b\x11\x2c\xe0\x2b\xe3\x94\xc9\x18\x5d\x45\x39\x83\x5f\xbe\x7d\x33\xc6\x90\x32\x85\x02\xf2\x3f\x8f\x4a\xe2\x84\x38\x82\x85\x7d\xe8\xe6\xf2\x28\x42\xa6\xe0\x3b\xc6\x5c\x28\x50\x28\x18\x11\x29\xe0\x3e\x16\x28\x25\xe5\x4c\x82\x0a\x88\x02\x97\x30\x70\x10\x24\x8d\xe2\x90\xfa\x14\xbd\xb5\xe9\xee\xa0\xcf\x05\x02\x58\x7b\xb8\xd3\x1f\x97\x60\xa5\xe6\x05\xf1\x73\xb0\x7e\x51\x18\xed\x91\x9f\xb0\x5c\x5f\x81\xf9\x23\xf7\x96\xce\xe6\xf0\x3a\x02\x30\x9a\x40\xf7\x8e\x48\xea\x20\xb8\x3c\x09\x3d\x10\x18\x87\xc4\x45\x50\x01\xbe\xcb\x7b\xa1\x2a\x80\x9f\x89\x54\x60\xb9\x9c\x79\x45\x2f\x95\xc6\x08\x0e\xe7\x61\xc5\x6a\x8f\x20\x7f\x82\x3b\x50\x22\x41\xb8\x04\x9f\x84\x12\xaf\x46\x27\x80\x2f\x82\x2a\x04\x22\x61\x3b\xd3\xee\xe6\xc6\xc1\xb6\x4a\x81\xf1\x7f\xcb\x29\xd3\x54\x42\x7c\xba\xaf\xa4\xce\x98\xe2\x44\x20\x58\xfb\x03\xad\x92\xf2\x01\x94\xbb\x16\xca\x5d\x49\xd1\x7e\xa9\x94\xa8\x66\xd6\x7e\x5e\x75\xff\xd6\x39\x62\x62\xae\x90\x29\x4a\x42\xe0\x31\x0a\x62\xca\x1b\x0b\x74\xd1\x43\xe6\xa2\xf6\x96\xa0\x6c\x0c\x96\x29\x58\x11\x91\x4f\x70\x73\x03\xff\xbb\x02\xdb\xd6\x5f\x02\x22\x21\xa0\xbb\x00\x45\xd5\x81\x0a\x08\x83\xe9\xd1\x98\x9a\x1d\x1c\xcc\x8d\x87\xe3\xc1\x75\xe8\x5c\x8e\x2b\x1b\x7e\xe7\x0a\x2f\xe1\x05\xf5\x68\xd2\xaa\xb7\x15\x0d\xe3\x1b\x9d\x12\x9d\x20\xd2\x50\x0e\xf8\x8c\x2c\x77\x41\x7d\xa0\xef\xf3\xc0\x25\xc9\x2e\x50\xf9\x38\xdc\xea\x11\xe1\x06\xe8\x3e\xdd\xc7\xdb\x62\xb6\xe8\x27\x09\x0e\x57\x41\x9e\x16\x33\x4a\x6c\x1b\x74\x53\x09\x66\x54\x01\x95\xc0\xb8\x02\x02\x3b\xce\xbd\xb2\x19\xf8\x5c\x80\x43\xd5\x0b\x95\x78\xc8\xe8\x7c\x6d\xba\xe7\x3e\xf2\xc4\x53\xb6\x83\x2d\x65\xcf\x24\xa4\x5e\xee\x76\xa9\x67\x2d\xba\x0a\x3d\x60\x49\xe4\xa0\x00\x9f\x27\xcc\x33\x33\x62\x0b\x54\xe6\xbd\x35\xd2\x68\x0c\x30\x8c\xfd\x24\x5c\x82\x83\x2e\x49\x64\x3e\xc1\x04\xe7\x0a\xb8\x6f\xbe\xc7\x82\x3b\x21\x46\x5a\xe7\x21\x2d\xb9\x10\xf8\xad\x0a\x06\x22\x10\x08\x08\x94\x49\x58\xf4\x26\x6a\x5d\x0c\x49\xf8\xfa\x42\x04\xd3\x6a\xcf\x94\x38\x1f\x7d\x84\xa5\x1b\xfc\x6b\xe3\x50\x45\x98\x77\x69\xca\x07\x60\x6d\x74\x67\x6b\xa3\x4b\xb6\xb9\x2a\x4d\xd3\x77\xbb\x36\xbd\xd5\x71\xe3\xbe\x38\xd6\xc6\x1b\x77\xf0\xc6\x9d\xbc\x9b\x01\xf1\xfd\xbf\x2d\xc0\xce\x08\x4f\x84\x38\x20\xc6\x16\xe6\xb8\x8b\x39\xae\x30\x87\x95\x31\xab\x97\x91\x8b\x46\x15\xb3\x2a\x2f\xfb\x37\x55\xcc\x1a\x55\x3c\xc2\x8d\x3b\x70\x1f\x2e\x62\xd6\x28\x62\x2d\xbc\xce\xf8\x3e\x5a\xc3\xac\x59\xc3\x5a\x88\x9d\x31\x1e\x90\xdd\xab\x37\x91\x92\xee\x98\xb6\xf4\xde\xe7\x6f\xf4\xc7\x67\xb3\x2b\xd4\x36\xfa\xcf\x37\x85\xb5\xb2\x18\xe7\x80\xfb\xf8\xcc\x16\x7f\xb4\x47\x19\x3f\xb5\x3d\xca\xd8\xba\x77\xc2\x8a\xa8\xbe\x94\x55\x0b\x65\xd5\x83\xb2\x1a\x44\x59\xb4\x50\x16\x3d\x28\x8b\x41\x14\xbb\x85\x62\xf7\xa0\xd8\x83\x28\x9f\x5a\x28\x9f\x7a\x50\x3e\x0d\xa2\x4c\x5b\x28\xd3\x1e\x94\xe9\x20\x4a\xd6\x42\xc9\x7a\x50\xb2\x41\x94\xc7\x16\xca\x63\x0f\xca\xe3\x20\xca\xf5\x75\x0b\x26\x37\x9e\xe1\x5c\x5f\x0f\x02\xdd\xde\xb6\x80\x72\xe3\x19\xd0\xed\xed\x20\xd0\xba\x85\xb3\xee\x81\x59\x0f\x3c\x0b\xb7\x60\x72\xe3\x19\x8e\x39\x31\xf7\x3c\x15\xfb\xfe\xca\x49\x57\x9c\x21\x44\x54\x2a\xf2\xd4\x38\x0d\x93\x3f\x5d\x9e\x30\x35\xb3\xc8\xfc\xe1\x78\x49\xad\xbc\x59\x7d\x79\x38\x5e\x58\xb9\xef\xff\x9a\x7e\x69\x2c\xab\xe5\xb6\xa2\x0f\x6f\xc4\x09\x53\xd0\x37\x40\xe6\xa1\x07\x8a\x83\x3e\xe5\x19\x8f\xab\x2f\xe6\xb8\xcb\x80\x32\x0f\xf7\x95\x04\x40\x0d\x0b\x2b\xd0\xe0\x32\xfc\xaa\xd4\x5a\x9e\xcf\x82\x25\xfd\x1b\xb9\x7f\x8e\x9c\xb7\x6a\x45\x1f\x5e\x3d\x9c\x4a\xbd\x4c\x64\x4c\x5d\xca\x13\x7d\x2e\xdd\x25\xf9\xde\xc6\x85\x87\xe2\x38\xef\x52\x89\x98\xcb\xd9\x85\x7d\xb1\x04\x4b\xce\x8f\x32\x5f\xbc\xb3\xe4\x12\x2e\xec\x8b\x79\x6d\x4b\x13\x3b\x79\xaf\xfd\x75\x27\xbf\xac\xbe\x49\x83\xcb\x85\x40\x57\x41\x40\x52\xa9\x88\xfb\x04\xfa\x98\xcf\x10\xbd\x10\xeb\x0a\xdf\xc3\xd5\xfb\x7d\xd9\x7e\x93\xb7\x2d\x37\xfd\x52\xdb\xeb\xc4\x0d\x88\x98\xbc\x2d\xc1\x7a\x9d\x2c\x26\x6f\xf3\xab\xf2\x35\x3d\xf3\xfe\x74\xff\xc4\x91\x4a\x6c\x8a\x3a\xbf\x4e\xa4\xaa\xb7\x79\xeb\x28\x7c\x6b\xd0\xc5\xed\xdd\x14\x48\xc7\x2d\x13\xe7\xa7\xb6\x77\x05\x1e\x0b\xdc\x6d\x8a\x4e\x33\x6b\xb3\x04\xf3\xdf\x94\x31\x5c\x42\x8e\x57\x42\x37\x3c\x95\x76\x1d\x7d\xd1\xa5\x92\xf2\x36\x4d\x5d\xf9\x6d\xb4\x9d\x4c\x3e\x9e\x40\x0f\x43\x1a\x51\x3d\x2c\x7b\xe8\xc7\x7d\x1c\x72\xaf\x00\xb7\x08\xec\x35\x6b\x12\x49\x76\xa8\xaf\x71\x8d\x6b\x68\x6d\xe5\xa2\x3e\xcc\x2c\x2a\x7f\x7c\xff\xa6\x37\xdf\x67\x14\xd4\x4f\xe7\xb0\x5e\xaf\x8f\xe6\x52\xb5\x55\xa3\x59\x65\x5a\x15\xb4\xfb\x58\x76\xce\xab\x1f\x12\x3d\x98\xd6\x74\x71\x01\xfc\x19\x45\xfe\xc3\x4f\x71\x8b\x96\x4b\x88\x51\x04\x24\x96\x9a\x49\xe5\xfb\x62\x74\x57\x3b\x57\x4c\x0f\x6b\x7d\xe5\xd7\xa3\x7d\xd3\x94\x56\xf7\x80\x96\xa3\xc6\x91\xc4\x6c\x98\xc4\x2c\x3b\x21\x31\xcb\x3e\x24\xb1\xf3\x9c\x62\x04\x36\xe5\x31\x90\x3c\x42\x15\xe8\x18\xcc\x45\x20\x22\xa9\xf9\xad\xc0\xd1\x57\x7b\x96\x44\x28\xa8\x6b\xae\xfb\x55\xf0\x78\x46\x99\xca\xfc\x90\x13\x35\xaf\x69\x3a\x7e\x95\x56\xa7\xd8\xfb\xf5\xa5\xcc\x64\xf1\x90\x55\x1f\x1e\x8b\x07\x7d\x7b\xf9\x27\x00\x00\xff\xff\x61\x31\xe5\x35\xeb\x14\x00\x00")
 
 func embeddedrulesRulesPhpBytes() ([]byte, error) {
 	return bindataRead(
@@ -193,8 +193,8 @@ type bintree struct {
 }
 
 var _bintree = &bintree{nil, map[string]*bintree{
-	"embeddedrules": {nil, map[string]*bintree{
-		"rules.php": {embeddedrulesRulesPhp, map[string]*bintree{}},
+	"embeddedrules": &bintree{nil, map[string]*bintree{
+		"rules.php": &bintree{embeddedrulesRulesPhp, map[string]*bintree{}},
 	}},
 }}
 
diff --git a/src/cmd/embeddedrules/rules.php b/src/cmd/embeddedrules/rules.php
index 38b90bf..5bee397 100644
--- a/src/cmd/embeddedrules/rules.php
+++ b/src/cmd/embeddedrules/rules.php
@@ -238,3 +238,37 @@ function argsOrder() {
    */
   explode($_, ${"char"}, ${"*"});
 }
+
+/**
+ * @comment Report suspicious usage of bitwise operations.
+ * @before  if ($isURL & $verify) ...
+ * @after   if ($isURL && $verify) ...
+ */
+function bitwiseOps() {
+  /**
+   * @warning Used & bitwise operator over bool operands, perhaps && is intended?
+   * @fix $x && $y
+   * @type bool $x
+   * @type bool $y
+   */
+  $x & $y;
+
+  /**
+   * @warning Used | bitwise operator over bool operands, perhaps || is intended?
+   * @fix $x || $y
+   * @type bool $x
+   * @type bool $y
+   */
+  $x | $y;
+
+  /**
+   * @maybe Used bitwise operator on something that may not be a numeric type
+   * @type !(int|float) $x
+   * @type !(int|float) $y
+   */
+  any: {
+    $x & $y;
+    $x | $y;
+    $x ^ $y;
+  }
+}
diff --git a/src/linter/block_linter.go b/src/linter/block_linter.go
index 7d6aad8..e376d66 100644
--- a/src/linter/block_linter.go
+++ b/src/linter/block_linter.go
@@ -191,19 +191,8 @@ func (b *blockLinter) checkTryStmt(s *ir.TryStmt) {
 }
 
 func (b *blockLinter) checkBitwiseOp(n, left, right ir.Node) {
-	tok := "|"
-	if _, ok := n.(*ir.BitwiseAndExpr); ok {
-		tok = "&"
-	}
-
 	b.checkBinaryDupArgs(n, left, right)
 	b.checkBinaryVoidType(left, right)
-
-	if b.walker.exprType(left).Is("bool") && b.walker.exprType(right).Is("bool") {
-		b.report(n, LevelWarning, "bitwiseOps",
-			"Used %s bitwise op over bool operands, perhaps %s is intended?", tok, tok+tok)
-		return
-	}
 }
 
 func (b *blockLinter) checkBinaryVoidType(left, right ir.Node) {
diff --git a/src/linter/report.go b/src/linter/report.go
index 6e7264b..fbf1209 100644
--- a/src/linter/report.go
+++ b/src/linter/report.go
@@ -92,15 +92,6 @@ func init() {
 			After:    `if ($foo instanceof ArrayAccess) { return $foo[0]; }`,
 		},
 
-		{
-			Name:     "bitwiseOps",
-			Default:  true,
-			Quickfix: false,
-			Comment:  `Report suspicious usage of bitwise operations.`,
-			Before:   `if ($isURL & $verify) ...`,
-			After:    `if ($isURL && $veriry) ...`,
-		},
-
 		{
 			Name:     "mixedArrayKeys",
 			Default:  true,


Test patch:
diff --git a/src/tests/checkers/basic_test.go b/src/tests/checkers/basic_test.go
index 0c9db7a..ee1b263 100644
--- a/src/tests/checkers/basic_test.go
+++ b/src/tests/checkers/basic_test.go
@@ -686,20 +686,6 @@ function lhs($x, $mask) {
 `)
 }
 
-func TestBitwiseOps(t *testing.T) {
-	test := linttest.NewSuite(t)
-	test.AddFile(`<?php
-$x = 10;
-$_ = ($x > 0 & $x != 15);
-$_ = ($x == 1 | $x == 2);
-`)
-	test.Expect = []string{
-		`Used & bitwise op over bool operands, perhaps && is intended?`,
-		`Used | bitwise op over bool operands, perhaps || is intended?`,
-	}
-	test.RunAndMatch()
-}
-
 func TestArgvGlobal(t *testing.T) {
 	test := linttest.NewSuite(t)
 
diff --git a/src/tests/golden/testdata/embeddedrules/bitwiseOps.php b/src/tests/golden/testdata/embeddedrules/bitwiseOps.php
new file mode 100644
index 0000000..569afe0
--- /dev/null
+++ b/src/tests/golden/testdata/embeddedrules/bitwiseOps.php
@@ -0,0 +1,39 @@
+<?php
+
+class BitwiseExample1 {}
+class BitwiseExample2 {}
+
+function andor_bool_bad() {
+  $x = 10;
+  $_ = (($x > 0) & ($x != 15)); // Bad 1
+  $_ = (($x == 1) | ($x == 2)); // Bad 2
+}
+
+function andor_bool_good() {
+  $x = 10;
+  $_ = (($x > 0) && ($x != 15));
+  $_ = (($x == 1) || ($x == 2));
+
+  $_ = $x & 10;
+  $_ = 10 & $x;
+  $_ = $x | 10;
+  $_ = 10 | $x;
+}
+
+function bitwise_non_number(string $s1, string $s2, array $a) {
+  $_ = $s1 & $s2; // Bad 1
+  $_ = $a | $s1;  // Bad 2
+  $_ = $s2 ^ [];  // Bad 3
+
+  $obj1 = new BitwiseExample1();
+  $obj2 = new BitwiseExample2();
+  return $obj1 & $obj2;
+}
+
+/**
+ * @param int|float $x
+ * @param float|int $y
+ */
+function bitwise_number($x, $y) {
+  $_ = $x ^ $y;
+}
diff --git a/src/tests/golden/testdata/embeddedrules/golden.txt b/src/tests/golden/testdata/embeddedrules/golden.txt
index 072e667..816c4f3 100644
--- a/src/tests/golden/testdata/embeddedrules/golden.txt
+++ b/src/tests/golden/testdata/embeddedrules/golden.txt
@@ -58,6 +58,24 @@ MAYBE   assignOp: could rewrite as `$a >>= $b` at testdata/embeddedrules/assignO
 MAYBE   assignOp: could rewrite as `$a ??= $b` at testdata/embeddedrules/assignOp.php:83
   $a = $a ?? $b; // Could rewrite
   ^^^^^^^^^^^^^
+WARNING bitwiseOps: Used & bitwise operator over bool operands, perhaps && is intended? at testdata/embeddedrules/bitwiseOps.php:8
+  $_ = (($x > 0) & ($x != 15)); // Bad 1
+        ^^^^^^^^^^^^^^^^^^^^^
+WARNING bitwiseOps: Used | bitwise operator over bool operands, perhaps || is intended? at testdata/embeddedrules/bitwiseOps.php:9
+  $_ = (($x == 1) | ($x == 2)); // Bad 2
+        ^^^^^^^^^^^^^^^^^^^^^
+MAYBE   bitwiseOps: Used bitwise operator on something that may not be a numeric type at testdata/embeddedrules/bitwiseOps.php:24
+  $_ = $s1 & $s2; // Bad 1
+       ^^^^^^^^^
+MAYBE   bitwiseOps: Used bitwise operator on something that may not be a numeric type at testdata/embeddedrules/bitwiseOps.php:25
+  $_ = $a | $s1;  // Bad 2
+       ^^^^^^^^
+MAYBE   bitwiseOps: Used bitwise operator on something that may not be a numeric type at testdata/embeddedrules/bitwiseOps.php:26
+  $_ = $s2 ^ [];  // Bad 3
+       ^^^^^^^^
+MAYBE   bitwiseOps: Used bitwise operator on something that may not be a numeric type at testdata/embeddedrules/bitwiseOps.php:30
+  return $obj1 & $obj2;
+         ^^^^^^^^^^^^^
 WARNING offBy1: probably intended to use count-1 as an index at testdata/embeddedrules/offBy1.php:7
   $_ = $xs[count($xs)];
        ^^^^^^^^^^^^^^^
diff --git a/src/tests/golden/testdata/math/golden.txt b/src/tests/golden/testdata/math/golden.txt
index 2e71052..6397f91 100644
--- a/src/tests/golden/testdata/math/golden.txt
+++ b/src/tests/golden/testdata/math/golden.txt
@@ -4,6 +4,18 @@ INFO    unused: Variable a is unused (use $_ to ignore this inspection) at testd
 MAYBE   ternarySimplify: could rewrite as `$matches['fractional'] ?? ''` at testdata/math/src/BigNumber.php:90
             $fractional = isset($matches['fractional']) ? $matches['fractional'] : '';
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+MAYBE   bitwiseOps: Used bitwise operator on something that may not be a numeric type at testdata/math/src/Internal/Calculator.php:584
+                $value = $aBin & $bBin;
+                         ^^^^^^^^^^^^^
+MAYBE   bitwiseOps: Used bitwise operator on something that may not be a numeric type at testdata/math/src/Internal/Calculator.php:589
+                $value = $aBin | $bBin;
+                         ^^^^^^^^^^^^^
+MAYBE   bitwiseOps: Used bitwise operator on something that may not be a numeric type at testdata/math/src/Internal/Calculator.php:594
+                $value = $aBin ^ $bBin;
+                         ^^^^^^^^^^^^^
+MAYBE   bitwiseOps: Used bitwise operator on something that may not be a numeric type at testdata/math/src/Internal/Calculator.php:622
+        $number = $number ^ $xor;
+                  ^^^^^^^^^^^^^^
 MAYBE   assignOp: could rewrite as `$number ^= $xor` at testdata/math/src/Internal/Calculator.php:622
         $number = $number ^ $xor;
         ^^^^^^^^^^^^^^^^^^^^^^^^