Class: Pluginscan::VariableSafetyChecker

Inherits:
Object
  • Object
show all
Defined in:
lib/pluginscan/reports/issues_report/issue_checks/variable_safety_checker.rb

Overview

Responsible for deciding whether usages of a variable in a string are safe

Constant Summary collapse

SAFE_FUNCTIONS =

Functions which, if they surround the variable, make it safe because they return a boolean and not the value of the varaible

[
  "isset",
  "empty",
  "in_array",
  "strpos",
  "strlen",
  "if",
  "switch",
  "is_email",

  # PHP typechecks - seen in the wild:
  "is_array",

  # PHP typechecks - not seen in the wild:
  "is_bool",
  "is_callable",
  "is_double",
  "is_float",
  "is_int",
  "is_integer",
  "is_long",
  "is_null",
  "is_numeric",
  "is_object",
  "is_real",
  "is_resource",
  "is_scalar",
  "is_string",

  "intval",
  "absint",
  "wp_verify_nonce",
  "count",
  "sizeof",
  "unset",

  # Candidates for inclusion - not seen in the wild:
  # "gettype",
  # "settype",
  # "boolval",
  # "doubleval", # might match eval?
  # "floatval",
].freeze
SAFE_INFIXES =

Infixes which, if they are used around the variable, make it safe, because they are checking the value, not returning it

[
  '==',
  '===',
  '!=',
  '!==',
  '<',
  '>',
  '<=',
  '>=',
].freeze
INFIX_CHARS =
%w(= < > !).freeze

Instance Method Summary collapse

Instance Method Details

#all_safe?(variable, content) ⇒ Boolean

Returns:

  • (Boolean)


65
66
67
# File 'lib/pluginscan/reports/issues_report/issue_checks/variable_safety_checker.rb', line 65

def all_safe?(variable, content)
  match_count(variable, content) <= safe_count(variable, content)
end

#match_count(variable, content) ⇒ Object



69
70
71
# File 'lib/pluginscan/reports/issues_report/issue_checks/variable_safety_checker.rb', line 69

def match_count(variable, content)
  content.scan(variable).count # `scan` returns ALL matches
end

#safe_count(variable, content) ⇒ Object



73
74
75
76
# File 'lib/pluginscan/reports/issues_report/issue_checks/variable_safety_checker.rb', line 73

def safe_count(variable, content)
  safe_function_count(variable, content) +
    safe_infix_count(variable, content)
end

#used_in_infix_check_count(infix, variable, content) ⇒ Object

TODO: the below methods feel private, but are directly tested

That makes me feel like there's an object to be extracted here


96
97
98
99
100
101
102
103
104
105
# File 'lib/pluginscan/reports/issues_report/issue_checks/variable_safety_checker.rb', line 96

def used_in_infix_check_count(infix, variable, content)
  variable = Regexp.escape variable
  infix    = Regexp.escape infix
  non_infix = "[^#{Regexp.escape INFIX_CHARS.join}]"

  equals_before_regexp = /#{non_infix}#{infix}\ *#{variable}\ *\[/
  equals_after_regexp  = /#{variable}\ *\[[^\[]+\]\ *#{infix}#{non_infix}/
  content.scan(equals_before_regexp).count +
    content.scan(equals_after_regexp).count
end

#wrapped_in_function_count(function_name, variable, content) ⇒ Object



107
108
109
110
# File 'lib/pluginscan/reports/issues_report/issue_checks/variable_safety_checker.rb', line 107

def wrapped_in_function_count(function_name, variable, content)
  variable = Regexp.escape variable
  content.scan(/#{function_name}\ *\(\ *#{variable}[^)]*\)/).count
end